#ekarma
1 messages · Page 1 of 1 (latest)
Hello! Do you see any errors in the web dev console in the browser when this happens?
Now that you mention it, I see 2 errors.
Unhandled address Element loaderror & Unhandled linkAuthentication Element loaderror
ha, thanks. I can take it from here. Great error handling.
"message: "The client_secret provided does not match any associated SetupIntent on this account.""
So .. while we're here.. My process is to reuse the same email to move through the checkout flow. If I had to swap the email each time it would take a while.
Given this, it appears Stripe does not permit more than 1 SetupIntent at a time? Is that right?
oh nvm, this error is because I switched the keys to 'live' from 'test'..
Can you explain what Stripe is protecting against, with this error? Not quite sure the path forward given this circumstance, unless this situation is an anomaly only me testing would create
You're talking about the client secret error?
Here's my React Client Code..
const [clientSecret, setClientSecret] = useState(null);
useEffect(() => {
const getClientSecret = async () => {
const response = await axios.post(
'/api/ecommerce/setup-intent'
);
setClientSecret(response.data.client_secret);
};
getClientSecret();
}, []);
if (!clientSecret) {
return <div>Loading...</div>; // or your custom loader
}
return (
<Elements
stripe={stripePromise}
options={{ clientSecret, appearance, loader }}
>
<CheckoutForm {...props} />
</Elements>
);
// api/ecommerce/setup-intent code
const stripe = new Stripe(privateConfig.stripeKey, {
apiVersion: null,
});
// const customer = await stripe.customers.create();
try {
const setupIntent = await stripe.setupIntents.create({
// customer: customer.id,
automatic_payment_methods: {
enabled: true,
},
});
res.status(201).json(setupIntent);
} catch (err) {
res.status(500).json({
error: 'An error occurred while creating the session',
details: err.message,
});
}
Requirements mandate a 2 step checkout process.
Step 1 = Auth & Payment Intent Setup & Cart Desired Submits (Code I shared)
Step 2 = Admin finalizes payment of the Pending Cart & Payment Itent from the backend when shipment is ready
Okay, so you're doing separate authorization and capture?
Or are you using a Setup Intent without taking payment and then later charging them some amount?
Basically. I'm using a basic auth from my app, that preceeds LinkAuthenticationElement for first step
Okay, so what's your specific question?
Maybe i'm not positive what precisely what is calling the error and what the remedy is
Which specific error are you talking about?
So 2 of the 3 Stripe Elements generate teh same error back to back
"The client_secret provided does not match any associated SetupIntent on this account.""
That error means the API key being used doesn't have access to the client secret provided.
For example, if you use a live key on your server but a test key on your client that won't work because live and test mode are isolated from each other.
If you try to use a live client secret with a test mode publishable key the publishable key won't find that client secret because that client secret does not exist in test mode.
ahh, so the culprit is using mismatching .env values within the same environment?
Or could it be that Stripe logic has been generated to my user with the test keys, so now when I switch to live keys, it triggers the error?
Most likely, yes. This can also be an issue with Stripe Connect, when multiple accounts are involved.
Or could it be that Stripe logic has been generated to my user with the test keys, so now when I switch to live keys, it triggers the error?
I don't understand what this means, can you elaborate?
So.. my setup is Custom Connect with Destination payments for my first ecommerce customer, who sells many products to their customers.
Consider me Lvl 0;
My customer is Lvl 1;
Their customers = Lvl 2;
I'm just using my own account login (going to polish the logic to be sorta recursive to support all 3 lvl types in a way that works.
Its probably important I figure the cause out soon becuase we deployed to their production environment this AM & this blocks purchases
Auth / Checkout requirement flow:
-Lvl 2 customers come, register & setup w/ Link, save their payment & user info w/ me & Link.
-I Provide Lvl 2 Users w/ basic dynamic user experience w/ simply past, pending orders & user settings
-Once Lvl 1 User (connected account I charge destination payments to) finalizes a payment of the Lvl 2 user, I get a % leftover from Stripe costs, they get the rest.
With destination charges everything is happeing on your platform (when it comes to the API requests), so I don't think this is an issue where you're doing something like using the connected account's API keys, or using the Stripe-Account header. I think the cause of the error is most likely to be trying to use test and live keys together.
Walk through this for a moment with me if you would..
Starting w/ this code..
useEffect(() => {
const getClientSecret = async () => {
const response = await axios.post(
'/api/ecommerce/setup-intent'
);
setClientSecret(response.data.client_secret);
};
getClientSecret();
}, []);
if (!clientSecret) {
return <div>Loading...</div>; // or your custom loader
}
return (
<Elements
stripe={stripePromise}
options={{ clientSecret, appearance, loader }}
>
<CheckoutForm {...props} />
</Elements>
);
The client secret comes from the response of an API call response.data.client_secret
That API call uses the private STRIPE_SECRET env var I changed on production... STRIPE_SECRET=sk_live_5.... to power this API call that should..
-instantiate the setupIntent
-turns into the client secret on the client..
const stripe = new Stripe(privateConfig.stripeKey, {
apiVersion: null,
});
const setupIntent = await stripe.setupIntents.create({
// customer: customer.id,
automatic_payment_methods: {
enabled: true,
},
});
res.status(201).json(setupIntent);
Yes. Client-side, though, what publishable key (pk_•••) are you using to initialize Stripe on the front end?
There we are.. You guys are good. Theres a static 'test' key hiding in a big code file that only is a problem when prod flipped
Ah, yeah, that's probably the issue.
You need to switch that to your pk_live_ key in production.
Would I ideally use the Public key / Live for this value then?
const keyLoad = 'pk_test_eS4wLDqwDSi6tGD7QHnz2IXZ00RMZ3Cn9p'; <- here
const stripePromise = loadStripe(keyLoad);
You need to use the key that matches the environment you're in. If you're testing you need to use the test key, if you're in production you need to use the live key. The main thing is that the environments for the keys used on your server and your client match.
Example from my local...
NEXT_PUBLIC_STRIPE_PUBLIC=pk_test_eS4wLDqwDSi6t....
Right I get that, i'm more speaking to not exposing a private secret key to the client that would be insecure, so looking to confirm the public (live) key on client would match up with the api server private secret 'stripe' keyloader
CLIENT loads the 'stripe' promise object via the public stripeKey -> process.env.NEXT_PUBLIC_STRIPE_PUBLIC,
API CALL loads the 'stripe' promise object via stripeKey: process.env.STRIPE_SECRET,
Yep
Perfect. Any common pitfalls or advice for a first week ecommerce deploy.. Custom / Connect / Destination Payment Approach?
I know i'm about to learn some hard lessons just wish I could know what I dont .. know lol
Test everything end-to-end thoroughly
Set up monitoring in case something unexpected happens you catch it immediately
Good call.. What would you say are the main 'somethings' that happen
Can't really say. That all depends on your integration
Right, the main thing i'm a big torn about is how Link doesnt share the info they collect. I understand why n PCI n all that, its just a hard sell to clients to suggest to them their app will gather a bunch of user info, but they can't have it.
Is the way around that to simply capture it all first / upfront and use to seed the LinkAuthentication component?
You could do that, yes. But really the whole premise around Link is that it is a huge conversion uplift.
But yeah, if you are relying on collecting customer details then you can do that outside your payment flow.
And then Link can still streamline the checkout experience
I see its value in that regard, but at the end of the day it boils down to a few paths forward..
1 where link gets User / PW / First / Last / Email / Phone / Address & you dont..
1 where you both get it, but you have to ask twice...
or the 3rd which obviously is best, where you collect first, and share w/ Link, stopping short of card / bank info
Not sure exactly what you mean by "share w/ link" but yeah that third option is what I would recommend -- just use Link for the card/bank info input piece of your checkout flow.
I was hoping / figured i'd pass that info into Link up front.. User / PW / First / Last / Email / Phone / Address, so they only need to authorize using Link and then all what they'd ask besides card/bank info is already there
<LinkAuthenticationElement
options={{
defaultValues: {
email: session?.user?.email,
// User / PW / First / Last / Email / Phone
},
}}
onChange={(event) => {
setEmail(event.value.email);
}}
/>
<AddressElement
options={{
mode: 'shipping',
defaultValues: {
billingAddress,
// pass more data in
},
}}
The only default value you pass to LinkAuthElement is email if you do want to prefill that: https://stripe.com/docs/js/elements_object/create_link_authentication_element#link_authentication_element_create-options-defaultValues-email
so email is the only thing I can pre-populate?
Yes for Link Authentication Element
last 2 questions.. this client expressed interest in blocking all purchase attempts when the 'billing' and 'shipping' don't match. They find alot of fraud when they allowed them to be different.
On the flip side, I noticed 60% of the checkout attempts fail, and a main reason is mismatched shipping/billing.
Any insider suggestions on ways they can keep the fraud down without what feels like a dramatic step not permitting separate billing/shipping?
Link presents a checkbox to enable re-using shipping as billing address. If matching is my requirement, can you think of the best way to apply this up front w/ Link, instead of downstream where you allow them to do separate, only to know it will fail later
That isn't Link
That is Address Element
I'm not sure I understand what you mean exactly by:
Link presents a checkbox to enable re-using shipping as billing address. If matching is my requirement, can you think of the best way to apply this up front w/ Link, instead of downstream where you allow them to do separate, only to know it will fail later
Can you explain a bit more?
Scenario 1 = User registers, logs in, link/ address element kick in and gather info. User decides to apply a different billing/shipping address (per the defualt options) by unchecking the 'use same' checkbox
Scenario 2 = Since this customer doesnt allow mismatching billing/shipping, this option isn't provided so no one gets all registered, setup w/ banking and then the client says "nope"
Scenario 2 could be as simple as default checking that checkbox and not enabling it to toggle
So you are asking if it is possible to disable the Address Element checkbox?
Curious if i'm able to remove the users choice to have a billing/shipping that are different
Not present that checkbox that selects 'use same address' , and apply it by default, or just show it as a default & immutable detail (must be same)
Thanks
Yeah no this isn't possible. I think the only workaround here would be to just use Address Element in billing mode here and indicate it is for both billing and shipping and then you would use getValue() (https://stripe.com/docs/js/elements_object/get_value_address_element) to get these values and pass them directly to confirmPayment() for shipping: https://stripe.com/docs/js/payment_intents/confirm_payment#confirm_payment_intent-options-confirmParams-shipping
The downside here is that you don't get the prefill from Link
Maybe theres a way I could maybe just hack & override the code it generates to disable it changing or something..
Is it at least possible for me to assign the state of the checkbox value to a variable / listener or something?
Anyway, thanks for your help, much appreciated, ill let ya go
The Address Element doesn't emit any Events and I don't believe we indicate the tickbox from element.getValue() unfortunately
Wait wait wait
I'm wrong it does have a change event
You can test that
I'm not sure if that fires or not when you select the tickbox
I think i'm halfway to the solution.. the onSubmit function
sorry onChange..
onChange={(event) => {
if (event.complete) {
// Extract potentially complete address
const address = event.value.address;
// trigger Ship Calc
// setShippingAddress(address); enable if require match
setBillingAddress(address);
}
}}
That seems like it could potentially work
I have a hard time envisioning these things end-to-end without testing them
So can't say 100%
I embarked on a journey to default the payment method type to default to bank.. your docs didn't provide the syntax for ACH bank, but a lil inspect element was all it took. I'll figure something out
Let me know if I can help