Skip to content

Commit

Permalink
fix: Bump txn free for creating resources
Browse files Browse the repository at this point in the history
Signed-off-by: jay-dee7 <me@jsdp.dev>
  • Loading branch information
jay-dee7 committed Oct 23, 2024
1 parent 535ae12 commit a92bb6b
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 45 deletions.
119 changes: 75 additions & 44 deletions src/controllers/admin/subscriptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { SubscriptionService } from '../../services/admin/subscription.js';
import { stripeService } from '../../services/admin/stripe.js';
import type { UnsuccessfulResponseBody } from '../../types/shared.js';
import { validate } from '../validator/decorator.js';
import { MaxAllowedTrialPeriodDays } from '../../types/constants.js';

dotenv.config();

Expand Down Expand Up @@ -180,60 +181,90 @@ export class SubscriptionController {

@validate
async create(request: Request, response: Response) {
const stripe = response.locals.stripe as Stripe;
const body: SubscriptionCreateRequestBody = request.body;

const { price, successURL, cancelURL, quantity, idempotencyKey, trialPeriodDays } =
request.body satisfies SubscriptionCreateRequestBody;
try {
const session = await stripe.checkout.sessions.create(
{
mode: 'subscription',
customer: response.locals.customer.paymentProviderId,
line_items: [
{
price: price,
quantity: quantity || 1,
},
],
success_url: successURL,
cancel_url: cancelURL,
subscription_data: {
trial_settings: {
end_behavior: {
missing_payment_method: 'cancel',
},
},
trial_period_days: trialPeriodDays,
},
payment_method_collection: 'if_required',
},
{
idempotencyKey,
}
);

if (session.lastResponse?.statusCode !== StatusCodes.OK) {
return response.status(StatusCodes.BAD_GATEWAY).json({
error: 'Checkout session was not created',
} satisfies SubscriptionCreateUnsuccessfulResponseBody);
}
// ensure trials don't succeed 30 days (default)
if (!body.trialPeriodDays || body.trialPeriodDays > MaxAllowedTrialPeriodDays) {
body.trialPeriodDays = MaxAllowedTrialPeriodDays;
}

if (!session.url) {
return response.status(StatusCodes.BAD_GATEWAY).json({
error: 'Checkout session URL was not provided',
} satisfies SubscriptionCreateUnsuccessfulResponseBody);
try {
if (body.trialMode) {
return await this.startTrialForPlan(response, body);
} else {
return await this.createCheckoutSession(response, body);
}

return response.json({
sessionURL: session.url as string,
} satisfies SubscriptionCreateResponseBody);
} catch (error) {
return response.status(StatusCodes.INTERNAL_SERVER_ERROR).json({
error: `Internal error: ${(error as Error)?.message || error}`,
} satisfies SubscriptionCreateUnsuccessfulResponseBody);
}
}

async createCheckoutSession(response: Response, body: SubscriptionCreateRequestBody) {
const stripe = response.locals.stripe as Stripe;
const { price, quantity = 1, cancelURL, successURL, idempotencyKey, trialPeriodDays } = body;

const session = await stripe.checkout.sessions.create(
{
mode: 'subscription',
customer: response.locals.customer.paymentProviderId,
line_items: [{ price, quantity }],
success_url: successURL,
cancel_url: cancelURL,
subscription_data: {
trial_period_days: trialPeriodDays,
},
},
{ idempotencyKey }
);

if (session.lastResponse?.statusCode !== StatusCodes.OK) {
return response.status(StatusCodes.BAD_GATEWAY).json({
error: 'Checkout session was not created',
} satisfies SubscriptionCreateUnsuccessfulResponseBody);
}

if (!session.url) {
return response.status(StatusCodes.BAD_GATEWAY).json({
error: 'Checkout session URL was not provided',
} satisfies SubscriptionCreateUnsuccessfulResponseBody);
}

return response.json({
sessionURL: session.url as string,
} satisfies SubscriptionCreateResponseBody);
}

async startTrialForPlan(response: Response, body: SubscriptionCreateRequestBody): Promise<Response> {
const stripe = response.locals.stripe as Stripe;

const { price, quantity = 1, trialPeriodDays } = body;
const subscriptionResponse = await stripe.subscriptions.create({
customer: response.locals.customer.paymentProviderId,
items: [{ price: price, quantity: quantity }],
payment_settings: {
save_default_payment_method: 'on_subscription',
},
trial_period_days: trialPeriodDays,
trial_settings: {
end_behavior: {
missing_payment_method: 'cancel',
},
},
});

if (subscriptionResponse.lastResponse.statusCode !== StatusCodes.OK) {
return response.status(StatusCodes.BAD_GATEWAY).json({
error: 'Failed to start trial plan',
} satisfies SubscriptionCreateUnsuccessfulResponseBody);
}

return response.status(StatusCodes.OK).json({
sessionURL: '' as string,
} satisfies SubscriptionCreateResponseBody);
}

/**
* @openapi
*
Expand Down
6 changes: 5 additions & 1 deletion src/services/identity/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ import {
DefaultStatusList2021StatusPurposeType,
TransactionResult,
} from '@cheqd/did-provider-cheqd';
import type { CheqdNetwork } from '@cheqd/sdk';
import { ResourceModule, type CheqdNetwork } from '@cheqd/sdk';
import { getDidKeyResolver as KeyDidResolver } from '@veramo/did-provider-key';
import { Resolver, ResolverRegistry } from 'did-resolver';
import { DefaultDidUrlPattern, CreateAgentRequest, VeramoAgent } from '../../types/shared.js';
Expand Down Expand Up @@ -305,6 +305,10 @@ export class Veramo {
payload,
network: network as CheqdNetwork,
signInputs: publicKeyHexs,
fee: {
amount: [ResourceModule.fees.DefaultCreateResourceJsonFee],
gas: Number(2_050_000).toString(),
},
} satisfies ICheqdCreateLinkedResourceArgs);
return result;
} catch (error) {
Expand Down
1 change: 1 addition & 0 deletions src/types/admin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export type SubscriptionCreateRequestBody = {
quantity?: number;
trialPeriodDays?: number;
idempotencyKey?: string;
trialMode?: boolean;
};

export type SubscriptionCreateResponseBody = {
Expand Down
1 change: 1 addition & 0 deletions src/types/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,3 +151,4 @@ export const StatusList2021Entry = 'StatusList2021Entry';
export const JSONLD_PROOF_TYPES = ['Ed25519Signature2018', 'Ed25519Signature2020', 'JsonWebSignature2020'];
export const DEFAULT_PAGINATION_LIST_LIMIT = 10;
export const DefaultStudioRoleName = 'default' as const;
export const MaxAllowedTrialPeriodDays = 30;

0 comments on commit a92bb6b

Please sign in to comment.