stripe / stripe-react-native

React Native library for Stripe.
https://stripe.dev/stripe-react-native
MIT License
1.27k stars 265 forks source link

How to set up subscriptions? #777

Closed alexandrebouttier closed 2 years ago

alexandrebouttier commented 2 years ago

Hello, in my expo react native mobile app I would like to set up monthly, yearly subscriptions, I created my products on the stripe dashboard, but I can't find any sample react native code to allow me to subscribe to his subscriptions

pratikdhody commented 2 years ago

I was stuck as it wasn't clear either. All info is here; https://stripe.com/docs/payments/save-and-reuse

hatem-72 commented 2 years ago

Even after reading the documentation linked above it is not clear to me at all how to use this library to manage recurring billing purchases... I mean I can't find any exemple of how to reconcile the use of paymentSheet (with purchase/pay button, not "Set up") and a call to the server creating a subscription (passing a priceId and a paymentMethodId).

bensnell-stripe commented 2 years ago

I recommend giving a read through https://stripe.com/docs/billing/subscriptions/build-subscriptions?ui=elements and replacing the parts that discuss using the Payment Element with using the Payment Sheet.

hatem-72 commented 2 years ago

@bensnell-stripe Thanks for the quick reply! From what I just read it seems much clearer. Creating an incomplete subscription first is a bit counterintuitive but then it makes possible to use the Payment Sheet normal workflow described in the documentation. Perfect.

hanza93 commented 2 years ago

@hatem-72 Hey! I'm stuck with the same issue, can you sure server code or write me an ordered steps to follow?

hatem-72 commented 2 years ago

Once customer has selected an offer:

  1. Pass the priceId to the server and ask it to create an incomplete subscription. You may need to create a Stripe customer first if it does not exist.
  2. Then server sends back to the client a secret materializing the payment intent. Use it to init and present the paymentSheet in you app.
  3. If payment succeed your are done for the front-side. For the server-side it is recommended to use the webhook integration to be notified that your subscription has been completed.
hanza93 commented 2 years ago

Hey! @hatem-72 Thanks for your response! I've followed your steps, yet the subscription is still not completed. my question should I update it to be completed on my own? or should stripe understand the flow and completed it for me.

I summarize my steps and please advise me:

create-subscription + paymentIntent

const subscription = await stripe.subscriptions.create({
    customer: customer.id,
    items: [
      {
        price: priceId,
      },
    ],
    payment_behavior: 'default_incomplete',
    expand: ['latest_invoice.payment_intent'],
  });
  ....
  const paymentIntent = await stripe.paymentIntents.create({
    amount,
    currency: 'eur',
    customer: customer.id,
    metadata: {
      subscriptionId: subscription.id,
      reason: 'subscription',
    },
    payment_method_types: [
      'card',
      'sepa_debit',
    ],
  });

Update subscription default method

On payment_intent.succeeded event I do

if (pi?.metadata?.subscriptionId) {
        const payment_intent = await stripe.paymentIntents.retrieve(pi.id);

        const subscription = await stripe.subscriptions.update(
          pi.metadata.subscriptionId,
          {
            default_payment_method: payment_intent.payment_method as string,
          }
        );
      }

btw, this update scenario is from their example here

hanza93 commented 2 years ago

just found my issue, No need to create a new payment intent I should use the same one created in the subscription subscription.latest_invoice.payment_intent.client_secret

hatem-72 commented 2 years ago

@hani-advocate Yes exactly 😇

pcatjee commented 1 year ago

@hanza93 a sample client-side code would have been helpful. Facing same issue.

Update: Thanks understood what you meant now. Working perfectly now.

samvoults commented 1 year ago

Can you please show code examples pls? I'm totally lost. The doc for React Native is just incomplete and after I created an incomplete subscription in the backend, I have no idea how to display the UI Element on my app to gather the user info and confirm the payment. Help pls.

gpawlik-cais commented 8 months ago

@hanza93 Would you be able to provide the code example please?

ta-sakin commented 6 months ago

just found my issue, No need to create a new payment intent I should use the same one created in the subscription subscription.latest_invoice.payment_intent.client_secret /update-subscription

this flow works for creating subscription any idea about upgrade or downgrading subscription?

elisabeth0bangoura commented 5 months ago

here is a full example for react-native expo and node.js Stripe product subscription

react-native frontend:

const fetchPaymentSheetParams = async () => {
  try {
      const response = await fetch('https://backend', {
          method: 'POST',
          headers: {
              'Content-Type': 'application/json',
          },
          body: JSON.stringify({ paymentMethodTypes: ['card'] }), // Replace 'your_payment_method_id' with the actual payment method id
      });
      const data = await response.json();
      console.log('Payment sheet params:', data); // Log the response data
      const { paymentIntent, customer } = data;

      return {
          paymentIntent,
          customer,
      };
  } catch (error) {
      console.error('Error fetching payment sheet params:', error);
      throw error;
  }

};

const initializePaymentSheet = async () => { try { const { paymentIntent, customer } = await fetchPaymentSheetParams();

      const { error } = await initPaymentSheet({
          merchantDisplayName: 'Example, Inc.',
          customerId: customer,
          paymentIntentClientSecret: paymentIntent,
          allowsDelayedPaymentMethods: true,
          defaultBillingDetails: {
              name: 'Jane Doe',
          },
      });
      if (!error) {
          setLoading(true);
      }
  } catch (error) {
      console.error('Error initializing payment sheet:', error);
  }

};

const openPaymentSheet = async () => { try { const { error } = await presentPaymentSheet();

      if (error) {
          console.log(`Error code: ${error.code}`, error.message);
      } else {
          Alert.alert('Success', 'Your order is confirmed!');
      }
  } catch (error) {
      console.error('Error opening payment sheet:', error);
  }

};

useEffect(() => { initializePaymentSheet(); }, []);

backend:

exports.firebase_function_example = functions.https.onRequest(async (req, res) => { try { if (req.method !== 'POST') { res.status(405).send('Method Not Allowed'); return; } const customer = await stripe.customers.create(); await stripe.paymentMethods.attach(req.body.paymentMethodId, { customer: customer.id }); await stripe.customers.update(customer.id, { invoice_settings: { default_payment_method: req.body.paymentMethodId } }); const subscription = await stripe.subscriptions.create({ customer: customer.id, items: [{ price: 'price_stripe_product_id' }], expand: ['latest_invoice.payment_intent'], });

    res.json({
        subscription: subscription.id,
        paymentIntent: subscription.latest_invoice.payment_intent.client_secret,
        customer: customer.id,
        publishableKey: 'your-stripe-pk-key'
    });

} catch (error) {
    console.error('Error creating subscription:', error);
    res.status(500).send('Error creating subscription');
}

});

myeh98 commented 5 months ago

I would love to add subscription upsells to my react native stripe experience that im building like https://docs.stripe.com/payment-links/promotions#subscription-upsells

Particularly, I want to enable the user to easily toggle between monthly and a discounted annual billing subscription for a discount. Are there any plans to support this? How have others enabled this in their React Native stripe apps?

kumarsoni7999 commented 4 months ago

I recommend giving a read through https://stripe.com/docs/billing/subscriptions/build-subscriptions?ui=elements and replacing the parts that discuss using the Payment Element with using the Payment Sheet.

This helped me to step up somehow

Maazasim1 commented 1 month ago

stripe has updated their billing API documentation for react native https://docs.stripe.com/billing/subscriptions/build-subscriptions?platform=react-native