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
},
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', () => {