Skip to content

Commit cfae602

Browse files
author
Olga Lashkul
committed
feat(payment): PAYPAL-365 choses paypalcredit method on the checkout
1 parent beb12cd commit cfae602

File tree

3 files changed

+70
-8
lines changed

3 files changed

+70
-8
lines changed

src/checkout-buttons/strategies/paypal-commerce/paypal-commerce-button-strategy.spec.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ describe('PaypalCommerceButtonStrategy', () => {
3434
let paymentMethod: PaymentMethod;
3535
let render: () => void;
3636
let orderID: string;
37+
let fundingSource: string;
3738

3839
beforeEach(() => {
3940
store = createCheckoutStore(getCheckoutStoreState());
@@ -63,11 +64,16 @@ describe('PaypalCommerceButtonStrategy', () => {
6364
};
6465

6566
orderID = 'ORDER_ID';
67+
fundingSource = 'paypal';
6668
eventEmitter = new EventEmitter();
6769
paypal = getPaypalCommerceMock();
6870

6971
render = jest.spyOn(paypal, 'Buttons')
7072
.mockImplementation((options: ButtonsOptions) => {
73+
eventEmitter.on('onClick', () => {
74+
options.onClick({ fundingSource });
75+
});
76+
7177
eventEmitter.on('createOrder', () => {
7278
options.createOrder();
7379
});
@@ -134,6 +140,7 @@ describe('PaypalCommerceButtonStrategy', () => {
134140
await strategy.initialize(options);
135141

136142
expect(paypal.Buttons).toHaveBeenCalledWith({
143+
onClick: expect.any(Function),
137144
createOrder: expect.any(Function),
138145
onApprove: expect.any(Function),
139146
style: paypalOptions.style,
@@ -212,6 +219,21 @@ describe('PaypalCommerceButtonStrategy', () => {
212219
.toHaveBeenCalledWith('paypalcommerce', 'b20deef40f9699e48671bbc3fef6ca44dc80e3c7');
213220
});
214221

222+
it('create order with credit (post request to server) when PayPalCommerce payment details are setup payment', async () => {
223+
fundingSource = 'credit';
224+
225+
await strategy.initialize(options);
226+
227+
eventEmitter.emit('onClick');
228+
229+
eventEmitter.emit('createOrder');
230+
231+
await new Promise(resolve => process.nextTick(resolve));
232+
233+
expect(paypalCommerceRequestSender.setupPayment)
234+
.toHaveBeenCalledWith('paypalcommercecredit', 'b20deef40f9699e48671bbc3fef6ca44dc80e3c7');
235+
});
236+
215237
it('post payment details to server to set checkout data when PayPalCommerce payment details are tokenized', async () => {
216238
await strategy.initialize(options);
217239

@@ -227,6 +249,25 @@ describe('PaypalCommerceButtonStrategy', () => {
227249
}));
228250
});
229251

252+
it('post payment details with credit to server to set checkout data when PayPalCommerce payment details are tokenized', async () => {
253+
fundingSource = 'credit';
254+
255+
await strategy.initialize(options);
256+
257+
eventEmitter.emit('onClick');
258+
259+
eventEmitter.emit('approve');
260+
261+
await new Promise(resolve => process.nextTick(resolve));
262+
263+
expect(formPoster.postForm).toHaveBeenCalledWith('/checkout.php', expect.objectContaining({
264+
payment_type: 'paypal',
265+
action: 'set_external_checkout',
266+
provider: CheckoutButtonMethodType.PAYPALCOMMERCE + 'credit',
267+
order_id: orderID,
268+
}));
269+
});
270+
230271
it('throws error in tokenize payment without order id', async () => {
231272
orderID = '';
232273
await strategy.initialize(options);
@@ -268,6 +309,7 @@ describe('PaypalCommerceButtonStrategy', () => {
268309
await strategy.initialize({ ...options, paypalCommerce: { style } });
269310

270311
expect(paypal.Buttons).toHaveBeenCalledWith({
312+
onClick: expect.any(Function),
271313
createOrder: expect.any(Function),
272314
onApprove: expect.any(Function),
273315
style: { height: 25 },
@@ -284,6 +326,7 @@ describe('PaypalCommerceButtonStrategy', () => {
284326
await strategy.initialize({ ...options, paypalCommerce: { style } });
285327

286328
expect(paypal.Buttons).toHaveBeenCalledWith({
329+
onClick: expect.any(Function),
287330
createOrder: expect.any(Function),
288331
onApprove: expect.any(Function),
289332
style: { tagline: true, layout: 'horizontal', height: 55 },
@@ -296,6 +339,7 @@ describe('PaypalCommerceButtonStrategy', () => {
296339
await strategy.initialize({ ...options, paypalCommerce: { style } });
297340

298341
expect(paypal.Buttons).toHaveBeenCalledWith({
342+
onClick: expect.any(Function),
299343
createOrder: expect.any(Function),
300344
onApprove: expect.any(Function),
301345
style: {},

src/checkout-buttons/strategies/paypal-commerce/paypal-commerce-button-strategy.ts

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@ import { FormPoster } from '@bigcommerce/form-poster';
33
import { Cart } from '../../../cart';
44
import { CheckoutActionCreator, CheckoutStore } from '../../../checkout';
55
import { InvalidArgumentError, MissingDataError, MissingDataErrorType } from '../../../common/error/errors';
6-
import { ApproveDataOptions, ButtonsOptions, DisableFundingType, PaypalButtonStyleOptions, PaypalCommerceInitializationData, PaypalCommerceRequestSender, PaypalCommerceScriptLoader, PaypalCommerceScriptOptions, StyleButtonColor, StyleButtonLabel, StyleButtonLayout, StyleButtonShape } from '../../../payment/strategies/paypal-commerce';
6+
import { ApproveDataOptions, ButtonsOptions, ClickDataOptions, DisableFundingType, PaypalButtonStyleOptions, PaypalCommerceInitializationData, PaypalCommerceRequestSender, PaypalCommerceScriptLoader, PaypalCommerceScriptOptions, StyleButtonColor, StyleButtonLabel, StyleButtonLayout, StyleButtonShape } from '../../../payment/strategies/paypal-commerce';
77
import { CheckoutButtonInitializeOptions } from '../../checkout-button-options';
88
import CheckoutButtonStrategy from '../checkout-button-strategy';
99

1010
export default class PaypalCommerceButtonStrategy implements CheckoutButtonStrategy {
11+
providerId?: string;
1112

1213
constructor(
1314
private _store: CheckoutStore,
@@ -20,9 +21,10 @@ export default class PaypalCommerceButtonStrategy implements CheckoutButtonStrat
2021
async initialize(options: CheckoutButtonInitializeOptions): Promise<void> {
2122
let state = this._store.getState();
2223
const {
23-
id: paymentId,
24+
id: providerId,
2425
initializationData,
2526
} = state.paymentMethods.getPaymentMethodOrThrow(options.methodId);
27+
this.providerId = providerId;
2628

2729
if (!initializationData.clientId) {
2830
throw new InvalidArgumentError();
@@ -33,8 +35,9 @@ export default class PaypalCommerceButtonStrategy implements CheckoutButtonStrat
3335
const paypalOptions = options.paypalCommerce;
3436

3537
const buttonParams: ButtonsOptions = {
36-
createOrder: () => this._setupPayment(options.methodId, cart.id),
37-
onApprove: data => this._tokenizePayment(paymentId, data),
38+
onClick: data => this._handleClickButtonProvider(providerId, data),
39+
createOrder: () => this._setupPayment(cart.id),
40+
onApprove: data => this._tokenizePayment(data),
3841
};
3942

4043
if (paypalOptions && paypalOptions.style) {
@@ -48,24 +51,34 @@ export default class PaypalCommerceButtonStrategy implements CheckoutButtonStrat
4851
}
4952

5053
deinitialize(): Promise<void> {
54+
this.providerId = undefined;
55+
5156
return Promise.resolve();
5257
}
5358

54-
private async _setupPayment(methodId: string, cartId: string): Promise<string> {
55-
const { orderId } = await this._paypalCommerceRequestSender.setupPayment(methodId, cartId);
59+
private _handleClickButtonProvider(providerId: string, { fundingSource }: ClickDataOptions): void {
60+
this.providerId = fundingSource === 'credit' ? 'paypalcommercecredit' : providerId;
61+
}
62+
63+
private async _setupPayment(cartId: string): Promise<string> {
64+
if (!this.providerId) {
65+
throw new MissingDataError(MissingDataErrorType.MissingPaymentMethod);
66+
}
67+
68+
const { orderId } = await this._paypalCommerceRequestSender.setupPayment(this.providerId, cartId);
5669

5770
return orderId;
5871
}
5972

60-
private _tokenizePayment(paymentId: string, { orderID }: ApproveDataOptions) {
73+
private _tokenizePayment({ orderID }: ApproveDataOptions) {
6174
if (!orderID) {
6275
throw new MissingDataError(MissingDataErrorType.MissingPayment);
6376
}
6477

6578
return this._formPoster.postForm('/checkout.php', {
6679
payment_type: 'paypal',
6780
action: 'set_external_checkout',
68-
provider: paymentId,
81+
provider: this.providerId,
6982
order_id: orderID,
7083
});
7184
}

src/payment/strategies/paypal-commerce/paypal-commerce-sdk.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ export interface ApproveDataOptions {
33
orderID: string;
44
}
55

6+
export interface ClickDataOptions {
7+
fundingSource: string;
8+
}
9+
610
export interface OrderData {
711
orderId: string;
812
approveUrl: string;
@@ -62,6 +66,7 @@ export interface ButtonsOptions {
6266
style?: PaypalButtonStyleOptions;
6367
createOrder(): Promise<string>;
6468
onApprove(data: ApproveDataOptions): void;
69+
onClick(data: ClickDataOptions): void;
6570
}
6671

6772
export interface PaypalCommerceSDK {

0 commit comments

Comments
 (0)