Zurdge
Zurdge

Reputation: 105

stripe-react-native | Pre-built UI and charge later

I'm following this guide - https://stripe.com/docs/payments/accept-a-payment?platform=react-native&ui=payment-sheet-custom

I'm trying to tweak the guide so that I can use the pre-built UI but I want to charge my customers later.

Annoyingly after presentPaymentSheet() is called the card is charged instantly however I want to charge the customer later after I've done some checking in the backend which will take a few hours/days.

Any advice would be greatly appreciated :)

Server

import Stripe from 'stripe';
import express from "express";
const app = express()
import bodyParser from "body-parser";
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())

const stripe = new Stripe('[API_KEY]',{
  apiVersion: '2020-08-27',
});

const port = 3000

var customer:Stripe.Response<Stripe.Customer>;
(async()=>{
  const _customer = await stripe.customers.retrieve("cus_KI8Y2B5gIU9nZI");
  if(_customer.deleted == true) throw new Error("Customer is deleted!");
  customer = _customer;
})();


app.post('/configure-paymentsheet', async (req, res) => {
  const ephemeralKey = await stripe.ephemeralKeys.create(
    {customer: customer.id},
    {apiVersion: '2020-08-27'}
  );
  const paymentIntent = await stripe.paymentIntents.create({
    amount: 299,
    currency: 'gbp',
    customer: customer.id,
    confirm:false,
    off_session:true
  });
  res.send({
    ephemeralKey: ephemeralKey.secret,
    paymentIntent: paymentIntent.client_secret,
    customer: customer.id
  })
});

app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`)
})

React Native

import React from 'react';
import { View, Button } from 'react-native';
import axios from "axios";
import { StripeProvider,  initPaymentSheet, presentPaymentSheet } from '@stripe/stripe-react-native';

export default class App extends React.Component{

  componentDidMount = ()=>{
    this.configurePaymentsheet()
  }
  private configurePaymentsheet = async()=>{
    const {data} = await axios.post("http://192.168.1.199:3000/configure-paymentsheet");
    const { error } = await initPaymentSheet({
      customerId: data.customer,
      customerEphemeralKeySecret: data.ephemeralKey,
      paymentIntentClientSecret: data.paymentIntent,
    });
    if(error){
      throw error;
    }
  }
  private openPaymentsheet = async()=>{
    const { error, paymentOption } = await presentPaymentSheet();

    if (error) {
      throw error
    }

  }
  render(){
    return(
      <StripeProvider
       publishableKey="[API_KEY]"
       urlScheme="localhost" // required for 3D Secure and bank redirects
     >
      <View>

      <Button title="Open payment" onPress={this.openPaymentsheet}/>

      </View>
      </StripeProvider>
    )
  }
}

Upvotes: 0

Views: 497

Answers (1)

Pompey
Pompey

Reputation: 1354

If your checks normally take less than 7 days you can place a hold on the card and capture the funds later after you have done your checks[1]. If you determine that you should not charge the customer, you can cancel the PaymentIntent that you used to hold the funds.

If your checks will take longer than 7 days, you will want to save the payment method and charge it later. Stripe has a “Set up future payments” tutorial for that flow[2], demonstrating how to collect the card details, save them, and charge the card after you have done your checks. Make sure to keep in mind the sections about off-session parameters and starting a recovery flow to give yourself the best chance at success when charging the card later and to allow your customers to respond if further action is needed from them.

[1]https://stripe.com/docs/payments/capture-later

[2]https://stripe.com/docs/payments/save-and-reuse?platform=react-native

Upvotes: 1

Related Questions