diff --git a/src/controller/buy.controller.ts b/src/controller/buy.controller.ts index 0c4bfd7..860f74b 100644 --- a/src/controller/buy.controller.ts +++ b/src/controller/buy.controller.ts @@ -1,4 +1,4 @@ -import { Body, Controller, Get, Post, Redirect } from '@nestjs/common'; +import { Body, Controller, Get, Logger, Param, Post, Redirect } from '@nestjs/common'; import { PurchaseService } from '../service/purchase.service'; import { UserService } from '../service/user.service'; import { PurchaseItem } from '../dto/purchase-item'; @@ -7,6 +7,8 @@ import { PurchaseStatus } from 'src/dto/purchase-status'; @Controller('/buy') export class BuyController { + private readonly logger = new Logger(BuyController.name); + constructor( private readonly purchaseService: PurchaseService, private readonly userService: UserService, @@ -24,22 +26,21 @@ export class BuyController { PurchaseItem.PAELLA, quantity, ); - const session = await this.stripeService.createStripeSession( + const { sessionUrl } = await this.stripeService.createStripeSession( user, purchase, ); - this.purchaseService.attachStripeSessionToPurchase(session.id, purchase.id); - console.log(session); - return { url: session.url }; + this.logger.debug(`Redirecting to ${sessionUrl}`); + return { url: sessionUrl }; } @Post('/complete') public async complete(@Body('userId') userId: number) { const user = this.userService.getUserById(userId); - const session = await this.stripeService.getStripeSessionForCustomer(user); - const isPaid = session.payment_status == 'paid'; - this.purchaseService.findAndTransitionPurchaseStatus( - session.id, + const { isPaid, purchaseId } = + await this.stripeService.getStripeSessionForCustomer(user); + this.purchaseService.transitionPurchaseStatus( + purchaseId, isPaid ? PurchaseStatus.COMPLETED : PurchaseStatus.IN_PROGRESS, ); return { url: '/signup' }; diff --git a/src/dto/purchase.ts b/src/dto/purchase.ts index b9580da..60805e5 100644 --- a/src/dto/purchase.ts +++ b/src/dto/purchase.ts @@ -8,5 +8,4 @@ export class Purchase { purchasedProduct: PurchaseItem; purchasedUnits: number; status: PurchaseStatus; - stripeSessionId?: string; } diff --git a/src/dto/stripe-session.ts b/src/dto/stripe-session.ts new file mode 100644 index 0000000..bbaa089 --- /dev/null +++ b/src/dto/stripe-session.ts @@ -0,0 +1,5 @@ +export class StripeSession { + sessionId: string; + userId: number; + purchaseId: number; +} diff --git a/src/service/purchase.service.ts b/src/service/purchase.service.ts index b7381b0..413ae78 100644 --- a/src/service/purchase.service.ts +++ b/src/service/purchase.service.ts @@ -28,26 +28,12 @@ export class PurchaseService { return purchase; } - public attachStripeSessionToPurchase( - sessionId: string, + public transitionPurchaseStatus( purchaseId: number, - ): void { - const purchase = this.purchases.find( - (purchase) => purchase.id === purchaseId, - ); - if (!purchase) { - throw new NotFoundException(); - } - - purchase.stripeSessionId = sessionId; - } - - public findAndTransitionPurchaseStatus( - sessionId: string, purchaseStatus: PurchaseStatus, ) { const purchase = this.purchases.find( - (purchase) => purchase.stripeSessionId === sessionId, + (purchase) => purchase.id === purchaseId, ); if (!purchase) { throw new NotFoundException(); diff --git a/src/service/stripe.service.ts b/src/service/stripe.service.ts index c274d24..faab84d 100644 --- a/src/service/stripe.service.ts +++ b/src/service/stripe.service.ts @@ -2,22 +2,20 @@ import { Injectable, NotFoundException } from '@nestjs/common'; import { Purchase } from '../dto/purchase'; import Stripe from 'stripe'; import { User } from '../dto/user'; -import { NotFoundError } from 'rxjs'; +import { StripeSession } from 'src/dto/stripe-session'; @Injectable() export class StripeService { private readonly stripe: Stripe; - private readonly stripeSessions: Map = new Map(); + private readonly stripeSessions: StripeSession[] = []; constructor() { const stripePrivateKey = process.env.STRIPE_PRIVATE_KEY!; this.stripe = new Stripe(stripePrivateKey); } - public async createStripeSession( - user: User, - purchase: Purchase, - ): Promise> { + public async createStripeSession(user: User, purchase: Purchase) { + const redirectUrl = `http://localhost:5173/buy/return?purchaseId=${purchase.id}` const session = await this.stripe.checkout.sessions.create({ line_items: [ { @@ -26,21 +24,36 @@ export class StripeService { }, ], mode: 'payment', - success_url: 'http://localhost:5173/buy/return', - cancel_url: 'http://localhost:5173/buy/return', + success_url: redirectUrl, + cancel_url: redirectUrl, payment_method_types: ['card', 'paypal'], }); - this.stripeSessions.set(user.id, session.id); - return session; + const stripeSession: StripeSession = { + sessionId: session.id, + userId: user.id, + purchaseId: purchase.id, + }; + + this.stripeSessions.push(stripeSession); + return { + sessionUrl: session.url, + }; } - public getStripeSessionForCustomer( - user: User, - ): Promise> { - const sessionId = this.stripeSessions.get(user.id); - if (!sessionId) { + public async getStripeSessionForCustomer(user: User) { + const stripeSession = this.stripeSessions.find( + (session) => session.userId === user.id, + ); + if (!stripeSession) { throw new NotFoundException(); } - return this.stripe.checkout.sessions.retrieve(sessionId); + + const session = await this.stripe.checkout.sessions.retrieve( + stripeSession.sessionId, + ); + return { + isPaid: session.payment_status === 'paid', + purchaseId: stripeSession.purchaseId, + }; } }