#mick23_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/1227356235829874820
๐ Have more to share? Add more details, code, screenshots, videos, etc. below.
Below are links to other discussions we've had with you in the past week in case you want to review that information. If your question is related to one of these previous discussions, please provide a comprehensive summary of the current state and what you need help with now. We help many users simultaneously, so a summary allows us to resolve your issue as soon as possible.
- mick23_code, 21 minutes ago, 24 messages
- mick23_code, 20 hours ago, 84 messages
- mick23_code, 4 days ago, 48 messages
- mick23_best-practices, 5 days ago, 80 messages
Hello again
Yeah, I'm not following this at all. Conceptually I get the above. But I cannot find any working code snippets to use to get that bit working.
which bit exactly?
In step-3 of the guide though, you'd want to set paymentMethodCreation to manual & call stripe.createPayment
So I've found this - https://docs.stripe.com/payments/card-element - but it keeps directing me to make a payment
No, card-element isn't relevant here
I'm trying to take this one small step at a time to get working. But all the guides are just trying to shortcut things, and it's actually more confusing than it helps.
Are you using React or HTML?
card-element isn't relevant? Oh. That's even more confusing.
Just trying to get a basic helloworld.html example working here
i.e. AddCardToAccount.html
Gotcha.
So in step 2, you're configuring elements by passing options object
Drives me nuts the world of software engineering these days with a framework first approach - ain't got enough hrs in the day to keep up with the latset javascript framework of the day.
Yeah that bit just looks like the standard out of the box stuff
That's where you'd set paymentMethodCreation to manual (under options)
here's what the options object supports
https://docs.stripe.com/payments/accept-a-payment-deferred?platform=web&type=setup#additional-options
I tried to change "setup" to "manual" but got a Chrome Console error saying that this method wasn't supported
mode would still be setup
paymentMethodCreation is a separate parameter
I see.
So this is the code I now have, but still not working
HTML;
<h1>Add Card - Manual</h1>
<form id="payment-element">
<div id="card-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>
What error are you seeing in your console?
JavaScript;
<script type="text/javascript">
const options = {
mode: 'setup',
currency: 'gbp',
// Fully customizable with appearance API.
appearance: {/.../},
paymentMethodCreation: "manual",
};
// Set up Stripe.js and Elements to use in checkout form
const elements = stripe.elements(options);
// Create and mount the Payment Element
var cardElement = elements.create('card');
cardElement.mount('#payment-element');
stripe
.createPaymentMethod({
type: 'card',
card: cardElement,
billing_details: {
name: 'test',
},
})
.then(function(result) {
// Handle result.error or result.paymentMethod
});
</script>
๐ taking over for my teammate. Give me a few minutes to catch up, please
Thanks
I'm at the stage where I'm just randomly trying different combinations and permutations at the minute to try and get this working.
So just to reset where I'm up to for ease.
Let me recap what you're trying to do to make sure we're on the same page. You are attempting to save a card to a customer without charging them at the same time. Since you want to deduplicate cards, your goal is to create the PaymentMethod first and inspect its fingerprint in order to decide whether or not to attach it to a customer.
Yeah basically
So I've got the SetupIntent stuff working. But when I was testing, I was noticing that it was creating duplicate Cards in Stripe against that Customer, which is clearly going to be a nightmare waiting to happen.
So I thought - Ok, simple, "just" have some kind of duplicate card details check in place, and only allow the customer to actually have 1x unique card. Fairly common sense.
But making this happen is what I'm struggling with.
I don't know if I've just approaching this stuff in a non-standard way. But in my head it's fairly basic: 1) Create Customer in SaaS App --> 2) Add Card to Account --> 3) Subscribe to relevant Subscription
The reason for this approach, rather than the standard checkout is the need for creating a LOT of different subscriptions longer term - Think the complex Microsoft Licencing model - that's the idea. It's not just going to be a basic Bronze/Silver/Gold model.
It's all going to be per-seat too
Okay, I understand you've been advised to use the PaymentElement and the deferred intent flow so you can create a PaymentMethod first, then inspect its fingerprint. If this fingerprint doesn't match the fingerprint of a card already attached to the customer (or if no cards are attached to the customer), you will continue with creating a SetupIntent for this customer and attach this card to them.
Yes that's right
Let's start with your HTML code. I recommend updating <div id="card-element"> to <div id="payment-element">. This is just a name for your div but it'll hopefully remove some confusion if we use the same terminology
Done. This is the HTML now;
<h1>Add Card - Payment Element</h1>
<form id="payment-form">
<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>
This is currently the JavaScript;
<script type="text/javascript">
const options = {
mode: 'setup',
currency: 'gbp',
// Fully customizable with appearance API.
appearance: {/.../},
paymentMethodCreation: "manual"
};
// Set up Stripe.js and Elements to use in checkout form
const elements = stripe.elements(options);
// Create and mount the Payment Element
var cardElement = elements.create('card');
cardElement.mount('#payment-element');
stripe
.createPaymentMethod({
type: 'card',
card: cardElement,
billing_details: {
name: 'test',
},
})
.then(function(result) {
// Handle result.error or result.paymentMethod
});
</script>
For context, the CardElement and PaymentElement are totally different. The CardElement accepts just cards, while the PaymentElement is compatible with other payment method types (e.g. US bank accounts, GooglePay, ApplePay, Klarna, etc). The deferred intent flow is only supported by the PaymentElement.
Ok, that's good to know, didn't know that.
So with the above HTML + JS, this is the output;
Getting this error in Chrome Console, but I can't see how as I've commented out all the other SetupIntent code I had working;
Uncaught SyntaxError: Identifier 'options' has already been declared
In your Javascript code, replace:
cardElement.mount('#payment-element');```
with:
```const paymentElement = elements.create('payment');
paymentElement.mount('#payment-element');```
Ignore that last error I mentioned, just found a bit of code that was still uncommented - got rid of that error now
Just updated the code - that's looking more normal now, got the card fields to display as expected
rookie error when trying to piece together lots of complex docs and copying and pasting stuff
Right, so the next question then. What next?
I'm assuming that when I fill out the form, it'll create a card, and when I fill it out again, it'll create another duplicate card? (just going to test that now...)
Yes, that should still happen right now
In fact, it won't - as the HTML + JS don't know who the Customer is to attach it to
That's where the SaaS Server Side /create-intent piece was handling that previously.
So do I need a bit of JS now to get the Fingerprint in the JS, which can then call /my-api/check-if-fingerprint-already-exists, and ifFalse, then /my-api/setup-intent ?
Ah I see, so this is this bit then;
.then(function (result) {
// Handle result.error or result.paymentMethod
});
Right, this is where my hatred of JavaScipt comes in. I'm much more familiar with IDE driven getters/setters in proper languages
So how do I find the docs on what I need to translate into JavaScript which would normally be something like "result.getFingerprintOfCardJustCreated() etc.
In your Javascript code, replace:
type: 'card',
card: cardElement,
billing_details: {
name: 'test',
},
})
.then(function(result) {
// Handle result.error or result.paymentMethod
});
with:
form.addEventListener('submit', async (event) => {
event.preventDefault();
elements.submit();
const paymentMethod = await stripe.createPaymentMethod({
elements
})
console.log ("PaymentMethod: " + paymentMethod);
})
}```
so you can see this in action
Let me give that a go now
So now when you submit the PaymentElement with a test card, you should see a request to create a PaymentMethod in your account logs. You'll also see your browser's console log return the newly-created PaymentMethod object.
Yeah that's showing now. Is there any way via the Chrome Console to view the object key:value data like you can with JSON?
I can see that JSON object in the Stripe Account > Developer > Logs > Request I just made - that is all JSON
Why isn't this working?
console.log("PaymentMethod: " + paymentMethod.id);
Again, this is just my lack of JavaScript syntax knowledge
I try and avoid JavaScript where ever possible and use actual programming languages
Error it's showing in Console is;
PaymentMethod: undefined
I think for now, just logging console.log(paymentMethod); will suffice for testing/seeing how this will work. What you should do is pass this to your server code to retrieve the PaymentMethod's fingerprint and add the logic to compare this to other fingerprints for cards stored on that customer.
Then basically just parse the JSON Object as a requsetParameter using something like the Google GSON Library and extract the "id" which is the Fingerprint ID of the card, and compare with what already exists in the DB. Makes sense.
Interestingly I've just tried to parse the JSON in JS and I'm getting this error;
Uncaught (in promise) SyntaxError: "[object Object]" is not valid JSON
Code;
console.log("PaymentMethod: " + JSON.parse(paymentMethod).id);
Figured it out
So in the Stripe > Developer > Logs > Request X. The "Response Body" is actually inaccurate, that needs updating to be accurate.
Looks like the object that comes back is wrapped in an additional object;
{"paymentMethod":
Then the Response Body is what it shows in the Stripe Developer Logs inside that
That is really confusing