Skip to content

Commit f8e87d5

Browse files
committed
feat(payment): Stripe Link V2 digital products handle
1 parent 737eec0 commit f8e87d5

File tree

9 files changed

+139
-130
lines changed

9 files changed

+139
-130
lines changed

packages/stripe-integration/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ export { default as createStripeV3PaymentStrategy } from './stripev3/create-stri
22
export { default as createStripeUPEPaymentStrategy } from './stripe-upe/create-stripe-upe-payment-strategy';
33
export { default as createStripeUPECustomerStrategy } from './stripe-upe/create-stripe-upe-customer-strategy';
44
export { default as createStripeOCSPaymentStrategy } from './stripe-ocs/create-stripe-ocs-payment-strategy';
5-
export { default as createStripeLinkV2CustomerStrategy } from './stripe-link-v2/create-stripe-link-v2-customer-strategy';
5+
export { default as createStripeLinkV2CustomerStrategy } from './stripe-ocs/create-stripe-link-v2-customer-strategy';
66

77
export { default as StripeScriptLoader } from './stripev3/stripev3-script-loader';
88

packages/stripe-integration/src/stripe-link-v2/types.ts

Lines changed: 0 additions & 99 deletions
This file was deleted.

packages/stripe-integration/src/stripe-link-v2/create-stripe-link-v2-customer-strategy.ts renamed to packages/stripe-integration/src/stripe-ocs/create-stripe-link-v2-customer-strategy.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
toResolvableModule,
66
} from '@bigcommerce/checkout-sdk/payment-integration-api';
77

8-
import StripeUPEScriptLoader from '../stripe-upe/stripe-upe-script-loader';
8+
import StripeUPEScriptLoader from '../stripe-utils/stripe-script-loader';
99

1010
import StripeLinkV2CustomerStrategy from './stripe-link-v2-customer-strategy';
1111

packages/stripe-integration/src/stripe-link-v2/stripe-link-v2-customer-strategy.spec.ts renamed to packages/stripe-integration/src/stripe-ocs/stripe-link-v2-customer-strategy.spec.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,22 @@ import {
66
} from '@bigcommerce/checkout-sdk/payment-integration-api';
77
import { PaymentIntegrationServiceMock } from '@bigcommerce/checkout-sdk/payment-integrations-test-utils';
88

9-
import { StripeStringConstants } from '../stripe-upe/stripe-upe';
10-
import StripeUPEScriptLoader from '../stripe-upe/stripe-upe-script-loader';
11-
import { getStripeUPEJsMock } from '../stripe-upe/stripe-upe.mock';
12-
13-
import StripeLinkV2CustomerStrategy from './stripe-link-v2-customer-strategy';
149
import {
1510
StripeLinkV2Client,
1611
StripeLinkV2Element,
1712
StripeLinkV2ElementEvent,
1813
StripeLinkV2Elements,
19-
} from './types';
14+
StripeStringConstants,
15+
} from '../stripe-utils/stripe';
16+
import StripeScriptLoader from '../stripe-utils/stripe-script-loader';
17+
18+
import StripeLinkV2CustomerStrategy from './stripe-link-v2-customer-strategy';
19+
import { getStripeOCSMock } from './stripe-ocs.mock';
2020

2121
describe('StripeLinkV2CustomerStrategy', () => {
2222
let strategy: StripeLinkV2CustomerStrategy;
2323
let paymentIntegrationService: PaymentIntegrationService;
24-
let scriptLoader: jest.Mocked<StripeUPEScriptLoader>;
24+
let scriptLoader: jest.Mocked<StripeScriptLoader>;
2525
let stripeClient: jest.Mocked<StripeLinkV2Client>;
2626
let elements: jest.Mocked<StripeLinkV2Elements>;
2727
let element: jest.Mocked<StripeLinkV2Element>;
@@ -61,7 +61,7 @@ describe('StripeLinkV2CustomerStrategy', () => {
6161
} as any;
6262

6363
stripeClient = {
64-
...getStripeUPEJsMock(),
64+
...getStripeOCSMock(),
6565
elements: jest.fn().mockReturnValue(elements),
6666
confirmPayment: jest.fn(),
6767
} as any;

packages/stripe-integration/src/stripe-link-v2/stripe-link-v2-customer-strategy.ts renamed to packages/stripe-integration/src/stripe-ocs/stripe-link-v2-customer-strategy.ts

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,9 @@ import {
1212
} from '@bigcommerce/checkout-sdk/payment-integration-api';
1313

1414
// import { isStripeUPEPaymentMethodLike } from '../stripe-upe/is-stripe-upe-payment-method-like';
15-
import { StripeElementType, StripeStringConstants } from '../stripe-utils/stripe';
16-
import StripeScriptLoader from '../stripe-utils/stripe-script-loader';
1715
import { WithStripeUPECustomerInitializeOptions } from '../stripe-upe/stripeupe-customer-initialize-options';
18-
19-
import { expressCheckoutAllowedCountryCodes } from './constants';
2016
import {
17+
StripeElementType,
2118
StripeLinkV2Client,
2219
StripeLinkV2Element,
2320
StripeLinkV2ElementCreateOptions,
@@ -26,7 +23,11 @@ import {
2623
StripeLinkV2Event,
2724
StripeLinkV2Options,
2825
StripeLinkV2ShippingRate,
29-
} from './types';
26+
StripeStringConstants,
27+
} from '../stripe-utils/stripe';
28+
import StripeScriptLoader from '../stripe-utils/stripe-script-loader';
29+
30+
import { expressCheckoutAllowedCountryCodes } from './constants';
3031

3132
export default class StripeLinkV2CustomerStrategy implements CustomerStrategy {
3233
private _stripeLinkV2Client?: StripeLinkV2Client;
@@ -63,7 +64,7 @@ export default class StripeLinkV2CustomerStrategy implements CustomerStrategy {
6364
}
6465
});
6566

66-
const stripePublishableKey = undefined;
67+
const stripePublishableKey = 'key';
6768
// TODO uncomment below lines on finalizing
6869

6970
// const state = this.paymentIntegrationService.getState();
@@ -78,8 +79,7 @@ export default class StripeLinkV2CustomerStrategy implements CustomerStrategy {
7879
// } = paymentMethod;
7980

8081
// TODO remove mock below on finalizing
81-
this._stripePublishableKey =
82-
stripePublishableKey || 'pk_test_iyRKkVUt0YWpJ3Lq7mfsw3VW008KiFDH4s';
82+
this._stripePublishableKey = stripePublishableKey;
8383

8484
this._stripeLinkV2Client = await this.scriptLoader.getStripeLinkV2Client(
8585
this._stripePublishableKey,
@@ -114,10 +114,15 @@ export default class StripeLinkV2CustomerStrategy implements CustomerStrategy {
114114
container: string,
115115
stripeExpressCheckoutClient: StripeLinkV2Client,
116116
) {
117+
const shouldRequireShippingAddress = this.shouldRequireShippingAddress();
117118
const expressCheckoutOptions: StripeLinkV2ElementCreateOptions = {
118-
allowedShippingCountries: await this.getAvailableCountries(),
119-
shippingAddressRequired: true,
120-
shippingRates: [{ id: '_', amount: 0, displayName: 'Pending rates' }],
119+
shippingAddressRequired: shouldRequireShippingAddress,
120+
...(shouldRequireShippingAddress
121+
? { allowedShippingCountries: await this.getAvailableCountries() }
122+
: {}),
123+
...(shouldRequireShippingAddress
124+
? { shippingRates: [{ id: '_', amount: 0, displayName: 'Pending rates' }] }
125+
: {}),
121126
billingAddressRequired: true,
122127
emailRequired: true,
123128
phoneNumberRequired: true,
@@ -153,12 +158,19 @@ export default class StripeLinkV2CustomerStrategy implements CustomerStrategy {
153158
/** Events * */
154159

155160
private initializeEvents(expressCheckoutElement: StripeLinkV2Element): void {
156-
expressCheckoutElement.on(StripeLinkV2ElementEvent.SHIPPING_ADDRESS_CHANGE, async (event) =>
157-
this.onShippingAddressChange(event),
158-
);
159-
expressCheckoutElement.on(StripeLinkV2ElementEvent.SHIPPING_RATE_CHANGE, async (event) =>
160-
this.onShippingRateChange(event),
161-
);
161+
const shouldRequireShippingAddress = this.shouldRequireShippingAddress();
162+
163+
if (shouldRequireShippingAddress) {
164+
expressCheckoutElement.on(
165+
StripeLinkV2ElementEvent.SHIPPING_ADDRESS_CHANGE,
166+
async (event) => this.onShippingAddressChange(event),
167+
);
168+
expressCheckoutElement.on(
169+
StripeLinkV2ElementEvent.SHIPPING_RATE_CHANGE,
170+
async (event) => this.onShippingRateChange(event),
171+
);
172+
}
173+
162174
expressCheckoutElement.on(StripeLinkV2ElementEvent.CONFIRM, async (event) =>
163175
this.onConfirm(event),
164176
);
@@ -267,6 +279,13 @@ export default class StripeLinkV2CustomerStrategy implements CustomerStrategy {
267279

268280
/** Utils * */
269281

282+
private shouldRequireShippingAddress() {
283+
const { getCartOrThrow } = this.paymentIntegrationService.getState();
284+
const { lineItems } = getCartOrThrow();
285+
286+
return !!lineItems.physicalItems.length;
287+
}
288+
270289
private async updateDisplayedPrice() {
271290
if (this._stripeElements) {
272291
this._stripeElements.update({

packages/stripe-integration/src/stripe-utils/stripe-script-loader.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,13 @@ import { ScriptLoader } from '@bigcommerce/script-loader';
22

33
import { PaymentMethodClientUnavailableError } from '@bigcommerce/checkout-sdk/payment-integration-api';
44

5-
import { StripeLinkV2Client } from '../stripe-link-v2/types';
6-
75
import {
86
StripeClient,
97
StripeConfigurationOptions,
108
StripeElements,
119
StripeElementsOptions,
1210
StripeHostWindow,
11+
StripeLinkV2Client,
1312
} from './stripe';
1413

1514
export default class StripeScriptLoader {

packages/stripe-integration/src/stripe-utils/stripe.ts

Lines changed: 92 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { PaymentMethod } from '@bigcommerce/checkout-sdk/payment-integration-api';
2-
import { StripeLinkV2Client } from '../stripe-link-v2/types';
32

43
/**
54
* Initialization options.
@@ -511,11 +510,11 @@ export interface StripeResult {
511510
export interface StripeHostWindow extends Window {
512511
bcStripeClient?: StripeClient;
513512
bcStripeElements?: StripeElements;
513+
bcStripeLinkV2Client?: StripeLinkV2Client;
514514
Stripe?<T = StripeClient>(
515515
stripePublishableKey: string,
516516
options?: StripeConfigurationOptions,
517517
): T;
518-
bcStripeLinkV2Client?: StripeLinkV2Client;
519518
}
520519

521520
export enum StripePaymentMethodType {
@@ -584,3 +583,94 @@ export interface StripeAdditionalActionResponseBody {
584583
token?: string;
585584
};
586585
}
586+
587+
export enum StripeLinkV2ElementEvent {
588+
CLICK = 'click',
589+
READY = 'ready',
590+
SHIPPING_ADDRESS_CHANGE = 'shippingaddresschange',
591+
SHIPPING_RATE_CHANGE = 'shippingratechange',
592+
CONFIRM = 'confirm',
593+
}
594+
595+
export interface StripeLinkV2Client extends Omit<StripeClient, 'elements' | 'confirmPayment'> {
596+
elements(options: StripeLinkV2Options): StripeLinkV2Elements;
597+
confirmPayment(options: StripeLinkV2ConfirmPaymentData): Promise<StripeResult>;
598+
}
599+
600+
export interface StripeLinkV2ConfirmPaymentData extends Omit<StripeConfirmPaymentData, 'elements'> {
601+
elements: StripeLinkV2Elements;
602+
clientSecret?: string;
603+
}
604+
605+
export interface StripeLinkV2Elements extends Omit<StripeElements, 'create' | 'update'> {
606+
create(
607+
elementType: StripeElementType,
608+
options?: StripeLinkV2ElementCreateOptions,
609+
): StripeLinkV2Element;
610+
update(options?: StripeLinkV2Options): StripeLinkV2Element;
611+
}
612+
613+
export interface StripeLinkV2Element extends Omit<StripeElement, 'on' | 'update'> {
614+
on(event: StripeLinkV2ElementEvent, handler: (event: StripeLinkV2Event) => void): void;
615+
616+
update(options?: StripeLinkV2ElementCreateOptions): void;
617+
}
618+
619+
export interface LineItem {
620+
name: string;
621+
amount: number;
622+
}
623+
624+
export interface StripeLinkV2ElementCreateOptions {
625+
lineItems?: LineItem[];
626+
allowedShippingCountries?: string[];
627+
shippingAddressRequired?: boolean;
628+
shippingRates?: StripeLinkV2ShippingRate[];
629+
billingAddressRequired?: boolean;
630+
emailRequired?: boolean;
631+
phoneNumberRequired?: boolean;
632+
paymentMethods?: {
633+
link: StripeStringConstants.AUTO;
634+
applePay: StripeStringConstants.NEVER;
635+
googlePay: StripeStringConstants.NEVER;
636+
amazonPay: StripeStringConstants.NEVER;
637+
paypal: StripeStringConstants.NEVER;
638+
};
639+
buttonHeight?: number;
640+
}
641+
642+
export interface StripeLinkV2Event {
643+
address?: {
644+
city?: string;
645+
country?: string;
646+
postal_code?: string;
647+
state?: string;
648+
};
649+
shippingRate?: StripeLinkV2ShippingRate;
650+
elementType: string;
651+
expressPaymentType: string;
652+
resolve(data: StripeLinkV2EventResolveData): void;
653+
}
654+
655+
export interface StripeLinkV2EventResolveData {
656+
lineItems?: LineItem[];
657+
allowedShippingCountries?: string[];
658+
shippingAddressRequired?: boolean;
659+
shippingRates?: StripeLinkV2ShippingRate[];
660+
billingAddressRequired?: boolean;
661+
emailRequired?: boolean;
662+
phoneNumberRequired?: boolean;
663+
}
664+
665+
export interface StripeLinkV2ShippingRate {
666+
id: string;
667+
amount: number;
668+
displayName: string;
669+
}
670+
671+
export interface StripeLinkV2Options {
672+
clientSecret?: string;
673+
mode?: string;
674+
currency?: string;
675+
amount?: number;
676+
}

0 commit comments

Comments
 (0)