#AlienSoft
1 messages ยท Page 1 of 1 (latest)
Hi ๐
Payment Intents are not related to products. But I think you would want to start by looking into payment links.
I'm basically having trouble displaying multiple payment methods i/e GBP and EUR
Where?
previously, I tried updating the payment intent with a new Price and currency which seems to be working, but that wasn't updating the UI where GBP works with cards/alipay/wechat and EUR works with iDEAL etc...
Those are currencies, not payment methods
payment intents are not related to prices
So I think you are confused about the objects you are working with here
Price records are specific to currency as well
ok, here's a simple scenario
i had a product with a GBP price and EUR price.
how do i go about showing that on my page
php/javascript
payment element
Okay so you set the currency on the Payment Intent. Each intent will be specific to one currency
Are you using Invoices?
yes. i'm able to update the intent with the correct currency.
but the UI of the elements do not get updated.
Because payment intents in themselves have no relationship to prices
how do i force the UI's to be re-populated?
Ah okya
You need to fetch updates: https://stripe.com/docs/js/elements_object/fetch_updates
This will update the Payment Element with changes from the Payment Intent
would that just trigger/raise an event that there has been an update on the INTENT or would it cause to re-fresh/reload the payment-elemnt DIV ?
๐ stepping in
When you say you "update the intent" do you mean you create a different Invoice? Can you provide a specific example I can look at so that we are on the same page?
Okay thanks so then you aren't using Products/Prices which you mentioned above and is a bit confusing.
So yeah, if you fetchUpdates you should see Payment Element update to use the newly available Payment Method types based on currency
Have you tried doing this yet?
ohh
i think im going in circles in terms of what I'm trying to achieve all week
everyone is telling me something differen.t
how do i sell a product with GBP and EUR ? it's that simple
Well let's back up then and make sure we have all the details of what you are trying to do.
You decide on what currency you are going to use when you create the PaymentIntent and render Payment Element. So you know ahead of time from your customer whether they want GBP or EUR, no?
i don't know ahead of time. That's the problem. They can select on the page GBP or EUR.
i think it's best if i show you the page: https://korgpamanager.com/v5test/buy/v4/
if you clicked the EUROPE vs International, the price changes between GBP and EUR also this updated the paymentIntent
but the UI elements are not rerendered accordingly
since when u select EUROPE it needs to populate iDeal etc...
this currently isn't using a PRODUCT from the dashboard. It's populating everything internally.
I thought, If i had a product, with GBP and EUR prices, then it would automatically RENDER the UI elements somehow by attaching the productID
which wouldn't require any paymentIntent currency/price updates etc..
Yep okay so when the customer clicks the "Europe" toggle you need to call your backend and update the PaymentIntent's currency
Then on the frontend you call fetchUpdates
Then you will see the UI update
ok trying fetchupdates now.. brb
Cannot read properties of undefined (reading 'getElement') ๐ค
Sounds like you don't have your elements object in-scope of that function
Where you are trying to call elements.fetchUpdates
on the EUROPE toggle
Can you show me your client-side code here?
The relevant parts that is
How/where are you initializing elements to begin with?
the elements obj is initialized in my checkout.js
but i'm trying to run the fetchUpdate from my frontend
so either I need to make it in to a function in my checkout.js and then call that from front end?
or I can add an Eventlistener that would raise the function from the checkout.js?
Sorry, I don't understand. You initialize elements in your frontend to render Payment Element. You don't initialize elements from your backend.
Can you share your client-side code?
async function initialize() {
const options = {
mode: 'payment',
amount: 12500,
currency: 'gbp',
// Fully customizable with appearance API.
appearance: {/*...*/},
};
//elements.update({locale: 'fr'});
// Set up Stripe.js and Elements to use in checkout form
const elements = stripe.elements(options);
//const linkAuthenticationElement = elements.create("linkAuthentication");
//linkAuthenticationElement.mount("#link-authentication-element");
const paymentElementOptions = {
layout: "tabs",
paymentMethodOrder: ['card', 'iDeal', 'Alipay', 'wechat_pay'],
fields: {
billingDetails: {
name: "auto",
email: "never",
address: {
country: 'never',
postalCode: 'never'
}
}
}
};
const paymentElement = elements.create("payment", paymentElementOptions);
paymentElement.mount("#payment-element");
}
that renders the initial element
Not the standard Payment Element flow
So you haven't even created your PaymentIntent when you render Payment Element here
yh i was told to use that If i wanted separate currencies.
Yeah that works fine for sure
Oh you are passing paymentElementOptions to your elements.create not the options object
That threw me off
Okay
i think it would be easier if you can INSPECT page on the browser, which would show you the .js stuff
might help
here's my INTENT:
$intent = \Stripe\PaymentIntent::create([
"amount" => ($amount) * 100,
"currency" => "gbp",
//"payment_method_types" => ["card"],
"payment_method_types" => ["card", "wechat", "alipay"],
//"automatic_payment_methods" => [
// "enabled" => true,
// ],
]);
So yeah basically in that initialize function you want an eventListener where you call your backend to update the currency and then after you return a successful response from your backend then you call fetchUpdates()
Then your elements object will be in-scope
Where did you put fetchUpdates currently?
currently fetchUpdate is a javascript on the onClick of the EUROPE tab
which is missing the ELEMENT OBJ as it's not in scope
Right so you either can make your elements object a global variable or you can move your eventListener into your initialize function
ok let me try a few things
document.addEventListener("tab1", handleUpdateUI);
document.addEventListener("tab2", handleUpdateUI);
function handleUpdateUI() {
console.log("imhere");
elements.fetchUpdates()
.then(function(result) {
// Handle result.error
});
}
doesn't that seem right?
not raising that event at all.... does it have to be a POST or something?
"tab1" and "tab2" is not a valid event listener. You need a type there like "click"
But you need to access the HTML element beforehand
I'd recommend reading through https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener
You can see an example there like: ```// Function to change the content of t2
function modifyText() {
const t2 = document.getElementById("t2");
const isNodeThree = t2.firstChild.nodeValue === "three";
t2.firstChild.nodeValue = isNodeThree ? "two" : "three";
}
// Add event listener to table
const el = document.getElementById("outside");
el.addEventListener("click", modifyText, false);```
oh i see
ok
ok so.. now it works! the event is fired but i still get an error
Cannot read properties of undefined (reading 'fetchUpdates')
eventhough my elements is a global var
let elements;
let paymentElement;
on top of .js page
Looking
Looks like you forgot to remove the const elements
Change that to just elements =
In order to call fetchUpdates, you must pass a valid PaymentIntent or SetupIntent client secret when creating the Elements group.
Also where are you actually calling your backend?
isn't there a way to fetch via php on server side? or must it be a front end thing
i/e when I'm updating the current on the paymentIntent. to also call fetchUpdates through php
lol okay now looking at your actual full JS code you are using deferred intent.
not much of a JS person, so please bare with me ๐
As you pass options to stripe.elements()
Okay sorry -- I should have caught that before.
So in this case you don't want to fetchUpdates since you aren't (or at least shouldn't) actually be creating a PaymentIntent on page load
Instead you want to use elements.update like we show here: https://stripe.com/docs/payments/accept-a-payment-deferred?type=payment#dynamic-updates
So try just replacing fetchUpdates with elements.update({currency: newCurrency});
๐ฎ
IT WORKS!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
WOW can't believe it after all week of trial and error ๐
ok now let's see if the actual payment works ๐
lol glad it is working
So when you call your backend now you need to indicate which currency should be used to create the PaymentIntent based on which tab was selected last
ok perfect so now i can switch between GBP / EUR currencies! thank you
final problem. seems with the confirmPayment
(index):1 Uncaught (in promise) IntegrationError: A valid Element name must be provided. Valid Elements are:
card, cardNumber, cardExpiry, cardCvc, postalCode, paymentRequestButton, iban, idealBank, p24Bank, auBankAccount, fpxBank, affirmMessage, afterpayClearpayMessage, paymentMethodMessaging; you passed: payment-element.
From a brief look at your code I don't see where you are actually calling your backend
And why are you doing var paymentElement = elements.getElement('payment-element'); paymentElement.update({business: {name: 'Stripe Shop'}});
that was from the STRIPE template
now i was asking my self why is there a BUSINESS name update ๐
ok now i removed those and get
IntegrationError: elements.submit() must be called before stripe.confirmPayment(). Call elements.submit() as soon as your customer presses pay, prior to any asynchronous work. Integration guide: https://stripe.com/docs/payments/accept-a-payment-deferred
Yep indeed you are missing elements.submit()
Take a look at the code here: https://stripe.com/docs/payments/accept-a-payment-deferred?type=payment#submit-the-payment
You want to model your "pay" code based on that
ok i see in the dashboard
"message": "Payment details were collected through Stripe Elements using automatic payment methods and cannot be confirmed with a Payment Intent configured with payment_method_types."
"type": "invalid_request_error"
Change your PaymentIntent creation code to use 'automatic_payment_methods' => ['enabled' => true],
Instead of payment_method_types
๐
๐ฅณ
you have no idea how happy i am right now ๐
after so many days of failure
So glad you could get it working!
one last question. When would i update the DESCRIPTION field on the payment intent?
i only need it for visual purposes. as on the dashboard all you see is PAYMENT intents!!
whereas if i had a description, i can populate with the user email for example
can i do it on the stripe.confirmpayment ? cos i was gettin errors few days ago there
No you have to do this from your backend
So you might just want to set it when you create the PaymentIntent
Since you should know all the info at that point any way
$intent_response = \Stripe\PaymentIntent::update(
$_GET['intentId'],
[
'description' => $_GET['email1'].' : '.$_GET['country'],
'receipt_email' => $_GET['email1'],
]
);
i do have this on my backend but for some reason not updating/showing on dashboard?
that's why i thought i can do during submission or something
Well are you ever calling that part of your backend?
Mostly though just pass it on creation
No need to update
i don't know the details on creation though
intent is created on page load then user enters their data
No it isn't ๐
Or it shouldn't be at least with the deffered intent flow
That is the whole point of that flow
See step 5: https://stripe.com/docs/payments/accept-a-payment-deferred?type=payment#dynamic-updates how you call // Create the PaymentIntent and obtain clientSecret const res = await fetch("/create-intent", { method: "POST", });
That is when you would actually create the PaymentIntent
oh i see! this is what i've been looking for all the time to create the intent on POST rather than on page load
which would eliminate UNNECESSARY loggon on the dashboard
yep
damn! i do have to leave for today though.. and continue tomorrow to finalize that part
can I reach you tomorrow if i need help on that ?
cos these threads close after some time and new people get allocated on each chat
i've had 5 guys over the last week and no one was able to help, but YOU
๐
i 'll need YOUR assistance plz
Everyone does their best :). Pop in the main channel and someone will be able to help!
Have a good rest of the day!