From 612afaf3a671dbea187c4de37ec1f4ecd7e71ff8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20D=C4=85bek?= Date: Mon, 5 Aug 2019 16:00:26 +0200 Subject: [PATCH 1/2] Add support for handleCardAction --- src/components/inject.js | 4 +++- src/components/inject.test.js | 16 ++++++++++++++++ src/decls/Stripe.js | 3 +++ src/index.test.js | 21 +++++++++++++++++++++ 4 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/components/inject.js b/src/components/inject.js index 0d4a065..bf693ea 100644 --- a/src/components/inject.js +++ b/src/components/inject.js @@ -22,6 +22,7 @@ type WrappedStripeShape = { createPaymentMethod: Function, handleCardPayment: Function, handleCardSetup: Function, + handleCardAction: Function, }; type State = {stripe: WrappedStripeShape | null}; @@ -99,6 +100,7 @@ Please be sure the component that calls createSource or createToken is within an createPaymentMethod: this.wrappedCreatePaymentMethod(stripe), handleCardPayment: this.wrappedHandleCardX(stripe, 'handleCardPayment'), handleCardSetup: this.wrappedHandleCardX(stripe, 'handleCardSetup'), + handleCardAction: this.wrappedHandleCardX(stripe, 'handleCardAction'), }; } @@ -283,7 +285,7 @@ Please be sure the component that calls createSource or createToken is within an wrappedHandleCardX = ( stripe: StripeShape, - method: 'handleCardPayment' | 'handleCardSetup' + method: 'handleCardPayment' | 'handleCardSetup' | 'handleCardAction' ) => (clientSecret: mixed, elementOrData?: mixed, maybeData?: mixed) => { if (!clientSecret || typeof clientSecret !== 'string') { // If a bad value was passed in for clientSecret, throw an error. diff --git a/src/components/inject.test.js b/src/components/inject.test.js index 63f0123..6ab79ae 100644 --- a/src/components/inject.test.js +++ b/src/components/inject.test.js @@ -12,6 +12,7 @@ describe('injectStripe()', () => { let createPaymentMethod; let handleCardPayment; let handleCardSetup; + let handleCardAction; let elementMock; let rawElementMock; @@ -22,6 +23,7 @@ describe('injectStripe()', () => { createPaymentMethod = jest.fn(); handleCardPayment = jest.fn(); handleCardSetup = jest.fn(); + handleCardAction = jest.fn(); rawElementMock = { _frame: { id: 'id', @@ -52,6 +54,7 @@ describe('injectStripe()', () => { createPaymentMethod, handleCardPayment, handleCardSetup, + handleCardAction, }, getRegisteredElements: () => [elementMock], }; @@ -506,6 +509,18 @@ describe('injectStripe()', () => { ); }); + it('props.stripe.handleCardAction calls handleCardAction with only clientSecret when only clientSecret is passed in', () => { + const Injected = injectStripe(WrappedComponent); + + const wrapper = shallow(, { + context, + }); + + const props = wrapper.props(); + props.stripe.handleCardAction('clientSecret'); + expect(handleCardSetup).toHaveBeenCalledWith('clientSecret') + }); + it('throws when `getWrappedInstance` is called without `{withRef: true}` option.', () => { const Injected = injectStripe(WrappedComponent); @@ -583,6 +598,7 @@ describe('injectStripe()', () => { expect(props).toHaveProperty('stripe.createPaymentMethod'); expect(props).toHaveProperty('stripe.handleCardPayment'); expect(props).toHaveProperty('stripe.handleCardSetup'); + expect(props).toHaveProperty('stripe.handleCardAction'); }); }); }); diff --git a/src/decls/Stripe.js b/src/decls/Stripe.js index 4fa66de..f1e6c2c 100644 --- a/src/decls/Stripe.js +++ b/src/decls/Stripe.js @@ -40,4 +40,7 @@ declare type StripeShape = { element: ElementShape | MixedObject, options: mixed ) => Promise<{setupIntent?: MixedObject, error?: MixedObject}>, + handleCardAction: ( + clientSecret: string + ) => Promise<{paymentIntent?: MixedObject, error?: MixedObject}>, }; diff --git a/src/index.test.js b/src/index.test.js index 0d4e472..88216c7 100644 --- a/src/index.test.js +++ b/src/index.test.js @@ -47,6 +47,7 @@ describe('index', () => { createPaymentMethod: jest.fn(), handleCardPayment: jest.fn(), handleCardSetup: jest.fn(), + handleCardAction: jest.fn(), }; window.Stripe = jest.fn().mockReturnValue(stripeMock); @@ -546,6 +547,26 @@ describe('index', () => { }); }); + describe('handleCardAction', () => { + it('should be called when set up properly', () => { + const Checkout = WrappedCheckout((props) => + props.stripe.handleCardAction('client_secret') + ); + const app = mount( + + + + Hello world + + + + + ); + app.find('form').simulate('submit'); + expect(stripeMock.handleCardAction).toHaveBeenCalledTimes(1); + expect(stripeMock.handleCardAction).toHaveBeenCalledWith('client_secret'); + }); + }); describe('errors', () => { describe('createSource', () => { it('should throw if no source type is specified', () => { From 952986b8095b88cd76261819342925b510a3a06e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20D=C4=85bek?= Date: Mon, 5 Aug 2019 16:06:56 +0200 Subject: [PATCH 2/2] update readme with handleCardAction --- README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/README.md b/README.md index cce5154..b61cf1d 100644 --- a/README.md +++ b/README.md @@ -174,6 +174,7 @@ injected component, you can call any of the following: - `this.props.stripe.createSource` - `this.props.stripe.handleCardPayment` - `this.props.stripe.handleCardSetup` +- `this.props.stripe.handleCardAction` Calling any of these methods will collect data from the appropriate Element and use it to submit payment data to Stripe. @@ -219,6 +220,11 @@ class CheckoutForm extends React.Component { // https://stripe.com/docs/stripe-js/reference#stripe-handle-card-setup this.props.stripe.handleCardSetup('{PAYMENT_INTENT_CLIENT_SECRET}', data); + // You can also use handleCardAction with the SetupIntents API. + // See our handleCardAction documentation for more: + // https://stripe.com/docs/stripe-js/reference#stripe-handle-card-action + this.props.stripe.handleCardAction('{PAYMENT_INTENT_CLIENT_SECRET}'); + // You can also use createToken to create tokens. // See our tokens documentation for more: // https://stripe.com/docs/stripe-js/reference#stripe-create-token @@ -734,6 +740,12 @@ type FactoryProps = { setupIntent?: Object, error?: Object, }>, + handleCardAction: ( + clientSecret: string + ) => Promise<{ + paymentIntent?: Object, + error?: Object, + }>, // and other functions available on the `stripe` object, // as officially documented here: https://stripe.com/docs/elements/reference#the-stripe-object },