Skip to content

Commit ad8d0ac

Browse files
committed
[server] Refactor StripeService.createCustomer to only use attributionIds
1 parent d3e5716 commit ad8d0ac

File tree

6 files changed

+25
-49
lines changed

6 files changed

+25
-49
lines changed

components/dashboard/src/components/UsageBasedBillingConfig.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ function CreditCardInputForm(props: { attributionId: string }) {
296296
setIsLoading(true);
297297
try {
298298
// Create Stripe customer with currency
299-
await getGitpodService().server.createStripeCustomer(props.attributionId, currency);
299+
await getGitpodService().server.createStripeCustomerIfNeeded(props.attributionId, currency);
300300
const result = await stripe.confirmSetup({
301301
elements,
302302
confirmParams: {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ export interface GitpodServer extends JsonRpcServer<GitpodClient>, AdminServer,
287287
getStripePublishableKey(): Promise<string>;
288288
getStripeSetupIntentClientSecret(): Promise<string>;
289289
findStripeSubscriptionId(attributionId: string): Promise<string | undefined>;
290-
createStripeCustomer(attributionId: string, currency: string): Promise<void>;
290+
createStripeCustomerIfNeeded(attributionId: string, currency: string): Promise<void>;
291291
subscribeToStripe(attributionId: string, setupIntentId: string): Promise<void>;
292292
getStripePortalUrl(attributionId: string): Promise<string>;
293293
getUsageLimit(attributionId: string): Promise<number | undefined>;

components/server/ee/src/user/stripe-service.ts

Lines changed: 11 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -43,55 +43,32 @@ export class StripeService {
4343
return result.data[0]?.id;
4444
}
4545

46-
async createCustomerForUser(user: User): Promise<string> {
47-
const attributionId = AttributionId.render({ kind: "user", userId: user.id });
46+
async createCustomerForAttributionId(
47+
attributionId: string,
48+
preferredCurrency: string,
49+
billingEmail?: string,
50+
billingName?: string,
51+
): Promise<string> {
4852
if (await this.findCustomerByAttributionId(attributionId)) {
49-
throw new Error(`A Stripe customer already exists for user '${user.id}'`);
53+
throw new Error(`A Stripe customer already exists for '${attributionId}'`);
5054
}
5155
// Create the customer in Stripe
5256
const customer = await this.getStripe().customers.create({
53-
email: User.getPrimaryEmail(user),
54-
name: User.getName(user),
55-
metadata: { attributionId },
57+
email: billingEmail,
58+
name: billingName,
59+
metadata: { attributionId, preferredCurrency },
5660
});
5761
// Wait for the customer to show up in Stripe search results before proceeding
5862
let attempts = 0;
5963
while (!(await this.findCustomerByAttributionId(attributionId))) {
6064
await new Promise((resolve) => setTimeout(resolve, POLL_CREATED_CUSTOMER_INTERVAL_MS));
6165
if (++attempts > POLL_CREATED_CUSTOMER_MAX_ATTEMPTS) {
62-
throw new Error(`Could not confirm Stripe customer creation for user '${user.id}'`);
66+
throw new Error(`Could not confirm Stripe customer creation for '${attributionId}'`);
6367
}
6468
}
6569
return customer.id;
6670
}
6771

68-
async createCustomerForTeam(user: User, team: Team): Promise<string> {
69-
const attributionId = AttributionId.render({ kind: "team", teamId: team.id });
70-
if (await this.findCustomerByAttributionId(attributionId)) {
71-
throw new Error(`A Stripe customer already exists for team '${team.id}'`);
72-
}
73-
// Create the customer in Stripe
74-
const userName = User.getName(user);
75-
const customer = await this.getStripe().customers.create({
76-
email: User.getPrimaryEmail(user),
77-
name: userName ? `${userName} (${team.name})` : team.name,
78-
metadata: { attributionId },
79-
});
80-
// Wait for the customer to show up in Stripe search results before proceeding
81-
let attempts = 0;
82-
while (!(await this.findCustomerByAttributionId(attributionId))) {
83-
await new Promise((resolve) => setTimeout(resolve, POLL_CREATED_CUSTOMER_INTERVAL_MS));
84-
if (++attempts > POLL_CREATED_CUSTOMER_MAX_ATTEMPTS) {
85-
throw new Error(`Could not confirm Stripe customer creation for team '${team.id}'`);
86-
}
87-
}
88-
return customer.id;
89-
}
90-
91-
async setPreferredCurrencyForCustomer(customerId: string, currency: string): Promise<void> {
92-
await this.getStripe().customers.update(customerId, { metadata: { preferredCurrency: currency } });
93-
}
94-
9572
async setDefaultPaymentMethodForCustomer(customerId: string, setupIntentId: string): Promise<void> {
9673
const setupIntent = await this.getStripe().setupIntents.retrieve(setupIntentId);
9774
if (typeof setupIntent.payment_method !== "string") {

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

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2076,8 +2076,8 @@ export class GitpodServerEEImpl extends GitpodServerImpl {
20762076
}
20772077
}
20782078

2079-
async createStripeCustomer(ctx: TraceContext, attributionId: string, currency: string): Promise<void> {
2080-
const user = this.checkAndBlockUser("createStripeCustomer");
2079+
async createStripeCustomerIfNeeded(ctx: TraceContext, attributionId: string, currency: string): Promise<void> {
2080+
const user = this.checkAndBlockUser("createStripeCustomerIfNeeded");
20812081
const attrId = AttributionId.parse(attributionId);
20822082
if (!attrId) {
20832083
throw new ResponseError(ErrorCodes.BAD_REQUEST, `Invalid attributionId '${attributionId}'`);
@@ -2096,17 +2096,16 @@ export class GitpodServerEEImpl extends GitpodServerImpl {
20962096
await this.ensureStripeApiIsAllowed({ user });
20972097
}
20982098
try {
2099-
if (await this.stripeService.findCustomerByAttributionId(attributionId)) {
2100-
throw new ResponseError(
2101-
ErrorCodes.BAD_REQUEST,
2102-
"A Stripe customer profile already exists for this attributionId",
2099+
if (!(await this.stripeService.findCustomerByAttributionId(attributionId))) {
2100+
const billingEmail = User.getPrimaryEmail(user);
2101+
const billingName = attrId.kind === "team" ? team!.name : User.getName(user);
2102+
await this.stripeService.createCustomerForAttributionId(
2103+
attributionId,
2104+
currency,
2105+
billingEmail,
2106+
billingName,
21032107
);
21042108
}
2105-
const customerId =
2106-
attrId.kind === "team"
2107-
? await this.stripeService.createCustomerForTeam(user, team!)
2108-
: await this.stripeService.createCustomerForUser(user);
2109-
await this.stripeService.setPreferredCurrencyForCustomer(customerId, currency);
21102109
} catch (error) {
21112110
log.error(`Failed to create Stripe customer profile for '${attributionId}'`, error);
21122111
throw new ResponseError(

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ const defaultFunctions: FunctionsConfig = {
201201
getStripePublishableKey: { group: "default", points: 1 },
202202
getStripeSetupIntentClientSecret: { group: "default", points: 1 },
203203
findStripeSubscriptionId: { group: "default", points: 1 },
204-
createStripeCustomer: { group: "default", points: 1 },
204+
createStripeCustomerIfNeeded: { group: "default", points: 1 },
205205
subscribeToStripe: { group: "default", points: 1 },
206206
getStripePortalUrl: { group: "default", points: 1 },
207207
listUsage: { group: "default", points: 1 },

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3130,7 +3130,7 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
31303130
async findStripeSubscriptionId(ctx: TraceContext, attributionId: string): Promise<string | undefined> {
31313131
throw new ResponseError(ErrorCodes.SAAS_FEATURE, `Not implemented in this version`);
31323132
}
3133-
async createStripeCustomer(ctx: TraceContext, attributionId: string, currency: string): Promise<void> {
3133+
async createStripeCustomerIfNeeded(ctx: TraceContext, attributionId: string, currency: string): Promise<void> {
31343134
throw new ResponseError(ErrorCodes.SAAS_FEATURE, `Not implemented in this version`);
31353135
}
31363136
async subscribeToStripe(ctx: TraceContext, attributionId: string, setupIntentId: string): Promise<void> {

0 commit comments

Comments
 (0)