Skip to content

Commit 8312877

Browse files
committed
fix(payment): CHECKOUT-2789 Add PaypalProPaymentStrategy to handle special conditions for Paypal Payments Pro US
1 parent ee89380 commit 8312877

File tree

4 files changed

+110
-0
lines changed

4 files changed

+110
-0
lines changed

src/core/create-payment-strategy-registry.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
OfflinePaymentStrategy,
66
OffsitePaymentStrategy,
77
PaypalExpressPaymentStrategy,
8+
PaypalProPaymentStrategy,
89
SagePayPaymentStrategy,
910
} from './payment/strategies';
1011
import { PaymentStrategyRegistry } from './payment';
@@ -24,6 +25,7 @@ export default function createPaymentStrategyRegistry(store, placeOrderService)
2425
registry.addStrategy('legacy', new LegacyPaymentStrategy(store, placeOrderService));
2526
registry.addStrategy('offline', new OfflinePaymentStrategy(store, placeOrderService));
2627
registry.addStrategy('offsite', new OffsitePaymentStrategy(store, placeOrderService));
28+
registry.addStrategy('paypal', new PaypalProPaymentStrategy(store, placeOrderService));
2729
registry.addStrategy('paypalexpress', new PaypalExpressPaymentStrategy(store, placeOrderService, scriptLoader));
2830
registry.addStrategy('paypalexpresscredit', new PaypalExpressPaymentStrategy(store, placeOrderService, scriptLoader));
2931
registry.addStrategy('sagepay', new SagePayPaymentStrategy(store, placeOrderService, createFormPoster()));

src/core/payment/strategies/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ export { default as OfflinePaymentStrategy } from './offline-payment-strategy';
44
export { default as OffsitePaymentStrategy } from './offsite-payment-strategy';
55
export { default as PaymentStrategy } from './payment-strategy';
66
export { default as PaypalExpressPaymentStrategy } from './paypal-express-payment-strategy';
7+
export { default as PaypalProPaymentStrategy } from './paypal-pro-payment-strategy';
78
export { default as SagePayPaymentStrategy } from './sage-pay-payment-strategy';
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { omit, pick } from 'lodash';
2+
import * as paymentStatusTypes from '../payment-status-types';
3+
import PaymentStrategy from './payment-strategy';
4+
5+
export default class PaypalProPaymentStrategy extends PaymentStrategy {
6+
/**
7+
* @inheritdoc
8+
*/
9+
execute(payload, options) {
10+
if (this._isPaymentAcknowledged()) {
11+
return this._placeOrderService.submitOrder({
12+
...payload,
13+
payment: pick(payload.payment, 'name'),
14+
}, options);
15+
}
16+
17+
return this._placeOrderService.submitOrder(omit(payload, 'payment'), options)
18+
.then(() =>
19+
this._placeOrderService.submitPayment(payload.payment, payload.useStoreCredit, options)
20+
);
21+
}
22+
23+
/**
24+
* @private
25+
* @return {boolean}
26+
*/
27+
_isPaymentAcknowledged() {
28+
const { checkout } = this._store.getState();
29+
const { payment = {} } = checkout.getOrder();
30+
31+
return payment.status === paymentStatusTypes.ACKNOWLEDGE;
32+
}
33+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import { omit } from 'lodash';
2+
import { getOrderRequestBody, getIncompleteOrder } from '../../order/orders.mock';
3+
import * as paymentStatusTypes from '../payment-status-types';
4+
import createCheckoutStore from '../../create-checkout-store';
5+
import PaypalProPaymentStrategy from './paypal-pro-payment-strategy';
6+
7+
describe('PaypalProPaymentStrategy', () => {
8+
let placeOrderService;
9+
let store;
10+
let strategy;
11+
12+
beforeEach(() => {
13+
placeOrderService = {
14+
submitOrder: jest.fn(() => Promise.resolve(store.getState())),
15+
submitPayment: jest.fn(() => Promise.resolve(store.getState())),
16+
};
17+
18+
store = createCheckoutStore();
19+
20+
strategy = new PaypalProPaymentStrategy(store, placeOrderService);
21+
});
22+
23+
it('submits order without payment data', async () => {
24+
const payload = getOrderRequestBody();
25+
26+
await strategy.execute(payload);
27+
28+
expect(placeOrderService.submitOrder).toHaveBeenCalledWith(omit(payload, 'payment'), undefined);
29+
});
30+
31+
it('submits payment separately', async () => {
32+
const payload = getOrderRequestBody();
33+
34+
await strategy.execute(payload);
35+
36+
expect(placeOrderService.submitPayment).toHaveBeenCalledWith(payload.payment, payload.useStoreCredit, undefined);
37+
});
38+
39+
it('returns checkout state', async () => {
40+
const output = await strategy.execute(getOrderRequestBody());
41+
42+
expect(output).toEqual(store.getState());
43+
});
44+
45+
describe('if payment is acknowledged', () => {
46+
beforeEach(() => {
47+
const { checkout } = store.getState();
48+
49+
jest.spyOn(checkout, 'getOrder').mockReturnValue({
50+
...getIncompleteOrder(),
51+
payment: { status: paymentStatusTypes.ACKNOWLEDGE },
52+
});
53+
});
54+
55+
it('submits order with payment method name', async () => {
56+
const payload = getOrderRequestBody();
57+
58+
await strategy.execute(payload);
59+
60+
expect(placeOrderService.submitOrder).toHaveBeenCalledWith({
61+
...payload,
62+
payment: { name: payload.payment.name },
63+
}, undefined);
64+
});
65+
66+
it('does not submit payment separately', async () => {
67+
const payload = getOrderRequestBody();
68+
69+
await strategy.execute(payload);
70+
71+
expect(placeOrderService.submitPayment).not.toHaveBeenCalled();
72+
});
73+
});
74+
});

0 commit comments

Comments
 (0)