Help needed with integrating Stripe payments

Hi everyone

I’m really getting into working with APIs in Wappler and it’s going really well. @Hyperbytes tutorial on integrating Stripe has been very helpful but, unfortunately, the API he used is no longer an option because of the new SCA regulatations so I’ve been trying to implement another of their APIs myself. But I need some help.

I’m using the instructions from here: https://stripe.com/docs/payments/payment-intents/web

I’ve created the API Server Action and it’s talking to Stripe fine. It sends some info and gets back the response.

My page has a fairly long form on it to get lots of information from the visitor. The submit button then stores all this in the database and also executes the API Server Action to talk to Stripe.

My database insert works perfectly and is also inserting data returned by the Stripe API but I need their javascript to then run so that the card payment details modal is shown (I think that’s what should happen but can’t be sure as I keep getting errors).

The code I’m pasting is this (from Step 4 at the link above):

var cardholderName = document.getElementById('cardholder-name');
var cardButton = document.getElementById('card-button');
var clientSecret = cardButton.dataset.secret;

cardButton.addEventListener('click', function(ev) {
  stripe.handleCardPayment(
    clientSecret, cardElement, {
      payment_method_data: {
        billing_details: {name: cardholderName.value}
      }
    }
  ).then(function(result) {
    if (result.error) {
      // Display error.message in your UI.
    } else {
      // The payment has succeeded. Display a success message.
    }
  });
});

My form fields have the right IDs but I need to put the client secret in this line:

var clientSecret = cardButton.dataset.secret;

This is what’s driving me nuts! I’ve tried this:

var clientSecret = connDancerInsert.data.apiStripePaymentIntent.data.client_secret;

and this:

var clientSecret = '{{connDancerInsert.data.apiStripePaymentIntent.data.client_secret}}';

but neither work.

I’m sure it’s just a syntax issue but my javascript isn’t as good as it probably needs to be.

Can anyone give me a steer?

Cheers, Jon.

I really hope that Stripe or some other payment gateway integration into Wappler is still on the roadmap.

1 Like

I’m sure service-specific integration isn’t needed as the API actions work really well. I just need some quick help with getting this working.

That said, if they do add Stripe actions then I’m certainly not going to complain!

Do you have the secret saved in a server action ? It’s not clear from your post whether you do or do not. If you do, shouldn’t it be possible to set a variable in the server action and then refer to it in the app connect and bind it to your javascript?

I’m not familiar with javascript so I’m guessing.

Hey Jon,

Try this:

var clientSecret =  dmx.parse("connDancerInsert.data.apiStripePaymentIntent.data.client_secret");

–Ken

Thanks @mebeingken, sadly not working. Developer console says:

Uncaught IntegrationError: Invalid value for stripe.handleCardPayment intent secret: value should be a client_secret string. You specified: undefined.

If this script is running on page load, you might need to prevent it from running until the page finishes loading.

You can do this by wrapping with

$(document).ready(function(){
// your code
});

Can you show us a sample of what is stored in your database (and then used to populate client_secret) as it’s not clear if an existing client_secret key has been stored effectively.

The database is correctly storing the client secret:

pi_1FFccaFybVEIfVSlfM9GHeVU_secret_FDQl6LnKXxpj80OsJJ1T4CeHT

(I’ve changed some of the characters for security)

The “undefined” suggests the element being referenced does not exist… Maybe you can show us the json results from the console and the server connect action that calls for it?

Yep, that was my next troubleshooting question ! :slight_smile:

I’m currently integrating with Stripe PaymentIntents too through Wappler.
Just finished form design and validation, I’ll let you know if I managed to go further than you did.
(might not be before the middle of next week though)

Ooh, I’d be very interested to hear your progress, @jeoff75

@mebeingken - here are some screenshots. I also added some output in the HTML to try and see if the variable is showing but it doesn’t:

<p>Client Secret: {{connDancerInsert.data.apiStripePaymentIntent.data.client_secret}}</p>

I feel like I’m very close but just can’t crack it.

Okay so try this

var clientSecret =  dmx.parse("apiStripePaymentIntent.data.client_secret");

@mebeingken - tried that earlier and logged it but still undefined.

Okay… Have to rush out, but can look closely later if nobody else sees the mistake

1 Like

Okay, so you are setting a javascript variable clientSecret at the time the page loads, which would explain why undefined is returned because the apiStripePaymentIntent has not yet been set. So you need to get clientSecret set after the api has returned its results.

This first thing I would try is to not use the variable and use dmx.parse within the listener function like this:

var cardholderName = document.getElementById('cardholder-name');
var cardButton = document.getElementById('card-button');
// var clientSecret = cardButton.dataset.secret;

cardButton.addEventListener('click', function(ev) {
  stripe.handleCardPayment(
    dmx.parse("apiStripePaymentIntent.data.client_secret"), cardElement, {
      payment_method_data: {
        billing_details: {name: cardholderName.value}
      }
    }
  ).then(function(result) {
    if (result.error) {
      // Display error.message in your UI.
    } else {
      // The payment has succeeded. Display a success message.
    }
  });
});

This too may not get evaluated at the right time though…It works as a straight function, but I haven’t setup a listener with this.

So if that doesn’t work, you might tear apart the listener, and just call the function directly on success of the api call.

Thanks @mebeingken, you’re going down much the same path I have. I’ve tried your technique and also added a delay of 2 seconds so I know it’s fired after the API response but it’s still undefined.

How can I trigger something after the success of the API call? Does Wappler have such a feature?

You can use the on success of the action on your front end that calls the server action.

But where would I put the javascript?

Not sure I understand the question. And just so I’m clear…I have yet to implement this on my site, but I’ve done an integration of javascript with wappler elements, so I know there is a way. And I’m no javascript expert, just a copy/paste learner. :slight_smile:

In reading your link to Stripe, it seems that you will be calling a server action, which in turns calls stripe, etc. and then returns your client_secret. The on the front end, the javascript you posted is to be run…right?

So I’m suggesting, that your javascript still goes on the front end page, and that it is triggered to be run when the server call returns success. I would probably be removing the addEventListener stuff, and just leave the actual function, and then call that on success of your server connect action.

I think it would be something like:

function runStripe() {
stripe.handleCardPayment(
    dmx.parse("apiStripePaymentIntent.data.client_secret"), cardElement, {
      payment_method_data: {
        billing_details: {name: cardholderName.value}
      }
    }
  ).then(function(result) {
    if (result.error) {
      // Display error.message in your UI.
    } else {
      // The payment has succeeded. Display a success message.
    }
  });
}

which would be called with:

dmx-on:success="runStripe()"