Skip to content
This repository has been archived by the owner on Mar 27, 2021. It is now read-only.

Add support for handleCardAction #399

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
},
Expand Down
4 changes: 3 additions & 1 deletion src/components/inject.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ type WrappedStripeShape = {
createPaymentMethod: Function,
handleCardPayment: Function,
handleCardSetup: Function,
handleCardAction: Function,
};

type State = {stripe: WrappedStripeShape | null};
Expand Down Expand Up @@ -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'),
};
}

Expand Down Expand Up @@ -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.
Expand Down
16 changes: 16 additions & 0 deletions src/components/inject.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ describe('injectStripe()', () => {
let createPaymentMethod;
let handleCardPayment;
let handleCardSetup;
let handleCardAction;
let elementMock;
let rawElementMock;

Expand All @@ -22,6 +23,7 @@ describe('injectStripe()', () => {
createPaymentMethod = jest.fn();
handleCardPayment = jest.fn();
handleCardSetup = jest.fn();
handleCardAction = jest.fn();
rawElementMock = {
_frame: {
id: 'id',
Expand Down Expand Up @@ -52,6 +54,7 @@ describe('injectStripe()', () => {
createPaymentMethod,
handleCardPayment,
handleCardSetup,
handleCardAction,
},
getRegisteredElements: () => [elementMock],
};
Expand Down Expand Up @@ -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(<Injected />, {
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);

Expand Down Expand Up @@ -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');
});
});
});
3 changes: 3 additions & 0 deletions src/decls/Stripe.js
Original file line number Diff line number Diff line change
Expand Up @@ -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}>,
};
21 changes: 21 additions & 0 deletions src/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ describe('index', () => {
createPaymentMethod: jest.fn(),
handleCardPayment: jest.fn(),
handleCardSetup: jest.fn(),
handleCardAction: jest.fn(),
};

window.Stripe = jest.fn().mockReturnValue(stripeMock);
Expand Down Expand Up @@ -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(
<StripeProvider apiKey="pk_test_xxx">
<Elements>
<Checkout>
Hello world
<CardElement />
</Checkout>
</Elements>
</StripeProvider>
);
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', () => {
Expand Down