0
votes

I am creating a Stripe PaymentIntent on the server and retrieving its client secret to the Expo React-Native app. Before migrating to PaymentIntents I was using expo-payments-stripe and its PaymentStripe object to execute paymentRequestWithCardFormAsync and get the token which was helping me to charge the client's card without having a PaymentIntent.

Now with the PaymentIntent, the scenario is different. I don't need the token anymore but I need PaymentMethodId in order to confirm the intent (if I want to do it on the server). When the client is new though, I don't have his PaymentMethod and in order to receive it, the first PaymentIntent should be confirmed on the client-side. In another case when using a web client, I managed to get the Stripe Elements and with it, I was able to confirm the PaymentIntent client side. I don't find any similar library though for Expo React-Native application which to be able to confirm the payment intent.

Does anyone know how can I achieve that? Thanks in advance.

1
There is unfortunately no good story for Stripe on React Native. The closest thing is the 3rd party library tipsi-stripe: github.com/tipsi/tipsi-stripePaul Asjes
Thanks, @PaulAsjes. I knew about tipsi-stripe, though unfortunately, I don't know how to use it with Expo React-Native app. Maybe I am missing something here.Kalin Krastev

1 Answers

2
votes

I'm using stripe with expo. There is not a library for expo. What I had to do is to create a webview to use the web packages of stripe. this is an example:

This is the webview, I render the HTML where I use stripe and I call "window.ReactNativeWebView.postMessage" to communicate the webview with the app.

 <WebView
        originWhitelist={["*"]}
        source={{ html: renderHtml(user,token) }}
        ref={webviewRef}
        onError={(syntheticEvent) => {
          const { nativeEvent } = syntheticEvent;
          console.warn('WebView error: ', nativeEvent);
        }}
        injectedJavaScript={javascriptAfterLoad()}
        onLoad={() => onLoadWebView()}
        onMessage={(event) => {
          let data = JSON.parse(event.nativeEvent.data);
          console.log("Esta es la data");
          console.log(data);
          switch (data.action) {
            case "subscribe":
         
              subscribe(data.data);

              break;

              case "retry":
            

                retryInvoiceWithNewPaymentMethod(data.data)
                

              break;

            default:
              console.log("ninguna accion");
              break;
          }

        }}
        style={{ marginTop: 20 }}
      />

this is the HTML:

const renderHtml = (user,userToken) => {

  return /*html*/ `
    <html>

    <head>
        <title>Checkout</title>
        <meta name="viewport" content="width=device-width, initial-scale=1" />
    
        <link rel="stylesheet" href="./assets/normalize.css" />

        <script src="https://js.stripe.com/v3/"></script>
        <link rel="stylesheet" href="StripeElements.css">

        <style>
          ${globalCss()}
        </style>
    </head>
    
    <body style="width:100%;height:100%;">
    <div style="padding:0px 20px;">
    <h2 style="font-size:16px;margin-bottom:20px;">Empieza la membresía ahora y forma parte de nuestra comunidad de profesionales</h2>
    <h4>Beneficios:</h4>
    <ul>
    <li>Ten a tu disposición nuestra base de datos de profesionales de todas las áreas. </li>
    <li style="margin-top:10px;">Ofrece tus servicios y empieza a aumentar tus ingresos exponencialmente. </li>
    </ul>

    <h1 style="font-size:20px;">Ingresa tu número de tarjeta:</h1>
    <form id="subscription-form">
    <div id="card-element" class="MyCardElement">
        <!-- Elements will create input elements here -->
    </div>

    <!-- We'll put the error messages in this element -->
    <div id="card-errors" role="alert"></div>
    <button id="submit-premium" type="submit" style="margin-top:20px;"


    >
    
  
    <div class="">
    <div id="loading" class="hidden">Subscribing...</div>
    <span id="button-text" class="">  Empezar Membresía - US$14/año</span>
  </div>
    </button>
</form>
    
    </div>
    
    
       
        <script defer>

          try{
            var customerId = '${user.customerId}'
            

          }catch(err){
            alert(err)
          }
        
        ${globalJS(userToken)}
    
    
            var stripe = Stripe('STRIPE_API');
            var elements = stripe.elements();
    
          
            var style = {
                base: {
                    color: "#32325d",
                    fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
                    fontSmoothing: "antialiased",
                    fontSize: "16px",
                    "::placeholder": {
                        color: "#aab7c4"
                    }
                },
                invalid: {
                    color: "#fa755a",
                    iconColor: "#fa755a"
                }
            };
    
            var card = elements.create("card", { style: style });
            card.mount("#card-element");
            card.on('change', showCardError);
    
            function showCardError(event) {
                let displayError = document.getElementById('card-errors');
                if (event.error) {
                    displayError.textContent = event.error.message;
                } else {
                    displayError.textContent = '';
                }
            }
    
    
            var form = document.getElementById('subscription-form');
    
    
            form.addEventListener('submit', function (ev) {
                ev.preventDefault();
          
              
             
                // If a previous payment was attempted, get the latest invoice
                const latestInvoicePaymentIntentStatusKey = null; //get paymentintent from localstorage

             

            
                if (latestInvoicePaymentIntentStatus === 'requires_payment_method'  ) {
                    const isPaymentRetry = true;
                    // create new payment method & retry payment on invoice with new payment method

                
                    
                 try{

                  createPaymentMethod({
                        card,
                        isPaymentRetry,
                        invoiceId:latestInvoiceId,
                    });
                 }catch(err){
                   alert(err.message)
                 }
                 finally{
                      
                    }
                   
                } else {
                    // create new payment method & create subscription
                    try{
                      createPaymentMethod({ card,customerId });

                    }catch(err){
                      alert(err.message)
                    }
                    finally{
                      
                    }
                    
                }
            });
    
    
         
    
        </script>
    </body>
    
    
    </html>
    `;