0

I am trying to follow the guide here ( https://stripe.com/docs/stripe-js/elements/payment-request-button ) to setup Apple Pay for the web and Stripe. The initial steps such as verification of domain and all the pre-setup is done but I am having an issue following the steps for the payment.

The Apple Pay Button is showing up in my Safari browser. When the button is clicked, I fire an event called checkoutWithApplePay(). I get lost after step 3 and not sure what to do. I am posting to my backend and on the backend, creating a payment intent and returning the client_secret

checkoutWithApplePay() {
    // STEP 1 FROM GUIDE
    const stripe = Stripe("_____");
    
    // STEP 2 FROM GUIDE
    const paymentRequest = stripe.paymentRequest({
        country: 'US',
        currency: 'usd',
        total: {
            label: 'Store Total',
            amount: cartTotal() ,
        },
        requestPayerName: true,
        requestPayerEmail: true,
    });
    
    
    // STEP 3 FROM GUIDE
    const elements = stripe.elements();
    const prButton = elements.create('paymentRequestButton', {
        paymentRequest: paymentRequest,
    });
    
    paymentRequest.canMakePayment().then(function(result) {
        if (result) {
            prButton.mount('#payment-request-button');
        } else {
            document.getElementById('payment-request-button').style.display = 'none';
        }
    });
    
    // STEP 4 FROM GUIDE -- THIS RETURNS A CLIENT SECRET
    axios.post('/api/checkout/checkout-with-apple-pay-web', {
        total: this.formattedCartTotal()
    })
    .then((resp) => {
          myClientSecrent = resp.clientSecret;
    });

    // THIS IS WHERE I GET CONFUSED AND NOT SURE HOW TO HANDLE AND BELOW IS 
    JUST TEMPLATE CODE FROM THE GUIDE
    
    paymentRequest.on('paymentmethod', function(ev) {
        // Confirm the PaymentIntent without handling potential next actions (yet).
        stripe.confirmCardPayment(
        clientSecret,
        {payment_method: ev.paymentMethod.id},
        {handleActions: false}
        ).then(function(confirmResult) {
        if (confirmResult.error) {
            // Report to the browser that the payment failed, prompting it to
            // re-show the payment interface, or show an error message and close
            // the payment interface.
            ev.complete('fail');
        } else {
            // Report to the browser that the confirmation was successful, prompting
            // it to close the browser payment method collection interface.
            ev.complete('success');
            // Check if the PaymentIntent requires any actions and if so let Stripe.js
            // handle the flow. If using an API version older than "2019-02-11" instead
            // instead check for: `paymentIntent.status === "requires_source_action"`.
            if (confirmResult.paymentIntent.status === "requires_action") {
            // Let Stripe.js handle the rest of the payment flow.
            stripe.confirmCardPayment(clientSecret).then(function(result) {
                if (result.error) {
                    let data = {
                        msg: "An error occurred. Please try again."
                    }
                    this.handleShowFlashMsg(data);
                } else {
                    this.handleShowOrderConfirmModal();
                }
            });
            } else {
            // The payment has succeeded.
            }
        }
    });
}

1 Answers1

0

You're almost there. When you get the 'paymentmethod' event you would use the PaymentIntent client secret you retrieved earlier to confirm the PaymentIntent and complete the payment:

    let clientSecret;

    axios.post('/api/checkout/checkout-with-apple-pay-web', {
        total: this.formattedCartTotal()
    }).then((resp) => {
      // Assign this previously defined variable
      clientSecret = resp.clientSecret;
    });

    paymentRequest.on('paymentmethod', function(ev) {
        // Confirm the PaymentIntent without handling potential next actions (yet).
        stripe.confirmCardPayment(
        clientSecret,
        {payment_method: ev.paymentMethod.id},
        {handleActions: false}
        ).then(function(confirmResult) {
        if (confirmResult.error) {
            // Report to the browser that the payment failed, prompting it to
            // re-show the payment interface, or show an error message and close
            // the payment interface.
            ev.complete('fail');
        } else {
            // Report to the browser that the confirmation was successful, prompting
            // it to close the browser payment method collection interface.
            ev.complete('success');
            // Check if the PaymentIntent requires any actions and if so let Stripe.js
            // handle the flow. If using an API version older than "2019-02-11" instead
            // instead check for: `paymentIntent.status === "requires_source_action"`.
            if (confirmResult.paymentIntent.status === "requires_action") {
            // Let Stripe.js handle the rest of the payment flow.
            stripe.confirmCardPayment(clientSecret).then(function(result) {
                if (result.error) {
                    let data = {
                        msg: "An error occurred. Please try again."
                    }
                    this.handleShowFlashMsg(data);
                } else {
                    this.handleShowOrderConfirmModal();
                }
            });
            } else {
            // The payment has succeeded.
            }
        }
    });

Paul Asjes
  • 3,717
  • 1
  • 10
  • 14
  • thanks @paul . How does that event listener getting fired though ( `paymentRequest.on('paymentmethod', ...)` ? The only thing that comes back from the axios request is the clientSecret so what triggers that event listener? – Henry Macrinitz Nov 25 '20 at 15:33
  • That event is triggered when your user has completed the Payment Request modal, which itself is triggered when they click the Payment Request button. Stripe automatically adds the event listener in the `prButton.mount('#payment-request-button');` line. – Paul Asjes Nov 26 '20 at 00:16