Esteban Vargas
Esteban Vargas

Reputation: 594

Is it possible to create a Subscription using Stripe Elements?

I've created a checkout form using Stripe Elements because I want to use those pre-built UI components. I've followed this example and when you use a clientSecret obtained from generating a paymentIntent, it works great.

Now, I want to create not a one-time purchase, but a monthly/yearly subscription. This subscription can vary in $$ amount based on certain parameters that the user inputs through the UI.

I have two doubts about this:

  1. What should I use as the clientSecret? I see that the subscription object is more complex and has more props, but I see no equivalent.

  2. In the example they have the following flow for confirming/rejecting the payment using Elements. Is inserting the subscription creation here the way to go?

CheckoutForm.js:

const { error } = await stripe.confirmPayment({
  //`Elements` instance that was used to create the Payment Element
  elements,
  confirmParams: {
    return_url: "https://example.com/order/123/complete",
  },
});
if (error) {
  // This point will only be reached if there is an immediate error when
  // confirming the payment. Show error to your customer (for example, payment
  // details incomplete)
  setErrorMessage(error.message);
} else {
  // Your customer will be redirected to your `return_url`. For some payment
  // methods like iDEAL, your customer will be redirected to an intermediate
  // site first to authorize the payment, then redirected to the `return_url`.
  
  console.log("Payment confirmed!");
  await createStripeSubscription(subscriptionPrice, interval);
}

createSubscription.ts:

export default async function createStripeSubscription(paymentAmount, paymentInterval) {
  const lowerCasePaymentInterval = paymentInterval.toLowerCase();
  console.log("createSubscription.ts - lowerCasePaymentInterval", lowerCasePaymentInterval);
  stripe.products
    .create({
      name: `$${paymentAmount} ${lowerCasePaymentInterval} Subscription`,
      description: `$${paymentAmount} ${paymentInterval} subscription`,
    })
    .then((product) => {
      console.log("createSubscription.ts - product", product);
      stripe.prices
        .create({
          unit_amount: paymentAmount * 100, // this unit is cents, not dollars
          currency: "usd",
          recurring: {
            interval: lowerCasePaymentInterval,
          },
          product: product.id,
        })
        .then((price) => {
          console.log(
            "Success! Here is your starter subscription product id: " +
              product.id
          );
          console.log(
            "Success! Here is your premium subscription price id: " + price.id
          );
        }).catch((err) => {
          console.log("createSubscription.ts - err", err);
        });
    });
}

Upvotes: 0

Views: 799

Answers (1)

koopajah
koopajah

Reputation: 25552

The Subscription will create an Invoice on each cycle (both on Subscription creation and each cycle such as month after that). The Invoice will have a PaymentIntent associated with it if the Invoice is not for $0 (such as a trial period would be).

This means that on Subscription creation, you need to find the most recent Invoice (the first one really) associated with it which is available in latest_invoice. And that Invoice will have a payment_intent property set to the id of the associated PaymentIntent.

Then you can use Stripe's feature called Expand to create the Subscription and get all of those objects at the same time so that you can directly access the underlying PaymentIntent's client_secret.

Note that if your Subscription does not require a payment upfront (such as a 100% off coupon or a trial period) there won't be a PaymentIntent. Since you'll still want to collect payment method details, you still need a client_secret. In that case, you should use at the SetupIntent's client_secret that Stripe creates for you. It is available in pending_setup_intent on the Subscription.

This is all covered in details in Stripe's quickstart for Subscriptions here.

It's also important to understand that you never create the PaymentIntent or the SetupIntent yourself in that case. You create the Subscription and Stripe does the rest for you automatically.

Upvotes: 1

Related Questions