Skip to content

Commit 0f88afe

Browse files
adding backend support for payment intents (#17309)
* adding support for payment intents * support payment intents in server * handling new arg * adjust hold to be 1.00 * removing old comment
1 parent ecfbfd3 commit 0f88afe

File tree

11 files changed

+756
-153
lines changed

11 files changed

+756
-153
lines changed

components/dashboard/src/components/UsageBasedBillingConfig.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ export default function UsageBasedBillingConfig({ attributionId, hideSubheading
140140
const newLimit = await getGitpodService().server.subscribeToStripe(
141141
attributionId,
142142
setupIntentId,
143+
"", // TODO: pass paymentIntentId
143144
limit,
144145
);
145146
if (newLimit) {

components/gitpod-protocol/src/gitpod-service.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,15 @@ export interface GitpodServer extends JsonRpcServer<GitpodClient>, AdminServer,
236236
findStripeSubscriptionId(attributionId: string): Promise<string | undefined>;
237237
getPriceInformation(attributionId: string): Promise<string | undefined>;
238238
createStripeCustomerIfNeeded(attributionId: string, currency: string): Promise<void>;
239-
subscribeToStripe(attributionId: string, setupIntentId: string, usageLimit: number): Promise<number | undefined>;
239+
createHoldPaymentIntent(
240+
attributionId: string,
241+
): Promise<{ paymentIntentId: string; paymentIntentClientSecret: string }>;
242+
subscribeToStripe(
243+
attributionId: string,
244+
setupIntentId: string,
245+
paymentIntentId: string,
246+
usageLimit: number,
247+
): Promise<number | undefined>;
240248
getStripePortalUrl(attributionId: string): Promise<string>;
241249
getCostCenter(attributionId: string): Promise<CostCenterJSON | undefined>;
242250
setUsageLimit(attributionId: string, usageLimit: number): Promise<void>;

components/server/ee/src/workspace/gitpod-server-impl.ts

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1099,10 +1099,41 @@ export class GitpodServerEEImpl extends GitpodServerImpl {
10991099
}
11001100
}
11011101

1102+
async createHoldPaymentIntent(
1103+
ctx: TraceContext,
1104+
attributionId: string,
1105+
): Promise<{ paymentIntentId: string; paymentIntentClientSecret: string }> {
1106+
this.checkAndBlockUser("createHoldPaymentIntent");
1107+
1108+
const attrId = AttributionId.parse(attributionId);
1109+
if (attrId === undefined) {
1110+
log.error(`Invalid attribution id`);
1111+
throw new ResponseError(ErrorCodes.BAD_REQUEST, `Invalid attibution id: ${attributionId}`);
1112+
}
1113+
1114+
try {
1115+
const response = await this.billingService.createHoldPaymentIntent({ attributionId: attributionId });
1116+
return {
1117+
paymentIntentId: response.paymentIntentId,
1118+
paymentIntentClientSecret: response.paymentIntentClientSecret,
1119+
};
1120+
} catch (error) {
1121+
log.error(`Failed to subscribe '${attributionId}' to Stripe`, error);
1122+
if (error instanceof ClientError) {
1123+
throw new ResponseError(error.code, error.details);
1124+
}
1125+
throw new ResponseError(
1126+
ErrorCodes.INTERNAL_SERVER_ERROR,
1127+
`Failed to subscribe '${attributionId}' to Stripe`,
1128+
);
1129+
}
1130+
}
1131+
11021132
async subscribeToStripe(
11031133
ctx: TraceContext,
11041134
attributionId: string,
11051135
setupIntentId: string,
1136+
paymentIntentId: string,
11061137
usageLimit: number,
11071138
): Promise<number | undefined> {
11081139
const user = this.checkAndBlockUser("subscribeToStripe");
@@ -1127,7 +1158,12 @@ export class GitpodServerEEImpl extends GitpodServerImpl {
11271158
throw new Error(`No Stripe customer profile for '${attributionId}'`);
11281159
}
11291160

1130-
await this.billingService.createStripeSubscription({ attributionId, setupIntentId, usageLimit });
1161+
await this.billingService.createStripeSubscription({
1162+
attributionId,
1163+
setupIntentId,
1164+
paymentIntentId,
1165+
usageLimit,
1166+
});
11311167

11321168
// Creating a cost center for this customer
11331169
const { costCenter } = await this.usageService.setCostCenter({

components/server/src/auth/rate-limiter.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ const defaultFunctions: FunctionsConfig = {
183183
getStripeSetupIntentClientSecret: { group: "default", points: 1 },
184184
findStripeSubscriptionId: { group: "default", points: 1 },
185185
createStripeCustomerIfNeeded: { group: "default", points: 1 },
186+
createHoldPaymentIntent: { group: "default", points: 1 },
186187
subscribeToStripe: { group: "default", points: 1 },
187188
getStripePortalUrl: { group: "default", points: 1 },
188189
getPriceInformation: { group: "default", points: 1 },

components/server/src/workspace/gitpod-server-impl.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3361,10 +3361,17 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
33613361
async createStripeCustomerIfNeeded(ctx: TraceContext, attributionId: string, currency: string): Promise<void> {
33623362
throw new ResponseError(ErrorCodes.SAAS_FEATURE, `Not implemented in this version`);
33633363
}
3364+
async createHoldPaymentIntent(
3365+
ctx: TraceContext,
3366+
attributionId: string,
3367+
): Promise<{ paymentIntentId: string; paymentIntentClientSecret: string }> {
3368+
throw new ResponseError(ErrorCodes.SAAS_FEATURE, `Not implemented in this version`);
3369+
}
33643370
async subscribeToStripe(
33653371
ctx: TraceContext,
33663372
attributionId: string,
33673373
setupIntentId: string,
3374+
paymentIntentId: string,
33683375
usageLimit: number,
33693376
): Promise<number | undefined> {
33703377
throw new ResponseError(ErrorCodes.SAAS_FEATURE, `Not implemented in this version`);

0 commit comments

Comments
 (0)