7
votes

I've tried three different Stripe support people to get a clear answer on this. No-one seems to know how to solve this. I want to sign up a customer for a recurring subscription using Stripe. When selecting a plan, a credit card form is shown. Customers input credit card info and click Pay and the subscription is created.

I've done this using Stripe.js and tokens by adding a bit of JavaScript to my client:

function pay() {
    stripe.createToken(card).then(function (result) {
        if (result.error) {
            // Do something
        } else {
            var token = result.token.id;
            $.post("/api/subscriptions/create?token=" + token, ...);
        }
    });
}

On the server I put the token on the customer (examples in C# but could be anything):

customerService.Update(customerId, new CustomerUpdateOptions
{
    SourceToken = token,
});

and create a subscription:

var items = new List<SubscriptionItemOption> {
    new SubscriptionItemOption {
        PlanId = newPlanId,
    },
};
var subscriptionCreateOptions = new SubscriptionCreateOptions
{
    CustomerId = customerId,
    Items = items,
};
Subscription subscription = stripe.Subscriptions.Create(subscriptionCreateOptions);

Everything works as expected so far. Stripe automatically create an invoice for the first payment and creates an automatic charge. It also generates an invoice for the next month that looks fine.

I should be happy now but I'm not. When testing the code above, it doesn't work for cards requiring 3D secure and similar extended authentication checks. In that case, I get an error from Stripe when creating the subscription, saying that the card isn't valid (I guess since we never completed 3D secure authentication).

From what I can understand from the Stripe documentation, showing 3D secure authentication dialog will require me to use either Checkout or Intents API. I don't want to use Checkout, but the Intents API looks like the right choice.

Using intents, I need to ask for an intent first:

var createOptions = new PaymentIntentCreateOptions {
  Amount = 4900,
  Currency = "usd",
  PaymentMethodTypes = new List<string> { "card" }
};
paymentIntents.Create(createOptions);

This produces a client secret that I send back to my client. Rather than calling createToken. On the client, I call the handleCardPayment function, which shows the 3D secure modal in the case it is required:

stripe.handleCardPayment(
    clientSecret, cardElement
  ).then(function(result) {
    if (result.error) {
      // Display error.message in your UI.
    } else {
      $.post("/api/subscriptions/create?...");
    }
  });

The issue here is that handleCardPayment create a charge on the customer. I don't want that since I want to automatically invoice the customer each month.

Does anyone know if it is possible to show 3D secure (and similar) without using intents or at least without creating a charge? I've read similar questions, where people are recommending creating the charge, then creating a subscription with 1 month of trial. This doesn't have the effect that I want since that will create a charge the first month and an invoice with a charge the following months.

Basically, I just want the simplest possible solution that still shows the 3D secure dialog.

1

1 Answers

7
votes

Stripe is currently working on integrating PaymentIntents with Subscriptions, and plans to support that flow in April 2019. Once that's available, you're going to definitely want to use PaymentIntents. Since it's in the very near future, you may just want to wait until it's available.

If you need to get this working in the meantime, this guide walks you through setting up a subscription with an initial 3DS check. That is the recommended approach with the trial period that you're talking about.

UPDATE

The date of full specification for Payment Intent was moved to July 1, 2019 according to Stripe:

OFF-SESSION PAYMENTS WITH THE PAYMENT INTENTS API

Point 3 saying:

You will need to make incremental changes in order to claim exemptions and decrease the rate of authentication challenges required by your customers—this will be ready by July 1, 2019.

https://stripe.com/docs/strong-customer-authentication/migration#step-2