Skip to content

Commit

Permalink
Uses stripe.handleNextAction for payment intents
Browse files Browse the repository at this point in the history
  • Loading branch information
chrissrogers committed Dec 4, 2024
1 parent 6b9d477 commit 3642335
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 9 deletions.
34 changes: 30 additions & 4 deletions lib/recurly/risk/three-d-secure/strategy/stripe.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const debug = require('debug')('recurly:risk:three-d-secure:stripe');
export default class StripeStrategy extends ThreeDSecureStrategy {
static libUrl = 'https://js.stripe.com/v3/';
static strategyName = 'stripe';
static PAYMENT_INTENT_STATUS_SUCCEEDED = 'succeeded';

constructor (...args) {
super(...args);
Expand Down Expand Up @@ -40,15 +41,40 @@ export default class StripeStrategy extends ThreeDSecureStrategy {

this.whenReady(() => {
const isPaymentIntent = this.stripeClientSecret.indexOf('pi') === 0;
const handleAction = isPaymentIntent ? this.stripe.handleCardAction : this.stripe.confirmCardSetup;

handleAction(this.stripeClientSecret).then(result => {
const handleResult = result => {
if (result.error) {
throw result.error;
}
const { id } = result.paymentIntent || result.setupIntent;
this.emit('done', { id });
}).catch(err => this.threeDSecure.error('3ds-auth-error', { cause: err }));
};
const handleError = err => this.threeDSecure.error('3ds-auth-error', { cause: err });

(() => (
isPaymentIntent
? this.stripe.handleNextAction({ clientSecret: this.stripeClientSecret })
: this.stripe.confirmCardSetup(this.stripeClientSecret)
))()
.then(handleResult)
.catch(err => {
// Handle a Payment Intent which has already had its action handled and succeeded
if (err.name === 'IntegrationError') {
return this.stripe.retrievePaymentIntent(this.stripeClientSecret)
.then(result => {
if (result.error) {
throw result.error;
}

const { next_action: nextAction, status } = result.paymentIntent || result.setupIntent;
if (!nextAction && status === StripeStrategy.PAYMENT_INTENT_STATUS_SUCCEEDED) {
return handleResult(result);
}
})
.catch(handleError);
}

return handleError(err);
});
});
}

Expand Down
2 changes: 1 addition & 1 deletion test/unit/risk/three-d-secure.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ describe('ThreeDSecure', function () {
{ id: 'action-token-adyen', strategy: AdyenStrategy },
{ id: 'action-token-braintree', strategy: BraintreeStrategy },
{ id: 'action-token-sage-pay', strategy: SagepayStrategy },
{ id: 'action-token-stripe', strategy: StripeStrategy },
{ id: 'action-token-stripe-pi', strategy: StripeStrategy },
{ id: 'action-token-test', strategy: TestStrategy },
{ id: 'action-token-wirecard', strategy: WirecardStrategy },
{ id: 'action-token-worldpay', strategy: WorldpayStrategy }
Expand Down
8 changes: 4 additions & 4 deletions test/unit/risk/three-d-secure/strategy/stripe.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ describe('StripeStrategy', function () {
setupIntent: { id: 'seti-test-id', test: 'result', consistingOf: 'arbitrary-values' }
};
this.stripe = {
handleCardAction: sinon.stub().resolves(this.paymentIntentResult),
handleNextAction: sinon.stub().resolves(this.paymentIntentResult),
confirmCardSetup: sinon.stub().resolves(this.setupIntentResult)
};
window.Stripe = sinon.spy(publishableKey => this.stripe);
Expand Down Expand Up @@ -78,8 +78,8 @@ describe('StripeStrategy', function () {
it('instructs Stripe.js to handle the card action using the client secret', function () {
const { strategy, target, stripe } = this;
strategy.attach(target);
assert(stripe.handleCardAction.calledOnce);
assert(stripe.handleCardAction.calledWithExactly('pi-test-stripe-client-secret'));
assert(stripe.handleNextAction.calledOnce);
assert(stripe.handleNextAction.calledWithExactly({ clientSecret: 'pi-test-stripe-client-secret' }));
});

it('emits done with the paymentIntent result', function (done) {
Expand All @@ -95,7 +95,7 @@ describe('StripeStrategy', function () {
beforeEach(function () {
const { strategy } = this;
this.exampleResult = { error: { example: 'error', for: 'testing' } };
strategy.stripe.handleCardAction = sinon.stub().resolves(this.exampleResult);
strategy.stripe.handleNextAction = sinon.stub().resolves(this.exampleResult);
});

it('emits an error on threeDSecure', function (done) {
Expand Down

0 comments on commit 3642335

Please sign in to comment.