Skip to content

Commit ba07314

Browse files
Carlos LopezVictor Parra
authored andcommitted
feat(payment): INT-1768 Payment Intent creation refactor
1 parent 848fe84 commit ba07314

File tree

3 files changed

+80
-84
lines changed

3 files changed

+80
-84
lines changed

src/payment/payment-request-sender.ts

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,6 @@ export default class PaymentRequestSender {
3232
});
3333
}
3434

35-
generatePaymentIntent(payload: any): Promise<Response> {
36-
return new Promise((resolve, reject) => {
37-
this._client.generatePaymentIntent(payload, (error: any, response: any) => {
38-
if (error) {
39-
reject(this._transformResponse(error));
40-
} else {
41-
resolve(this._transformResponse(response));
42-
}
43-
});
44-
});
45-
}
46-
4735
private _transformResponse(response: any): Response {
4836
return {
4937
headers: {},

src/payment/strategies/stripev3/stripev3-payment-strategy.spec.ts

Lines changed: 41 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import {
3333
import { getShippingAddress } from '../../../shipping/shipping-addresses.mock';
3434
import { PaymentArgumentInvalidError } from '../../errors';
3535
import PaymentActionCreator from '../../payment-action-creator';
36+
import PaymentMethod from '../../payment-method';
3637
import PaymentMethodActionCreator from '../../payment-method-action-creator';
3738
import { getPaymentMethodsState, getStripeV3 } from '../../payment-methods.mock';
3839
import PaymentRequestTransformer from '../../payment-request-transformer';
@@ -136,6 +137,7 @@ describe('StripeV3PaymentStrategy', () => {
136137

137138
describe('#execute', () => {
138139
let stripeV3Options: PaymentInitializeOptions;
140+
let paymentMethodMock: PaymentMethod;
139141
const stripeV3JsMock = getStripeV3JsMock();
140142

141143
beforeEach(() => {
@@ -145,12 +147,6 @@ describe('StripeV3PaymentStrategy', () => {
145147
jest.spyOn(paymentMethodActionCreator, 'loadPaymentMethod').mockReturnValue(Promise.resolve());
146148
jest.spyOn(orderActionCreator, 'submitOrder').mockReturnValue(Promise.resolve());
147149
jest.spyOn(paymentActionCreator, 'submitPayment').mockReturnValue(Promise.resolve());
148-
jest.spyOn(paymentRequestSender, 'generatePaymentIntent')
149-
.mockReturnValue(Promise.resolve({
150-
body: {
151-
client_token: 'paymentIntent',
152-
},
153-
}));
154150
jest.spyOn(paymentRequestTransformer, 'transform').mockReturnValue({
155151
state: 'state',
156152
});
@@ -178,7 +174,7 @@ describe('StripeV3PaymentStrategy', () => {
178174
expect(stripeV3JsMock.handleCardPayment).toHaveBeenCalled();
179175
expect(stripeV3JsMock.createPaymentMethod).toHaveBeenCalled();
180176
expect(orderActionCreator.submitOrder).toHaveBeenCalled();
181-
expect(paymentRequestSender.generatePaymentIntent).toHaveBeenCalled();
177+
expect(paymentMethodActionCreator.loadPaymentMethod).toHaveBeenCalled();
182178
expect(paymentActionCreator.submitPayment).toHaveBeenCalled();
183179
expect(response).toBe(store.getState());
184180
});
@@ -294,6 +290,36 @@ describe('StripeV3PaymentStrategy', () => {
294290
return expect(response).rejects.toThrow(StandardError);
295291
});
296292

293+
it('throws an error when ClientToken is undefined', async () => {
294+
paymentMethodMock = {
295+
...getStripeV3(),
296+
clientToken: undefined,
297+
initializationData: {
298+
stripePublishableKey: 'key',
299+
},
300+
};
301+
stripeV3JsMock.handleCardPayment = jest.fn(
302+
() => Promise.resolve(getStripeV3HandleCardResponse())
303+
);
304+
305+
stripeV3JsMock.createPaymentMethod = jest.fn(
306+
() => Promise.resolve({
307+
paymentMethod: {
308+
id: 'paymentMethod',
309+
},
310+
})
311+
);
312+
313+
jest.spyOn(store.getState().paymentMethods, 'getPaymentMethod')
314+
.mockReturnValue(paymentMethodMock);
315+
jest.spyOn(stripeScriptLoader, 'load').mockReturnValue(Promise.resolve(stripeV3JsMock));
316+
317+
await strategy.initialize(stripeV3Options);
318+
const response = strategy.execute(getStripeV3OrderRequestBodyMock());
319+
320+
return expect(response).rejects.toThrow(MissingDataError);
321+
});
322+
297323
it('creates the order and submit payment with a signed user', async () => {
298324
const elements = stripeV3JsMock.elements();
299325
const cardElement = elements.create('card', {});
@@ -326,14 +352,14 @@ describe('StripeV3PaymentStrategy', () => {
326352
getStripePaymentMethodOptionsWithSignedUser()
327353
);
328354
expect(stripeV3JsMock.handleCardPayment).toHaveBeenCalledWith(
329-
'paymentIntent',
355+
'clientToken',
330356
{
331357
...getStripeCardPaymentOptionsWithSignedUser(),
332358
payment_method: 'paymentMethod',
333359
}
334360
);
335361
expect(orderActionCreator.submitOrder).toHaveBeenCalled();
336-
expect(paymentRequestSender.generatePaymentIntent).toHaveBeenCalled();
362+
expect(paymentMethodActionCreator.loadPaymentMethod).toHaveBeenCalled();
337363
expect(paymentActionCreator.submitPayment).toHaveBeenCalled();
338364
expect(response).toBe(store.getState());
339365
});
@@ -371,14 +397,14 @@ describe('StripeV3PaymentStrategy', () => {
371397
getStripePaymentMethodOptionsWithGuestUser()
372398
);
373399
expect(stripeV3JsMock.handleCardPayment).toHaveBeenCalledWith(
374-
'paymentIntent',
400+
'clientToken',
375401
{
376402
...getStripeCardPaymentOptionsWithGuestUser(),
377403
payment_method: 'paymentMethod',
378404
}
379405
);
380406
expect(orderActionCreator.submitOrder).toHaveBeenCalled();
381-
expect(paymentRequestSender.generatePaymentIntent).toHaveBeenCalled();
407+
expect(paymentMethodActionCreator.loadPaymentMethod).toHaveBeenCalled();
382408
expect(paymentActionCreator.submitPayment).toHaveBeenCalled();
383409
expect(response).toBe(store.getState());
384410
});
@@ -416,14 +442,14 @@ describe('StripeV3PaymentStrategy', () => {
416442
getStripePaymentMethodOptionsWithGuestUserWithoutAddress()
417443
);
418444
expect(stripeV3JsMock.handleCardPayment).toHaveBeenCalledWith(
419-
'paymentIntent',
445+
'clientToken',
420446
{
421447
...getStripeCardPaymentOptionsWithGuestUserWithoutAddress(),
422448
payment_method: 'paymentMethod',
423449
}
424450
);
425451
expect(orderActionCreator.submitOrder).toHaveBeenCalled();
426-
expect(paymentRequestSender.generatePaymentIntent).toHaveBeenCalled();
452+
expect(paymentMethodActionCreator.loadPaymentMethod).toHaveBeenCalled();
427453
expect(paymentActionCreator.submitPayment).toHaveBeenCalled();
428454
expect(response).toBe(store.getState());
429455
});
@@ -463,14 +489,14 @@ describe('StripeV3PaymentStrategy', () => {
463489
getStripePaymentMethodOptionsWithGuestUser()
464490
);
465491
expect(stripeV3JsMock.handleCardPayment).toHaveBeenCalledWith(
466-
'paymentIntent',
492+
'clientToken',
467493
{
468494
...getStripeCardPaymentOptionsWithGuestUser(),
469495
payment_method: 'paymentMethod',
470496
}
471497
);
472498
expect(orderActionCreator.submitOrder).toHaveBeenCalled();
473-
expect(paymentRequestSender.generatePaymentIntent).toHaveBeenCalled();
499+
expect(paymentMethodActionCreator.loadPaymentMethod).toHaveBeenCalled();
474500
expect(paymentActionCreator.submitPayment).toHaveBeenCalled();
475501
expect(response).toBe(store.getState());
476502
});

src/payment/strategies/stripev3/stripev3-payment-strategy.ts

Lines changed: 39 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -91,46 +91,49 @@ export default class StripeV3PaymentStrategy implements PaymentStrategy {
9191
return this._store.dispatch(this._paymentActionCreator.submitPayment({...payment, paymentData}));
9292
}
9393

94-
return this._generatePaymentIntent(
95-
payment.methodId,
96-
shouldSaveInstrument,
97-
this._store,
98-
payment.gatewayId
99-
).then(paymentIntent => {
100-
if (!this._cardElement) {
101-
throw new NotInitializedError(NotInitializedErrorType.PaymentNotInitialized);
102-
}
103-
104-
return this._getStripeJs().createPaymentMethod('card', this._cardElement,
105-
this._mapStripePaymentMethodOptions()
106-
).then(stripePaymentMethod => {
107-
if (stripePaymentMethod.error || !stripePaymentMethod.paymentMethod.id) {
108-
throw new StandardError(stripePaymentMethod.error && stripePaymentMethod.error.message);
109-
}
110-
111-
const stripeCardPaymentOptions = {
112-
...this._mapStripeCardPaymentOptions(shouldSaveInstrument),
113-
payment_method: stripePaymentMethod.paymentMethod.id,
114-
};
94+
return this._store.dispatch(this._paymentMethodActionCreator.loadPaymentMethod(payment.methodId))
95+
.then(state => {
96+
const paymentMethod = state.paymentMethods.getPaymentMethod(payment.methodId);
97+
const paymentIntent = paymentMethod && paymentMethod.clientToken;
11598

116-
return this._getStripeJs().handleCardPayment(paymentIntent, stripeCardPaymentOptions);
117-
})
118-
.then(stripeResponse => {
119-
if (stripeResponse.error || !stripeResponse.paymentIntent.id) {
120-
throw new StandardError(stripeResponse.error && stripeResponse.error.message);
99+
if (!this._cardElement) {
100+
throw new NotInitializedError(NotInitializedErrorType.PaymentNotInitialized);
121101
}
122102

123-
const paymentPayload = {
124-
methodId: payment.methodId,
125-
paymentData: {
126-
nonce: stripeResponse.paymentIntent.id,
127-
shouldSaveInstrument,
128-
},
129-
};
130-
131-
return this._store.dispatch(this._paymentActionCreator.submitPayment(paymentPayload));
103+
return this._getStripeJs().createPaymentMethod('card', this._cardElement,
104+
this._mapStripePaymentMethodOptions()
105+
).then(stripePaymentMethod => {
106+
if (stripePaymentMethod.error || !stripePaymentMethod.paymentMethod.id) {
107+
throw new StandardError(stripePaymentMethod.error && stripePaymentMethod.error.message);
108+
}
109+
110+
if (!paymentIntent) {
111+
throw new MissingDataError(MissingDataErrorType.MissingPaymentMethod);
112+
}
113+
114+
const stripeCardPaymentOptions = {
115+
...this._mapStripeCardPaymentOptions(shouldSaveInstrument),
116+
payment_method: stripePaymentMethod.paymentMethod.id,
117+
};
118+
119+
return this._getStripeJs().handleCardPayment(paymentIntent, stripeCardPaymentOptions);
120+
})
121+
.then(stripeResponse => {
122+
if (stripeResponse.error || !stripeResponse.paymentIntent.id) {
123+
throw new StandardError(stripeResponse.error && stripeResponse.error.message);
124+
}
125+
126+
const paymentPayload = {
127+
methodId: payment.methodId,
128+
paymentData: {
129+
nonce: stripeResponse.paymentIntent.id,
130+
shouldSaveInstrument,
131+
},
132+
};
133+
134+
return this._store.dispatch(this._paymentActionCreator.submitPayment(paymentPayload));
135+
});
132136
});
133-
});
134137
});
135138
}
136139

@@ -146,27 +149,6 @@ export default class StripeV3PaymentStrategy implements PaymentStrategy {
146149
return Promise.resolve(this._store.getState());
147150
}
148151

149-
private _generatePaymentIntent(
150-
methodId: string,
151-
shouldSavePaymentInstrument: boolean,
152-
store: CheckoutStore,
153-
gatewayId?: string
154-
): Promise<string> {
155-
const paymentRequestBody = this._paymentRequestTransformer.transform(
156-
{ gatewayId, methodId },
157-
store.getState()
158-
);
159-
const payload = {
160-
...paymentRequestBody,
161-
shouldSavePaymentInstrument,
162-
};
163-
164-
return this._paymentRequestSender.generatePaymentIntent(payload)
165-
.then(response => {
166-
return response.body.client_token;
167-
});
168-
}
169-
170152
private _getStripeJs(): StripeV3Client {
171153
if (!this._stripeV3Client) {
172154
throw new NotInitializedError(NotInitializedErrorType.PaymentNotInitialized);

0 commit comments

Comments
 (0)