#Namrata
1 messages ยท Page 1 of 1 (latest)
(index):1 Uncaught IntegrationError: Invalid value for elements(): clientSecret should be a client secret of the form ${id}secret${secret}. You specified: .
getting this error when i am passing client secret form controller to ajax call the assign this this value hidden input field then in option to element i am using like below
are you setting up a Payment Intent or a Setup Intent?
const options = {
clientSecret: $("#clientSecreat").val(),
// Fully customizable with appearance API.
appearance: {/.../},
};
paymentIntent
could you please provide the payment intent id and the secret you're getting?
pi_3L2sv6Kz8WXEqDYJ2p0GScV9_secret_CpBWTQBGC0XRwnA7K32iuP5rA
are you setting a default value for that hidden input?
or maybe not setting a value at all?
then how to set value
can you share your code?
var stripe = Stripe('key');
const options = {
clientSecret: $("#clientSecreat").val(),
// Fully customizable with appearance API.
appearance: {/.../},
};
const elements = stripe.elements(options);
// Create and mount the Payment Element
const paymentElement = elements.create('payment');
paymentElement.mount('#payment-element');
const form = document.getElementById('payment-form');
form.addEventListener('submit', async (event) => {
event.preventDefault();
const {error} = await stripe.confirmPayment({
//Elements instance that was used to create the Payment Element
elements,
});
if (error) {
const messageContainer = document.querySelector('#error-message');
messageContainer.textContent = error.message;
} else {
}
});
<form id="payment-form">
<input type="hidden" id="clientSecreat">
<div id="payment-element">
<!-- Elements will create form elements here -->
</div>
<button id="submit">Submit</button>
<div id="error-message">
<!-- Display error message to your customers here -->
</div>
</form>
where are you setting the value of clientSecret?
are you doing an ajax call to your backend to get the clientSecret?
yes
could you share that bit of code?
yes
Stripe\Stripe::setApiKey(env('STRIPE_SECRET'));
$intent = \Stripe\PaymentIntent::create([
"amount" => $request->Price100,
"currency" => $request->stripeCurrency,
]);
$data = [
"amount" => $request->Price100,
'client_secret'=> $intent->client_secret,
];
return response()->json($data);
no I mean the ajax call on the front-end
yes
var price=$("#FinalTotal").text().replace(/[^\d.]/g, '');
var stripeCurrency=$("#stripeCurrency").val();
MakePaymentIntent.append('Price',price);
MakePaymentIntent.append('stripeCurrency',stripeCurrency);
var headers = {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
$.ajax({
type: "POST",
url: "/MakePaymentIntent",
data: MakePaymentIntent,
processData: false,
contentType: false,
headers: headers,
success: function(response){
console.log(response);
$("#clientSecreat").val(response.client_secret);
$("#makePaymentScreen").show();
}
});
where is that call executed?
on click of button
before or after the previous front-end code you sent?
before
would it be possible to share the file that contains the whole front-end code for this ?
the secret will always be null since the execution of the const options =... is being executed before the success of the ajax call
then how to handle this
you could do that chunk of the code within the success function of your ajax call
var options = {
clientSecret: $("#clientSecreat").val(),
// Fully customizable with appearance API.
appearance: {/.../},
};
means this code within ajax success
all of this
const options = {
clientSecret: $("#clientSecreat").val(),
// Fully customizable with appearance API.
appearance: {},
};
const elements = stripe.elements(options);
// Create and mount the Payment Element
const paymentElement = elements.create('payment');
paymentElement.mount('#payment-element');
const form = document.getElementById('payment-form');
form.addEventListener('submit', async (event) => {
event.preventDefault();
const {error} = await stripe.confirmPayment({
//Elements instance that was used to create the Payment Element
elements,
});
if (error) {
const messageContainer = document.querySelector('#error-message');
messageContainer.textContent = error.message;
} else {
}
});```
did it work?
let me check it
hello
it working but getting below error
Uncaught (in promise) IntegrationError: stripe.confirmPayment(): the confirmParams.return_url argument is required unless passing redirect: 'if_required'
at _ ((index):1:90912)
at (index):1:294668
at e.<anonymous> ((index):1:295162)
at e.confirmPayment ((index):1:129881)
at HTMLFormElement.<anonymous>
//Elements instance that was used to create the Payment Element
elements,
});```
you need to add return_url
https://stripe.com/docs/js/payment_intents/confirm_payment
Hey, taking over here. Let me know if there's any follow-up Qs I can answer!
Can you share the code you're calling that is throwing the error?
yes
Are you able to post it here? I can't really help any further without seeing the code you're calling!
form.addEventListener('submit', async (event) => {
event.preventDefault();
const {error} = await stripe.confirmPayment({
//Elements instance that was used to create the Payment Element
elements,
confirmParams: {
// Return URL where the customer should be redirected after the PaymentIntent is confirmed.
return_url: 'myurl',
},
});
if (error) {
const messageContainer = document.querySelector('#error-message');
messageContainer.textContent = error.message;
} else {
}
});
but i want to use stripe.confirmCardPayment
with payment-element element
You can't
but why
Not with the Payment Element
Because the Payment Element supports a number of non-card payment methods, hence the generic confirmPayment function
Can you share the error you're seeing? Your code seems ok to me
i am using this code in ajax success after that when user click on pay button i want to show 3DS screen to user
confirmPayment will handle any required 3DS actions for you
But you need to use a specific test card that requires authentication. Which card are you testing with?
4242 4242 4242 4242
Yep, that card requires no 3DS/auth action (so the UI won't present itself). The payment will go through
You should use 4000002760003184 instead: https://stripe.com/docs/testing#regulatory-cards
return_url: 'url',
return_url will need to be a valid URL, i.e. https://stripe.com
is return url is mandatory because i dont want to refresh my page due to this i lost my varaiable
That's where your user will be sent back to after completing the 3DS/auth challenge flow
After after completing the 3DS/auth i want to show payment success screen in same page without reload page can we do like this
You can't, no. Not without implementing the 3DS flow in some kind of iframe: https://stripe.com/docs/payments/3d-secure#custom-iframe
for return_url can we write ajax call to redirect to success page
It needs to be a valid URL. Why can't you just pass the success page URL there?
because after payment success i want download some file send invoice to user
My recommendation would be to pass a URL to return_url which is your success page, but for the post-payment actions instead utilise webhooks
So you'd listen for payment_intent.succeeded events and send the corresponding emails with the file/invoice
There's no guarantee your user will ever reach the return_url โ they close the window before they're redirected
You'd create a webhook handler in your backend/server. See: https://stripe.com/docs/webhooks/quickstart
so confusing i didnot understand anythings
This is a good introductory guide to webhooks for after payment actions: https://stripe.com/docs/payments/handling-payment-events
How do you mean?
You'd need to configure the Element with your own CSS: https://stripe.com/docs/js/appendix/style
It's not really possible to have that layout with the CardElement though
okay