Skip to content

Commit

Permalink
stripe setup
Browse files Browse the repository at this point in the history
  • Loading branch information
ArslanKamchybekov committed Oct 12, 2024
1 parent 106531c commit 4353a86
Show file tree
Hide file tree
Showing 12 changed files with 414 additions and 13 deletions.
42 changes: 40 additions & 2 deletions backend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
},
"dependencies": {
"@nestjs/common": "^10.0.0",
"@nestjs/config": "^3.2.3",
"@nestjs/core": "^10.0.0",
"@nestjs/jwt": "^10.2.0",
"@nestjs/mapped-types": "github:nestjs/mapped-types",
Expand All @@ -39,7 +40,8 @@
"nodemon": "^3.1.4",
"passport-jwt": "^4.0.1",
"reflect-metadata": "^0.2.0",
"rxjs": "^7.8.1"
"rxjs": "^7.8.1",
"stripe": "^17.2.0"
},
"devDependencies": {
"@nestjs/cli": "^10.0.0",
Expand Down
5 changes: 2 additions & 3 deletions backend/src/app.module.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import { Module } from "@nestjs/common";
import { AuthController } from "./auth/auth.controller";
import { AuthService } from "./auth/auth.service";
import { InsuranceController } from "./insurance/insurance.controller";
import { InsuranceService } from "./insurance/insurance.service";
import { UserController } from "./user/user.controller";
import { UserService } from "./user/user.service";
import { ServiceController } from "./services/service.controller";
import { ServiceService } from "./services/service.service";
import { AuthModule } from "./auth/auth.module";
import { StripeModule } from './stripe/stripe.module';

@Module({
imports: [AuthModule],
imports: [AuthModule, StripeModule],
controllers: [InsuranceController, UserController, ServiceController],
providers: [InsuranceService, UserService, ServiceService],
})
Expand Down
18 changes: 18 additions & 0 deletions backend/src/stripe/stripe.controller.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Test, TestingModule } from '@nestjs/testing';
import { StripeController } from './stripe.controller';

describe('StripeController', () => {
let controller: StripeController;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [StripeController],
}).compile();

controller = module.get<StripeController>(StripeController);
});

it('should be defined', () => {
expect(controller).toBeDefined();
});
});
16 changes: 16 additions & 0 deletions backend/src/stripe/stripe.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Controller, Get } from '@nestjs/common';
import { StripeService } from './stripe.service';
import { Roles } from '../auth/roles.decorator';
import { Post, Param, Req } from '@nestjs/common';

@Controller('subscriptions')
export class StripeController {
constructor(private readonly stripeService: StripeService) {}

@Roles('user')
@Post('subscribe/:planId')
async subscribeToPlan(@Param('planId') planId: string, @Req() req) {
const userId = req.user.sub;
return this.stripeService.createSubscription(userId, planId);
}
}
24 changes: 24 additions & 0 deletions backend/src/stripe/stripe.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { DynamicModule, Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { StripeController } from './stripe.controller';
import { StripeService } from './stripe.service';

@Module({})
export class StripeModule {
static forRootAsync(): DynamicModule {
return {
module: StripeModule,
controllers: [StripeController],
imports: [ConfigModule.forRoot()],
providers: [
StripeService,
{
provide: 'STRIPE_API_KEY',
useFactory: async (configService: ConfigService) =>
configService.get('STRIPE_API_KEY'),
inject: [ConfigService],
},
],
};
}
}
18 changes: 18 additions & 0 deletions backend/src/stripe/stripe.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Test, TestingModule } from '@nestjs/testing';
import { StripeService } from './stripe.service';

describe('StripeService', () => {
let service: StripeService;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [StripeService],
}).compile();

service = module.get<StripeService>(StripeService);
});

it('should be defined', () => {
expect(service).toBeDefined();
});
});
79 changes: 79 additions & 0 deletions backend/src/stripe/stripe.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { Inject, Injectable } from '@nestjs/common';
import Stripe from 'stripe';
import { User } from 'src/user/user.schema';
import { InsurancePlan } from 'src/insurance/insurance.schema';

@Injectable()
export class StripeService {
private stripe: Stripe;

constructor(@Inject('STRIPE_API_KEY') private readonly apiKey: string) {
this.stripe = new Stripe(this.apiKey)
}

async createSubscription(userId: string, insuranceId: string) {
const insurance = await InsurancePlan.findById(insuranceId);

if (!insurance) {
throw new Error('Insurance not found');
}

const user = await User.findById(userId);

// Create a customer if user doesn't have a Stripe ID
if (!user.stripeCustomerId) {
const customer = await this.stripe.customers.create({ email: user.email, });
user.stripeCustomerId = customer.id;
}

const subscription = await this.stripe.subscriptions.create({
customer: user.stripeCustomerId,
items: [{ price_data: { unit_amount: insurance.monthlyPremium * 100, currency: 'usd', product: insurance.id, recurring: { interval: 'month' } } }],
});

return subscription;
}


// async createSubscription(userId: string, planId: string) {
// const customer = await this.getOrCreateStripeCustomer(userId);

// const priceId = await this.getPriceIdFromPlan(planId); // Get the Stripe price_id for the plan

// const subscription = await this.stripe.subscriptions.create({
// customer: customer.id,
// items: [{ price: priceId }],
// });

// return subscription;
// }

// // Helper function to get or create a Stripe customer for the user
// async getOrCreateStripeCustomer(userId: string) {
// // Query your database to see if the user already has a Stripe customerId
// const user = await User.findById(userId);
// if (user.stripeCustomerId !== null) {
// return await this.stripe.customers.retrieve(user.stripeCustomerId);
// }

// const customer = await this.stripe.customers.create({ email: user.email });

// // Save the customerId in your database
// await this.saveStripeCustomerId(userId, customer.id);

// return customer;
// }

// // Helper function to get Stripe price_id for the plan
// async getPriceIdFromPlan(planId: string) {
// const plan = await InsurancePlan.findById(planId);
// return plan.stripePriceId; // Assuming the Stripe priceId is saved with the insurance plan
// }

// // Helper function to save the Stripe customerId in your database
// async saveStripeCustomerId(userId: string, stripeCustomerId: string) {
// const user = await User.findByIdAndUpdate(userId, {stripeCustomerId: stripeCustomerId}, {new: true});
// return user;
// }
}

3 changes: 2 additions & 1 deletion backend/src/user/user.schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ export interface IUser extends Document {
email: string;
password: string;
role: string;
stripeCustomerId?: string;
savedInsurancePlans: IInsurancePlan['_id'][];
savedServices: IService['_id'][];
language: string;
comparePassword(candidatePassword: string): Promise<boolean>;
SignAccessToken: () => string;
SignRefreshToken: () => string;
Expand All @@ -23,6 +23,7 @@ const UserSchema = new Schema<IUser>(
email: { type: String, required: true, unique: true },
password: { type: String, required: true },
role: { type: String, default: 'user' },
stripeCustomerId: { type: String, default: null },
savedInsurancePlans: [{ type: Schema.Types.ObjectId, ref: 'InsurancePlan' }],
savedServices: [{ type: Schema.Types.ObjectId, ref: 'Service' }],
},
Expand Down
Loading

0 comments on commit 4353a86

Please sign in to comment.