#alexconstantin_code
1 messages ยท Page 1 of 1 (latest)
๐ Welcome to your new thread!
โฒ๏ธ We'll be here soon! Typically we respond in a few minutes, but sometimes we might take a bit longer if the server is busy or if you have a particularly tricky question.
โฑ๏ธ We close idle threads, which makes them read-only. Once a thread is closed it won't be reopened, but you can always start a new thread if you have another question.
๐ This thread will always be available, even after it's closed. You can find it again using Discord's search, or you can save this link: https://discord.com/channels/841573134531821608/1422649346939424808
๐ Have more to share? Add more details, code, screenshots, videos, etc. below.
hello! looking at this now
hei! thank you!
can you explain why you are doing this await elements.submit(); at the start of the function? i'm guessing that's why it's submitting twice
hold on
you're collecting payment before confirming right?
I copy pasted from the documentation. The submit function is called there
sorry it's been a while since i've looked at that flow haha
hmm, no. How do I do that? I assumed everything was displayed in the example. If it helps, I can share my whole JS function
<div id="express-checkout"></div>
<div id="error-message"></div>
<script>
const handleError = (error) => {
const messageContainer = document.querySelector('#error-message');
messageContainer.textContent = error.message;
console.error('Error:', error);
}
async function init() {
const stripe = Stripe("pk_test_...");
// Create Express Checkout Element BEFORE creating PaymentIntent
const options = {
mode: 'payment',
amount: 5000,
currency: 'eur',
appearance: {/* optional */}
};
const elements = stripe.elements(options);
const expressCheckout = elements.create('expressCheckout', {
emailRequired: true,
billingAddressRequired: true
});
expressCheckout.mount('#express-checkout');
expressCheckout.on('confirm', async (event) => {
const {error: submitError} = await elements.submit();
if (submitError) {
document.getElementById('error-message').textContent = submitError.message;
return;
}
// fetch client secret from your backend
const response = await fetch('<@ofbizUrl>stripeCreatePaymentIntent</@ofbizUrl>', {
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: new URLSearchParams({
currency: 'eur',
amount: 5000,
})
});
const data = await response.json();
const clientSecret = data.clientSecret;
const {error: confirmError} = await stripe.confirmPayment({
elements,
clientSecret,
confirmParams: {
return_url: 'https://your-site.com/complete'
},
});
if (confirmError) {
document.getElementById('error-message').textContent = confirmError.message;
}
});
}
init();
</script>```
and my /stripeCreatePaymentIntent endpoint is doing this in JAVA:
String customerId = dto.getCustomerId();
if (UtilValidate.isEmpty(customerId)) {
Customer customer = stripeClient.customers().create();
customerId = customer.getId();
}
EphemeralKey ephemeralKey = stripeClient.ephemeralKeys().create(
EphemeralKeyCreateParams.builder()
.setCustomer(customerId)
.setStripeVersion(VERSION)
.build());
PaymentIntent intent = stripeClient.paymentIntents().create(PaymentIntentCreateParams.builder()
.setAmount(Long.parseLong(dto.getAmount()))
.setCurrency(dto.getCurrency())
.setCustomer(customerId)
.setAutomaticPaymentMethods(PaymentIntentCreateParams.AutomaticPaymentMethods.builder().setEnabled(true).build())
.build());
var resp = new StripeCreateIntentRespDTO();
resp.setClientSecret(intent.getClientSecret());
resp.setEphemeralKey(ephemeralKey.getSecret());
resp.setCustomerId(customerId);
return resp;
}```
sorry for the unformatted code, I am new to Discord ๐
I haven't found a way to format it better
you're good! you can make it more readable by wrapping everything in triple backticks `
thanks for the tip!
can you add logic to handle submit errors?
if (submitError) {
console.log(submitError);
return;
}```
or something along those lines
and let me know if you're getting anything there
yes, sure, adding it now
nothing in the submitError
and for iOS it gets stuck in "Processing":
actually no
for iOS it seems to be working
so it's only google pay that has that problem
i'm assuming by iOS you mean apple pay?
no worries ๐ and yeah that's weird. let me look through your code a bit more
yes, sure
can you add logging at each step of your function? like logging the response from your server, logging the client secret, etc. just to make sure your function is reaching all of the steps and passing the right data into the next step
Hello
Taking a look
The code looks fine
Is it possible your page is getting re-rendered at any point after retrieving the client-secret?
nope, I am not using any frameworks such as React. It's plain old JS/ HTML code
what I did see, is that the click event gets triggered twice
I added the "click" listener and it gets called twice when I click the Google Pay button
maybe that breaks something in the process?
let me try to add that listener back to confirm it still happens
Hmm
Can you check if you're importing Stripe.js twice?
because I did went through a lot of trials today
the JS is loaded once
I am importing it like this:
<script src="https://js.stripe.com/v3/"></script>
you don't need / after /v3
click event gets triggered twice
and when I add this listener, the chrome google pay dialog is no longer showing
this is what I added
Can you try importing the newer API version Stripe JS?
<script src="https://js.stripe.com/basil/stripe.js"></script>
yes, sure. changing it now
yeah the dialogue won't show until you call elements.submit()
but in this case, adding the "click" listener doesn't trigger the "confirm" event, that calls the elements.submit() function
Right
I'm just talking about the code you've shared above
Do you have two expressCheckout.on('click',...) handlers?
nope, only one
I confirmed this in the view source
I copy pasted your exact code and ran a version locally
I'm only seeing one click event on my end
and you need to call event.resolve() to get the google pay modal to show up
adding event.resolve(); now
I am on Chrome (latest version) in MacOS
if that matters for anything
it's a pretty old setup but I am using Tomcat 9 to serve Freemarker rendered HTML files
Hmm, are you using VS Code? I wonder if you can try with the built-in server?
I added event.resolve() and indeed it now passes on and I see the chrome Google Pay dialog
I am using IntelliJ, but I am happy to give VS code a try
I'll download it now
I'm not familiar with IntelliJ much but if it has a built in server, you can also use that
huh that's very odd
I don't have ngrok, I served it locally
I can shared the html file
but
I can add ngrok as well
here it is
let me know if you want me to install ngrok in the meantime
hmm, actually you won't get the payment intent secret
I have adblock
it's the only one
I will disabled it and retry
no, I still get 2 clicks
Yeah I don't think that'd cause issues like double click events as such but yeah try without it
Also I think Google Pay is supported on Firefox too? If you have that, you can try there
do you also see the "Pay with link" option?
same here. that's crazy
I have a chrome update available, I will try to install it now
but besides the 2 click events
are you able to pay with google succesfully/
Since your API is local/unreachable, that part won't work but If I replace the clientSecret with just sample pi_secret_123, I do see the confirmPayment call erroring out with missing client-secret error (which is expected)
So I do see confirmPayment being called
can you please try with this clientSecret?
pi_3SD9MRQIdMaEOCEY1q3hA5bS_secret_GBvdFlaOu2nQsHbvha4gJ6bjn
I also see it getting called, but it's throwing that "you must call confirmPayment" error
yup, just did and you can prob see that it succeeded
(I disabled email and address collection for privacy reasons)
ok, in this case I believe there is something weird going on with those double events on my browser
and that is the issue
I will retry tomorrow from other devices too
thank you for your help! I really appreaciate it
Yeah, very odd issue!
NP ๐ Good luck