Refactor: extract link between session and purchase to stripe session control
parent
d4e8883304
commit
a92855396b
|
|
@ -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' };
|
||||
|
|
|
|||
|
|
@ -8,5 +8,4 @@ export class Purchase {
|
|||
purchasedProduct: PurchaseItem;
|
||||
purchasedUnits: number;
|
||||
status: PurchaseStatus;
|
||||
stripeSessionId?: string;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
export class StripeSession {
|
||||
sessionId: string;
|
||||
userId: number;
|
||||
purchaseId: number;
|
||||
}
|
||||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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<number, string> = 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<Stripe.Response<Stripe.Checkout.Session>> {
|
||||
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<Stripe.Response<Stripe.Checkout.Session>> {
|
||||
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,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue