Skip to content

Commit 135d322

Browse files
committed
fix(payments): Update payment providers vs methods
- Because - Sentry events frequently stating the "Server Components render" error occur for the CheckoutForm component - CheckoutForm is a client component, but it is importing the Node server SDK for Stripe causing Next to try to bundle Stripe Node SDK into the client build and surfacing the Server Components render error - Validation for paymentProvider was expecting an enum - This occurred as some of the options for payment methods (e.g. Apple Pay, Google Pay) during checkout are considered valid payment provider types. - We should distinguish payment providers and payment methods. - This pull request - Updates definition/usage of payment providers vs methods - Closes PAY-3439
1 parent 701b660 commit 135d322

17 files changed

Lines changed: 123 additions & 114 deletions

libs/payments/customer/src/lib/factories/paymentMethod.factory.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,16 @@
33
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
44

55
import { faker } from '@faker-js/faker';
6-
import { SubPlatPaymentMethodType, type StripePaymentMethod } from '../types';
6+
import {
7+
PaymentProvider,
8+
SubPlatPaymentMethodType,
9+
type StripePaymentMethod,
10+
} from '../types';
711

812
export const StripePaymentMethodTypeResponseFactory = (
913
override?: Partial<StripePaymentMethod>
1014
): StripePaymentMethod => ({
15+
provider: PaymentProvider.Stripe,
1116
type: faker.helpers.arrayElement([
1217
SubPlatPaymentMethodType.Card,
1318
SubPlatPaymentMethodType.ApplePay,

libs/payments/customer/src/lib/paymentMethod.manager.spec.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@ import {
1111
PayPalClient,
1212
PaypalCustomerManager,
1313
} from '@fxa/payments/paypal';
14-
import { SubPlatPaymentMethodType } from '@fxa/payments/customer';
14+
import {
15+
PaymentProvider,
16+
SubPlatPaymentMethodType,
17+
} from '@fxa/payments/customer';
1518
import {
1619
StripeClient,
1720
MockStripeConfigProvider,
@@ -99,6 +102,7 @@ describe('PaymentMethodManager', () => {
99102
const mockUid = faker.string.uuid();
100103

101104
jest.spyOn(paymentMethodManager, 'determineType').mockResolvedValue({
105+
provider: PaymentProvider.Stripe,
102106
type: SubPlatPaymentMethodType.Card,
103107
paymentMethodId: 'pm_id',
104108
});
@@ -128,6 +132,7 @@ describe('PaymentMethodManager', () => {
128132
const mockUid = faker.string.uuid();
129133

130134
jest.spyOn(paymentMethodManager, 'determineType').mockResolvedValue({
135+
provider: PaymentProvider.PayPal,
131136
type: SubPlatPaymentMethodType.PayPal,
132137
});
133138
jest
@@ -155,6 +160,7 @@ describe('PaymentMethodManager', () => {
155160
const mockUid = faker.string.uuid();
156161

157162
jest.spyOn(paymentMethodManager, 'determineType').mockResolvedValue({
163+
provider: PaymentProvider.Stripe,
158164
type: SubPlatPaymentMethodType.ApplePay,
159165
paymentMethodId: 'pm_id',
160166
});
@@ -215,6 +221,7 @@ describe('PaymentMethodManager', () => {
215221
const mockUid = faker.string.uuid();
216222

217223
jest.spyOn(paymentMethodManager, 'determineType').mockResolvedValue({
224+
provider: PaymentProvider.Stripe,
218225
type: SubPlatPaymentMethodType.Card,
219226
paymentMethodId: 'pm_id',
220227
});
@@ -289,6 +296,7 @@ describe('PaymentMethodManager', () => {
289296
const mockUid = faker.string.uuid();
290297

291298
jest.spyOn(paymentMethodManager, 'determineType').mockResolvedValue({
299+
provider: PaymentProvider.Stripe,
292300
type: SubPlatPaymentMethodType.ApplePay,
293301
paymentMethodId: 'pm_id',
294302
});
@@ -331,6 +339,7 @@ describe('PaymentMethodManager', () => {
331339
const mockUid = faker.string.uuid();
332340

333341
jest.spyOn(paymentMethodManager, 'determineType').mockResolvedValue({
342+
provider: PaymentProvider.PayPal,
334343
type: SubPlatPaymentMethodType.PayPal,
335344
});
336345
jest
@@ -385,6 +394,7 @@ describe('PaymentMethodManager', () => {
385394
await expect(
386395
paymentMethodManager.determineType(mockCustomer)
387396
).resolves.toEqual({
397+
provider: PaymentProvider.Stripe,
388398
type: SubPlatPaymentMethodType.Card,
389399
paymentMethodId: expect.any(String),
390400
});
@@ -398,6 +408,7 @@ describe('PaymentMethodManager', () => {
398408
await expect(
399409
paymentMethodManager.determineType(undefined, [mockSubscription])
400410
).resolves.toEqual({
411+
provider: PaymentProvider.PayPal,
401412
type: SubPlatPaymentMethodType.PayPal,
402413
});
403414
});
@@ -424,6 +435,7 @@ describe('PaymentMethodManager', () => {
424435
await expect(
425436
paymentMethodManager.determineType(mockCustomer)
426437
).resolves.toEqual({
438+
provider: PaymentProvider.Stripe,
427439
type: SubPlatPaymentMethodType.Link,
428440
paymentMethodId: expect.any(String),
429441
});
@@ -451,6 +463,7 @@ describe('PaymentMethodManager', () => {
451463
await expect(
452464
paymentMethodManager.determineType(mockCustomer)
453465
).resolves.toEqual({
466+
provider: PaymentProvider.Stripe,
454467
type: SubPlatPaymentMethodType.ApplePay,
455468
paymentMethodId: expect.any(String),
456469
});
@@ -478,6 +491,7 @@ describe('PaymentMethodManager', () => {
478491
await expect(
479492
paymentMethodManager.determineType(mockCustomer)
480493
).resolves.toEqual({
494+
provider: PaymentProvider.Stripe,
481495
type: SubPlatPaymentMethodType.GooglePay,
482496
paymentMethodId: expect.any(String),
483497
});

libs/payments/customer/src/lib/paymentMethod.manager.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
DefaultPaymentMethod,
1515
DefaultPaymentMethodError,
1616
PaymentMethodErrorType,
17+
PaymentProvider,
1718
SubPlatPaymentMethodType,
1819
type PaymentMethodTypeResponse,
1920
} from './types';
@@ -124,6 +125,7 @@ export class PaymentMethodManager {
124125
subscriptions[0].collection_method === 'send_invoice'
125126
) {
126127
return {
128+
provider: PaymentProvider.PayPal,
127129
type: SubPlatPaymentMethodType.PayPal,
128130
};
129131
}
@@ -134,26 +136,34 @@ export class PaymentMethodManager {
134136
);
135137
if (paymentMethod.card?.wallet?.type === 'apple_pay') {
136138
return {
139+
provider: PaymentProvider.Stripe,
137140
type: SubPlatPaymentMethodType.ApplePay,
138141
paymentMethodId: customer.invoice_settings.default_payment_method,
139142
};
140143
} else if (paymentMethod.card?.wallet?.type === 'google_pay') {
141144
return {
145+
provider: PaymentProvider.Stripe,
142146
type: SubPlatPaymentMethodType.GooglePay,
143147
paymentMethodId: customer.invoice_settings.default_payment_method,
144148
};
145-
} else if (paymentMethod.type === 'link' || paymentMethod.card?.wallet?.type === 'link') {
149+
} else if (
150+
paymentMethod.type === 'link' ||
151+
paymentMethod.card?.wallet?.type === 'link'
152+
) {
146153
return {
154+
provider: PaymentProvider.Stripe,
147155
type: SubPlatPaymentMethodType.Link,
148156
paymentMethodId: customer.invoice_settings.default_payment_method,
149157
};
150158
} else if (paymentMethod.type === 'card') {
151159
return {
160+
provider: PaymentProvider.Stripe,
152161
type: SubPlatPaymentMethodType.Card,
153162
paymentMethodId: customer.invoice_settings.default_payment_method,
154163
};
155164
} else {
156165
return {
166+
provider: PaymentProvider.Stripe,
157167
type: SubPlatPaymentMethodType.Stripe,
158168
paymentMethodId: customer.invoice_settings.default_payment_method,
159169
};

libs/payments/customer/src/lib/types.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,13 @@ export type InvoicePreview = {
3030
subsequentTax?: TaxAmount[];
3131
};
3232

33+
export enum PaymentProvider {
34+
AppleIap = 'apple_iap',
35+
GoogleIap = 'google_iap',
36+
PayPal = 'paypal',
37+
Stripe = 'stripe',
38+
}
39+
3340
export enum SubPlatPaymentMethodType {
3441
PayPal = 'external_paypal',
3542
Stripe = 'stripe',
@@ -40,6 +47,7 @@ export enum SubPlatPaymentMethodType {
4047
}
4148

4249
export interface StripePaymentMethod {
50+
provider: 'stripe';
4351
type:
4452
| SubPlatPaymentMethodType.Card
4553
| SubPlatPaymentMethodType.ApplePay
@@ -50,6 +58,7 @@ export interface StripePaymentMethod {
5058
}
5159

5260
export interface PayPalPaymentMethod {
61+
provider: 'paypal';
5362
type: SubPlatPaymentMethodType.PayPal;
5463
}
5564

@@ -69,10 +78,10 @@ export interface AccountCreditBalance {
6978
}
7079

7180
export type PaymentProvidersType =
72-
| Stripe.PaymentMethod.Type
81+
| 'stripe'
7382
| 'google_iap'
7483
| 'apple_iap'
75-
| 'external_paypal';
84+
| 'paypal';
7685

7786
export enum PaymentMethodErrorType {
7887
CardExpired,

libs/payments/events/src/lib/emitter.service.spec.ts

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import {
3030
CustomerManager,
3131
SubscriptionManager,
3232
PaymentMethodManager,
33-
SubPlatPaymentMethodType,
33+
PaymentProvider,
3434
StripePaymentMethodTypeResponseFactory,
3535
} from '@fxa/payments/customer';
3636
import { MockFirestoreProvider } from '@fxa/shared/db/firestore';
@@ -39,7 +39,6 @@ import {
3939
CommonMetricsFactory,
4040
MockPaymentsGleanConfigProvider,
4141
MockPaymentsGleanFactory,
42-
PaymentProvidersType,
4342
PaymentsGleanManager,
4443
} from '@fxa/payments/metrics';
4544
import { CartManager } from '@fxa/payments/cart';
@@ -105,7 +104,7 @@ describe('PaymentsEmitterService', () => {
105104
});
106105
const mockCheckoutPaymentEvents = {
107106
...mockCommonMetricsData,
108-
paymentProvider: 'stripe' as PaymentProvidersType,
107+
paymentProvider: PaymentProvider.Stripe,
109108
};
110109
let retrieveOptOutMock: jest.SpyInstance<any, unknown[], any>;
111110
const mockLogger = {
@@ -403,7 +402,7 @@ describe('PaymentsEmitterService', () => {
403402
describe('handleCheckoutSuccess', () => {
404403
const mockCustomer = StripeCustomerFactory();
405404
const mockSubscription = StripeSubscriptionFactory();
406-
const mockPaymentMethodType = StripePaymentMethodTypeResponseFactory();
405+
const mockPaymentMethod = StripePaymentMethodTypeResponseFactory();
407406
beforeEach(() => {
408407
jest
409408
.spyOn(customerManager, 'retrieve')
@@ -413,7 +412,7 @@ describe('PaymentsEmitterService', () => {
413412
.mockResolvedValue(StripeResponseFactory([mockSubscription]));
414413
jest
415414
.spyOn(paymentMethodManager, 'determineType')
416-
.mockResolvedValue(mockPaymentMethodType);
415+
.mockResolvedValue(mockPaymentMethod);
417416
jest
418417
.spyOn(paymentsGleanManager, 'recordFxaPaySetupSuccess')
419418
.mockReturnValue();
@@ -440,7 +439,7 @@ describe('PaymentsEmitterService', () => {
440439
experimentationData: { nimbusUserId },
441440
...additionalMetricsData,
442441
},
443-
mockPaymentMethodType.type
442+
mockPaymentMethod.provider
444443
);
445444
});
446445

@@ -511,7 +510,7 @@ describe('PaymentsEmitterService', () => {
511510
priceId: additionalMetricsData.cmsMetricsData.priceId,
512511
priceInterval: mockInterval,
513512
priceIntervalCount: 1,
514-
paymentProvider: SubPlatPaymentMethodType.Card,
513+
paymentProvider: PaymentProvider.Stripe,
515514
});
516515

517516
const mockPrice = StripeResponseFactory(

libs/payments/events/src/lib/emitter.service.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import {
2222
CustomerManager,
2323
SubscriptionManager,
2424
PaymentMethodManager,
25-
type SubPlatPaymentMethodType,
25+
PaymentProvidersType,
2626
} from '@fxa/payments/customer';
2727
import * as Sentry from '@sentry/nestjs';
2828
import { StatsD, StatsDService } from '@fxa/shared/metrics/statsd';
@@ -217,8 +217,8 @@ export class PaymentsEmitterService {
217217
eventData?.searchParams?.['experimentationPreview'] === 'true',
218218
});
219219

220-
// Determine payment method type
221-
let paymentMethodType: SubPlatPaymentMethodType | undefined;
220+
// Determine payment provider
221+
let paymentProvider: PaymentProvidersType | undefined;
222222
if (additionalData.cartMetricsData.stripeCustomerId) {
223223
const { stripeCustomerId } = additionalData.cartMetricsData;
224224
const customer = await this.customerManager.retrieve(stripeCustomerId);
@@ -231,7 +231,7 @@ export class PaymentsEmitterService {
231231
);
232232

233233
if (paymentMethodTypeResponse?.type) {
234-
paymentMethodType = paymentMethodTypeResponse.type;
234+
paymentProvider = paymentMethodTypeResponse.provider;
235235
}
236236
}
237237

@@ -241,7 +241,7 @@ export class PaymentsEmitterService {
241241
...additionalData,
242242
experimentationData: { nimbusUserId },
243243
},
244-
paymentMethodType
244+
paymentProvider
245245
);
246246
}
247247
}

libs/payments/events/src/lib/emitter.types.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
/* This Source Code Form is subject to the terms of the Mozilla Public
22
* License, v. 2.0. If a copy of the MPL was not distributed with this
33
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4+
45
import {
56
CancellationReason,
67
CartMetrics,
78
CmsMetricsData,
89
CommonMetrics,
9-
PaymentProvidersType,
1010
} from '@fxa/payments/metrics';
1111
import { LocationStatus } from '@fxa/payments/eligibility';
1212
import { TaxChangeAllowedStatus } from '@fxa/payments/cart';
13-
import { SubPlatPaymentMethodType } from '@fxa/payments/customer';
13+
import { PaymentProvidersType } from '@fxa/payments/customer';
1414

1515
export type CheckoutEvents = CommonMetrics;
1616
export type CheckoutPaymentEvents = CommonMetrics & {
@@ -22,7 +22,7 @@ export type SubscriptionEndedEvents = {
2222
priceId: string;
2323
priceInterval?: string;
2424
priceIntervalCount?: number;
25-
paymentProvider?: SubPlatPaymentMethodType;
25+
paymentProvider?: PaymentProvidersType;
2626
providerEventId: string;
2727
cancellationReason: CancellationReason;
2828
uid?: string;

libs/payments/metrics/src/lib/glean/glean.manager.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ import {
77
CartMetrics,
88
CmsMetricsData,
99
CommonMetrics,
10-
PaymentProvidersType,
1110
PaymentsGleanProvider,
1211
SubscriptionCancellationData,
1312
type ExperimentationData,
1413
} from './glean.types';
1514
import { Inject, Injectable } from '@nestjs/common';
15+
import { PaymentProvidersType } from '@fxa/payments/customer';
1616
import { type PaymentsGleanServerEventsLogger } from './glean.provider';
1717
import { mapSession } from './utils/mapSession';
1818
import { mapUtm } from './utils/mapUtm';
@@ -21,7 +21,6 @@ import { mapRelyingParty } from './utils/mapRelyingParty';
2121
import { normalizeGleanFalsyValues } from './utils/normalizeGleanFalsyValues';
2222
import { PaymentsGleanConfig } from './glean.config';
2323
import { mapSubscriptionCancellation } from './utils/mapSubscriptionCancellation';
24-
import type { SubPlatPaymentMethodType } from '@fxa/payments/customer';
2524

2625
@Injectable()
2726
export class PaymentsGleanManager {
@@ -82,7 +81,7 @@ export class PaymentsGleanManager {
8281
cmsMetricsData: CmsMetricsData;
8382
experimentationData: ExperimentationData;
8483
},
85-
paymentProvider?: SubPlatPaymentMethodType
84+
paymentProvider?: PaymentProvidersType
8685
) {
8786
const commonMetrics = this.populateCommonMetrics(metrics);
8887

0 commit comments

Comments
 (0)