Skip to content

Commit

Permalink
fix(server): avoid error when other prices added but logic is not rel…
Browse files Browse the repository at this point in the history
…eased
  • Loading branch information
forehalo committed Mar 19, 2024
1 parent 398d66f commit 695ddea
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 65 deletions.
89 changes: 30 additions & 59 deletions packages/backend/server/src/plugins/payment/resolver.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
import {
BadGatewayException,
ForbiddenException,
InternalServerErrorException,
} from '@nestjs/common';
import { BadGatewayException, ForbiddenException } from '@nestjs/common';
import {
Args,
Context,
Expand Down Expand Up @@ -48,11 +44,11 @@ class SubscriptionPrice {
@Field()
currency!: string;

@Field()
amount!: number;
@Field(() => Int, { nullable: true })
amount?: number | null;

@Field()
yearlyAmount!: number;
@Field(() => Int, { nullable: true })
yearlyAmount?: number | null;
}

@ObjectType('UserSubscription')
Expand Down Expand Up @@ -176,64 +172,39 @@ export class SubscriptionResolver {
}
);

return Object.entries(group).map(([plan, prices]) => {
const yearly = prices.find(
price =>
decodeLookupKey(
// @ts-expect-error empty lookup key is filtered out
price.lookup_key
)[1] === SubscriptionRecurring.Yearly
);
const monthly = prices.find(
price =>
decodeLookupKey(
// @ts-expect-error empty lookup key is filtered out
price.lookup_key
)[1] === SubscriptionRecurring.Monthly
);
function findPrice(plan: SubscriptionPlan) {
const prices = group[plan];

if (!yearly || !monthly) {
throw new InternalServerErrorException(
'The prices are not configured correctly.'
);
if (!prices) {
return null;
}

const monthlyPrice = prices.find(p => p.recurring?.interval === 'month');
const yearlyPrice = prices.find(p => p.recurring?.interval === 'year');
const currency = monthlyPrice?.currency ?? yearlyPrice?.currency ?? 'usd';
return {
type: 'fixed',
plan: plan as SubscriptionPlan,
currency: monthly.currency,
amount: monthly.unit_amount ?? 0,
yearlyAmount: yearly.unit_amount ?? 0,
currency,
amount: monthlyPrice?.unit_amount,
yearlyAmount: yearlyPrice?.unit_amount,
};
});
}
}

/**
* @deprecated
*/
@Mutation(() => String, {
deprecationReason: 'use `createCheckoutSession` instead',
description: 'Create a subscription checkout link of stripe',
})
async checkout(
@CurrentUser() user: CurrentUser,
@Args({ name: 'recurring', type: () => SubscriptionRecurring })
recurring: SubscriptionRecurring,
@Args('idempotencyKey') idempotencyKey: string
) {
const session = await this.service.createCheckoutSession({
user,
plan: SubscriptionPlan.Pro,
recurring,
redirectUrl: `${this.config.baseUrl}/upgrade-success`,
idempotencyKey,
});
// extend it when new plans are added
const fixedPlans = [SubscriptionPlan.Pro];

if (!session.url) {
throw new BadGatewayException('Failed to create checkout session.');
}
return fixedPlans.reduce((prices, plan) => {
const price = findPrice(plan);

return session.url;
if (price && (price.amount || price.yearlyAmount)) {
prices.push({
type: 'fixed',
plan,
...price,
});
}

return prices;
}, [] as SubscriptionPrice[]);
}

@Mutation(() => String, {
Expand Down
4 changes: 3 additions & 1 deletion packages/backend/server/src/plugins/payment/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,9 @@ export class SubscriptionService {
) {}

async listPrices() {
return this.stripe.prices.list();
return this.stripe.prices.list({
active: true,
});
}

async createCheckoutSession({
Expand Down
7 changes: 2 additions & 5 deletions packages/backend/server/src/schema.gql
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,6 @@ type Mutation {
changeEmail(email: String!, token: String!): UserType!
changePassword(newPassword: String!, token: String!): UserType!

"""Create a subscription checkout link of stripe"""
checkout(idempotencyKey: String!, recurring: SubscriptionRecurring!): String! @deprecated(reason: "use `createCheckoutSession` instead")

"""Create a subscription checkout link of stripe"""
createCheckoutSession(input: CreateCheckoutSessionInput!): String!

Expand Down Expand Up @@ -275,11 +272,11 @@ enum SubscriptionPlan {
}

type SubscriptionPrice {
amount: Int!
amount: Int
currency: String!
plan: SubscriptionPlan!
type: String!
yearlyAmount: Int!
yearlyAmount: Int
}

enum SubscriptionRecurring {
Expand Down
1 change: 1 addition & 0 deletions packages/frontend/graphql/src/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ export enum ServerFeature {
}

export enum SubscriptionPlan {
AI = 'AI',
Enterprise = 'Enterprise',
Free = 'Free',
Pro = 'Pro',
Expand Down

0 comments on commit 695ddea

Please sign in to comment.