Skip to content
This repository has been archived by the owner on Apr 19, 2023. It is now read-only.

Commit

Permalink
✨ Add basic Stripe module
Browse files Browse the repository at this point in the history
  • Loading branch information
AnandChowdhary committed Oct 30, 2020
1 parent bed199b commit 62ee163
Show file tree
Hide file tree
Showing 6 changed files with 160 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { GroupsModule } from './modules/groups/groups.module';
import { MultiFactorAuthenticationModule } from './modules/multi-factor-authentication/multi-factor-authentication.module';
import { PrismaModule } from './modules/prisma/prisma.module';
import { SessionsModule } from './modules/sessions/sessions.module';
import { StripeModule } from './modules/stripe/stripe.module';
import { TasksModule } from './modules/tasks/tasks.module';
import { UsersModule } from './modules/users/users.module';

Expand All @@ -43,6 +44,7 @@ import { UsersModule } from './modules/users/users.module';
ApiKeysModule,
ApprovedSubnetsModule,
GeolocationModule,
StripeModule,
],
providers: [
{
Expand Down
4 changes: 4 additions & 0 deletions src/config/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,8 @@ export default () => ({
pass: process.env.EMAIL_PASSWORD,
},
},
payments: {
stripeApiKey: process.env.STRIPE_API_KEY,
stripeProductId: process.env.STRIPE_PRODUCT_ID,
},
});
35 changes: 35 additions & 0 deletions src/modules/stripe/stripe.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import {
Body,
Controller,
Get,
Param,
ParseIntPipe,
Patch,
} from '@nestjs/common';
import { Expose } from 'src/modules/prisma/prisma.interface';
import Stripe from 'stripe';
import { Scopes } from '../auth/scope.decorator';
import { UpdateBillingDto } from './stripe.dto';
import { StripeService } from './stripe.service';

@Controller('groups/:groupId/billing')
export class StripeController {
constructor(private stripeService: StripeService) {}

@Get()
@Scopes('group-{groupId}:read-billing')
async billingInfo(
@Param('groupId', ParseIntPipe) groupId: number,
): Promise<Expose<Stripe.Customer>> {
return this.stripeService.getCustomer(groupId);
}

@Patch()
@Scopes('group-{groupId}:write-billing')
async updateBillingInfo(
@Param('groupId', ParseIntPipe) groupId: number,
@Body() data: UpdateBillingDto,
): Promise<Expose<Stripe.Customer>> {
return this.stripeService.updateCustomer(groupId, data);
}
}
62 changes: 62 additions & 0 deletions src/modules/stripe/stripe.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import {
IsNotEmpty,
IsObject,
IsOptional,
IsString,
Length,
ValidateNested,
} from 'class-validator';

class Address {
@IsString()
@IsNotEmpty()
line1: string;

@IsString()
@IsOptional()
city?: string;

@IsString()
@IsOptional()
@Length(2)
country?: string;

@IsString()
@IsOptional()
line2?: string;

@IsString()
@IsOptional()
postal_code?: string;

@IsString()
@IsOptional()
state?: string;
}

export class UpdateBillingDto {
@IsString()
@IsOptional()
default_source?: string;

@IsString()
@IsOptional()
email?: string;

@IsString()
@IsOptional()
name?: string;

@IsString()
@IsOptional()
phone?: string;

@IsString()
@IsOptional()
promotion_code?: string;

@IsObject()
@ValidateNested()
@IsOptional()
address?: Address;
}
11 changes: 11 additions & 0 deletions src/modules/stripe/stripe.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { PrismaModule } from '../prisma/prisma.module';
import { StripeService } from './stripe.service';

@Module({
imports: [ConfigModule, PrismaModule],
providers: [StripeService],
exports: [StripeService],
})
export class StripeModule {}
46 changes: 46 additions & 0 deletions src/modules/stripe/stripe.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import {
BadRequestException,
Injectable,
NotFoundException,
} from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import Stripe from 'stripe';
import { PrismaService } from '../prisma/prisma.service';

@Injectable()
export class StripeService {
stripe = new Stripe(this.configService.get<string>('payments.stripeApiKey'), {
apiVersion: null,
});

constructor(
private configService: ConfigService,
private prisma: PrismaService,
) {}

async getCustomer(groupId: number) {
const stripeId = await this.stripeId(groupId);
const result = await this.stripe.customers.retrieve(stripeId);
if (result.deleted)
throw new NotFoundException('This customer has been deleted');
return result as Stripe.Response<Stripe.Customer>;
}

async updateCustomer(groupId: number, data: Stripe.CustomerUpdateParams) {
const stripeId = await this.stripeId(groupId);
const result = await this.stripe.customers.update(stripeId, data);
return result as Stripe.Response<Stripe.Customer>;
}

/** Get the Stripe customer ID from a group or throw an error */
private async stripeId(groupId: number): Promise<string> {
const team = await this.prisma.groups.findOne({
where: { id: groupId },
select: { attributes: true },
});
const attributes = team.attributes as { stripeCustomerId?: string };
if (!attributes?.stripeCustomerId)
throw new BadRequestException('Billing account is not set up');
return attributes.stripeCustomerId;
}
}

0 comments on commit 62ee163

Please sign in to comment.