From 7132b0cb679b4e4d4bd52fb6b690a75235658e92 Mon Sep 17 00:00:00 2001 From: Tiago Yamamoto Date: Mon, 15 Dec 2025 09:44:19 -0300 Subject: [PATCH] =?UTF-8?q?feat(stripe):=20=F0=9F=92=B3=20added=20Stripe?= =?UTF-8?q?=20integration=20for=20payments?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backoffice/src/stripe/index.ts | 2 + backoffice/src/stripe/stripe.module.ts | 11 +++++ backoffice/src/stripe/stripe.service.ts | 62 +++++++++++++++++++++++++ 3 files changed, 75 insertions(+) create mode 100644 backoffice/src/stripe/index.ts create mode 100644 backoffice/src/stripe/stripe.module.ts create mode 100644 backoffice/src/stripe/stripe.service.ts diff --git a/backoffice/src/stripe/index.ts b/backoffice/src/stripe/index.ts new file mode 100644 index 0000000..71f3586 --- /dev/null +++ b/backoffice/src/stripe/index.ts @@ -0,0 +1,2 @@ +export * from './stripe.module'; +export * from './stripe.service'; diff --git a/backoffice/src/stripe/stripe.module.ts b/backoffice/src/stripe/stripe.module.ts new file mode 100644 index 0000000..1376f19 --- /dev/null +++ b/backoffice/src/stripe/stripe.module.ts @@ -0,0 +1,11 @@ +import { Module, Global } from '@nestjs/common'; +import { ConfigModule } from '@nestjs/config'; +import { StripeService } from './stripe.service'; + +@Global() +@Module({ + imports: [ConfigModule], + providers: [StripeService], + exports: [StripeService], +}) +export class StripeModule { } diff --git a/backoffice/src/stripe/stripe.service.ts b/backoffice/src/stripe/stripe.service.ts new file mode 100644 index 0000000..3f822ff --- /dev/null +++ b/backoffice/src/stripe/stripe.service.ts @@ -0,0 +1,62 @@ +import { Injectable, OnModuleInit } from '@nestjs/common'; +import { ConfigService } from '@nestjs/config'; +import Stripe from 'stripe'; + +@Injectable() +export class StripeService implements OnModuleInit { + private stripe: Stripe; + + constructor(private configService: ConfigService) { } + + onModuleInit() { + const secretKey = this.configService.get('STRIPE_SECRET_KEY'); + if (!secretKey) { + console.warn('STRIPE_SECRET_KEY not configured'); + return; + } + this.stripe = new Stripe(secretKey, { apiVersion: '2024-11-20.acacia' }); + } + + getClient(): Stripe { return this.stripe; } + + async createCustomer(email: string, name: string) { + return this.stripe.customers.create({ email, name }); + } + + async createSubscription(customerId: string, priceId: string) { + return this.stripe.subscriptions.create({ + customer: customerId, + items: [{ price: priceId }], + payment_behavior: 'default_incomplete', + expand: ['latest_invoice.payment_intent'], + }); + } + + async cancelSubscription(subscriptionId: string) { + return this.stripe.subscriptions.cancel(subscriptionId); + } + + async listSubscriptions(customerId: string) { + return this.stripe.subscriptions.list({ customer: customerId, status: 'all' }); + } + + async createCheckoutSession(customerId: string, priceId: string, successUrl: string, cancelUrl: string) { + return this.stripe.checkout.sessions.create({ + customer: customerId, + payment_method_types: ['card'], + line_items: [{ price: priceId, quantity: 1 }], + mode: 'subscription', + success_url: successUrl, + cancel_url: cancelUrl, + }); + } + + async createBillingPortalSession(customerId: string, returnUrl: string) { + return this.stripe.billingPortal.sessions.create({ customer: customerId, return_url: returnUrl }); + } + + constructWebhookEvent(body: Buffer, signature: string): Stripe.Event { + const secret = this.configService.get('STRIPE_WEBHOOK_SECRET')!; + return this.stripe.webhooks.constructEvent(body, signature, secret); + } +}