Skip to content

Commit 53b632b

Browse files
committed
feat(payment): headless wallet button integration service + paypal strategy
1 parent b3cdb2d commit 53b632b

36 files changed

+906
-6
lines changed

packages/core/auto-export.config.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@
1414
"inputPath": "packages/*/src/index.ts",
1515
"outputPath": "packages/core/src/generated/checkout-button-strategies.ts",
1616
"memberPattern": "^create.+ButtonStrategy$"
17+
},
18+
{
19+
"inputPath": "packages/*/src/index.ts",
20+
"outputPath": "packages/core/src/generated/wallet-button-strategies.ts",
21+
"memberPattern": "^create.+WalletStrategy$"
1722
}
1823
]
1924
}

packages/core/extend-interface.config.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,14 @@
2323
"memberPattern": "^With.+ButtonInitializeOptions$",
2424
"targetPath": "packages/core/src/checkout-buttons/index.ts",
2525
"targetMemberName": "BaseCheckoutButtonInitializeOptions"
26+
},
27+
{
28+
"inputPath": "packages/*/src/index.ts",
29+
"outputPath": "packages/core/src/generated/wallet-button-initialize-options.ts",
30+
"outputMemberName": "WalletButtonInitializeOptions",
31+
"memberPattern": "^With.+WalletInitializeOptions$",
32+
"targetPath": "packages/core/src/wallet-buttons/index.ts",
33+
"targetMemberName": "BaseWalletButtonInitializeOptions"
2634
}
2735
]
2836
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export { createTimeout } from '@bigcommerce/request-sender';
2+
3+
export { createWalletButtonInitializer } from '../wallet-buttons';

packages/core/src/loader-cdn.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,20 @@ import * as checkoutButtonBundle from './bundles/checkout-button';
55
import * as mainBundle from './bundles/checkout-sdk';
66
import * as embeddedCheckoutBundle from './bundles/embedded-checkout';
77
import * as hostedFormBundle from './bundles/hosted-form';
8+
import * as walletButtonBundle from './bundles/wallet-button';
89
import { parseUrl } from './common/url';
910

1011
export type CheckoutButtonBundle = typeof checkoutButtonBundle & { version: string };
12+
export type WalletButtonBundle = typeof walletButtonBundle & {
13+
version: string;
14+
};
1115
export type EmbeddedCheckoutBundle = typeof embeddedCheckoutBundle & { version: string };
1216
export type HostedFormBundle = typeof hostedFormBundle & { version: string };
1317
export type MainBundle = typeof mainBundle & { version: string };
1418

1519
export enum BundleType {
1620
CheckoutButton = 'checkout-button',
21+
WalletButton = 'wallet-payment-button',
1722
EmbeddedCheckout = 'embedded-checkout',
1823
HostedForm = 'hosted-form',
1924
Main = 'checkout-sdk',
@@ -25,12 +30,19 @@ const scriptOrigin = isScriptElement(document.currentScript)
2530

2631
export function load(moduleName?: BundleType.Main): Promise<MainBundle>;
2732
export function load(moduleName: BundleType.CheckoutButton): Promise<CheckoutButtonBundle>;
33+
export function load(moduleName: BundleType.WalletButton): Promise<WalletButtonBundle>;
2834
export function load(moduleName: BundleType.EmbeddedCheckout): Promise<EmbeddedCheckoutBundle>;
2935
export function load(moduleName: BundleType.HostedForm): Promise<HostedFormBundle>;
3036

3137
export async function load(
3238
moduleName: string = BundleType.Main,
33-
): Promise<MainBundle | CheckoutButtonBundle | EmbeddedCheckoutBundle | HostedFormBundle> {
39+
): Promise<
40+
| MainBundle
41+
| CheckoutButtonBundle
42+
| WalletButtonBundle
43+
| EmbeddedCheckoutBundle
44+
| HostedFormBundle
45+
> {
3446
const { version, js } = MANIFEST_JSON;
3547
const manifestPath = js.find((path) => path.indexOf(moduleName) !== -1);
3648

packages/core/src/loader.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,39 @@ import * as checkoutButtonBundle from './bundles/checkout-button';
44
import * as mainBundle from './bundles/checkout-sdk';
55
import * as embeddedCheckoutBundle from './bundles/embedded-checkout';
66
import * as hostedFormBundle from './bundles/hosted-form';
7+
import * as walletButtonBundle from './bundles/wallet-button';
78

89
export type CheckoutButtonBundle = typeof checkoutButtonBundle & { version: string };
10+
export type WalletPaymentButtonBundle = typeof walletButtonBundle & {
11+
version: string;
12+
};
913
export type EmbeddedCheckoutBundle = typeof embeddedCheckoutBundle & { version: string };
1014
export type HostedFormBundle = typeof hostedFormBundle & { version: string };
1115
export type MainBundle = typeof mainBundle & { version: string };
1216

1317
export enum BundleType {
1418
CheckoutButton = 'checkout-button',
19+
WalletButton = 'wallet-button',
1520
EmbeddedCheckout = 'embedded-checkout',
1621
HostedForm = 'hosted-form',
1722
Main = 'checkout-sdk',
1823
}
1924

2025
export function load(moduleName?: BundleType.Main): Promise<MainBundle>;
2126
export function load(moduleName: BundleType.CheckoutButton): Promise<CheckoutButtonBundle>;
27+
export function load(moduleName: BundleType.WalletButton): Promise<WalletPaymentButtonBundle>;
2228
export function load(moduleName: BundleType.EmbeddedCheckout): Promise<EmbeddedCheckoutBundle>;
2329
export function load(moduleName: BundleType.HostedForm): Promise<HostedFormBundle>;
2430

2531
export async function load(
2632
moduleName: string = BundleType.Main,
27-
): Promise<MainBundle | CheckoutButtonBundle | EmbeddedCheckoutBundle | HostedFormBundle> {
33+
): Promise<
34+
| MainBundle
35+
| CheckoutButtonBundle
36+
| WalletPaymentButtonBundle
37+
| EmbeddedCheckoutBundle
38+
| HostedFormBundle
39+
> {
2840
const { version, js } = MANIFEST_JSON;
2941
const manifestPath = js.find((path) => path.indexOf(moduleName) !== -1);
3042

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { createWalletButtonIntegrationService } from '@bigcommerce/checkout-sdk/wallet-button-integration';
2+
3+
import * as walletButtonStrategyFactories from '../generated/wallet-button-strategies';
4+
5+
import createWalletButtonStrategyRegistry from './create-wallet-button-strategy-registry';
6+
import WalletButtonInitializer from './wallet-button-initializer';
7+
8+
export default function createWalletButtonInitializer(): WalletButtonInitializer {
9+
const walletPaymentButtonIntegrationService = createWalletButtonIntegrationService();
10+
const registryV2 = createWalletButtonStrategyRegistry(
11+
walletPaymentButtonIntegrationService,
12+
walletButtonStrategyFactories,
13+
);
14+
15+
return new WalletButtonInitializer(registryV2);
16+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import {
2+
CheckoutButtonStrategy,
3+
CheckoutButtonStrategyResolveId,
4+
isResolvableModule,
5+
} from '@bigcommerce/checkout-sdk/payment-integration-api';
6+
import {
7+
WalletButtonIntegrationService,
8+
WalletButtonStrategyFactory,
9+
} from '@bigcommerce/checkout-sdk/wallet-button-integration';
10+
11+
import { ResolveIdRegistry } from '../common/registry';
12+
13+
export interface WalletButtonStrategyFactories {
14+
[key: string]: WalletButtonStrategyFactory<CheckoutButtonStrategy>;
15+
}
16+
17+
export default function createWalletButtonStrategyRegistry(
18+
walletButtonIntegrationService: WalletButtonIntegrationService,
19+
walletButtonStrategyFactories: WalletButtonStrategyFactories,
20+
): ResolveIdRegistry<CheckoutButtonStrategy, CheckoutButtonStrategyResolveId> {
21+
const registry = new ResolveIdRegistry<
22+
CheckoutButtonStrategy,
23+
CheckoutButtonStrategyResolveId
24+
>();
25+
26+
for (const [, createCheckoutButtonStrategy] of Object.entries(walletButtonStrategyFactories)) {
27+
if (
28+
!isResolvableModule<
29+
WalletButtonStrategyFactory<CheckoutButtonStrategy>,
30+
CheckoutButtonStrategyResolveId
31+
>(createCheckoutButtonStrategy)
32+
) {
33+
continue;
34+
}
35+
36+
for (const resolverId of createCheckoutButtonStrategy.resolveIds) {
37+
registry.register(resolverId, () =>
38+
createCheckoutButtonStrategy(walletButtonIntegrationService),
39+
);
40+
}
41+
}
42+
43+
return registry;
44+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export { default as createWalletButtonInitializer } from './create-wallet-button-initializer';
2+
export { BaseWalletButtonInitializeOptions } from './wallet-button-options';
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { bindDecorator as bind } from '@bigcommerce/checkout-sdk/utility';
2+
3+
import { isElementId, setUniqueElementId } from '../common/dom';
4+
5+
import { BaseWalletButtonInitializeOptions, WalletButtonOptions } from './wallet-button-options';
6+
import WalletButtonRegistryV2 from './wallet-button-strategy-registry-v2';
7+
8+
@bind
9+
export default class WalletButtonInitializer {
10+
constructor(private _registryV2: WalletButtonRegistryV2) {}
11+
12+
initializeWalletButton(options: BaseWalletButtonInitializeOptions): Promise<void[]> {
13+
const containerIds = this.getContainerIds(options);
14+
15+
return Promise.all(
16+
containerIds.map(async (containerId) => {
17+
const strategy = this._registryV2.get({ id: options.methodId });
18+
19+
return strategy.initialize({ ...options, containerId });
20+
}),
21+
);
22+
}
23+
24+
deinitializeWalletButton(options: WalletButtonOptions): Promise<void> {
25+
return this._registryV2.get({ id: options.methodId }).deinitialize();
26+
}
27+
28+
private getContainerIds(options: BaseWalletButtonInitializeOptions) {
29+
return isElementId(options.containerId)
30+
? [options.containerId]
31+
: setUniqueElementId(options.containerId, `${options.methodId}-container`);
32+
}
33+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { RequestOptions } from '../common/http-request';
2+
3+
export { WalletButtonInitializeOptions } from '../generated/wallet-button-initialize-options';
4+
5+
enum CheckoutButtonMethodType {
6+
PAYPALCOMMERCE = 'paypalcommercepaypal',
7+
PAYPLCOMMERCEVENMO = 'paypalcommercevenmo',
8+
PAYPALCOMMERCEPAYPALCREDIT = 'paypalcommercepaypalcredit',
9+
}
10+
11+
export interface WalletButtonOptions extends RequestOptions {
12+
methodId: CheckoutButtonMethodType;
13+
}
14+
15+
export interface BaseWalletButtonInitializeOptions extends WalletButtonOptions {
16+
[key: string]: unknown;
17+
18+
containerId: string;
19+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import {
2+
CheckoutButtonStrategy,
3+
CheckoutButtonStrategyResolveId,
4+
} from '@bigcommerce/checkout-sdk/payment-integration-api';
5+
6+
import { ResolveIdRegistry } from '../common/registry';
7+
8+
type WalletButtonRegistry = ResolveIdRegistry<
9+
CheckoutButtonStrategy,
10+
CheckoutButtonStrategyResolveId
11+
>;
12+
13+
export default WalletButtonRegistry;
Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
1-
export { default as BillingAddress, BillingAddressRequestBody } from './billing-address';
1+
export {
2+
default as BillingAddress,
3+
BillingAddressRequestBody,
4+
BillingAddressUpdateRequestBody,
5+
} from './billing-address';
26
export { default as isBillingAddressLike } from './is-billing-address-like';

packages/payment-integration-api/src/index.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
export { Address, AddressRequestBody, LegacyAddress } from './address';
2-
export { BillingAddress, BillingAddressRequestBody, isBillingAddressLike } from './billing';
2+
export {
3+
BillingAddress,
4+
BillingAddressRequestBody,
5+
BillingAddressUpdateRequestBody,
6+
isBillingAddressLike,
7+
} from './billing';
38
export {
49
CheckoutButtonStrategy,
510
CheckoutButtonStrategyFactory,

packages/paypal-commerce-integration/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ export { WithPayPalCommerceCustomerInitializeOptions } from './paypal-commerce/p
1616
export { default as createPayPalCommercePaymentStrategy } from './paypal-commerce/create-paypal-commerce-payment-strategy';
1717
export { WithPayPalCommercePaymentInitializeOptions } from './paypal-commerce/paypal-commerce-payment-initialize-options';
1818

19+
export { default as createPayPalCommerceWalletStrategy } from './paypal-commerce/create-paypal-commerce-wallet-strategy';
20+
export { WithPayPalCommerceWalletInitializeOptions } from './paypal-commerce/paypal-commerce-wallet-initialize-options';
1921
/**
2022
*
2123
* PayPalCommerce Credit (PayLater) strategies

0 commit comments

Comments
 (0)