#batler-cardelement-confirmation

1 messages · Page 1 of 1 (latest)

tropic oliveBOT
trim matrix
#

@glacial scroll It feelsl like you are misunderstanding something fundamental with the product here.

#

Collecting card details is protected by PCI compliance which comes with strict rules. The way it works is that you use one of our UI libraries client-side to collect card details securely. Not server-side (which is blocked by default and can lead to all your transactions beind blocked)

glacial scroll
#

You didn't read what I typed.

trim matrix
#

I did

glacial scroll
#

I DO NOT WANT THE CARD DATA

#

Your API refused to work unless I sent the full card.

trim matrix
#

yes because you're not listening and using the wrong API

glacial scroll
#

I am asking how to send the source / token / whatever instead.

trim matrix
#

I am asking how to send the source / token / whatever instead.
sending where? Where does that source/token/whatever comes from?

glacial scroll
#

Let's simplify the process...

#

Step 1: the client's browser loads a script, one moment...

#

In Square's example code this happens:
setOutcome(result)

#

That result is a JavaScript object that contains the token/source based on...

#

stripe.createSource(cardNumberElement, {}

trim matrix
#

Tokens and Sources are legacy and were deprecated years ago. So why are you using that API?

glacial scroll
#

Because that is the only thing that worked that I could find.

#

I don't treat code like an installer on a Windows machine.

#

I need to have individual iframes per card field (one for the 16 digit number, one for the expiration, etc).

#

The demo that was presented creates one monolithic form in a single iframe.

#

I can't style client websites if Stripe only presents a monolithic iframe.

trim matrix
#

That "monolithic iframe" is drastically more powerful though and you 100% should be using it and selling your clients on it.

glacial scroll
#

No, I won't be using the monolithic ifame, I need the form fields broken up in to separate "fields"/iframes.

trim matrix
#

But ultimately if you have the split CardElement integration working then what you need to do is
1/ Create a PaymentIntent server-side
2/ Confirm the PaymentIntent client-side with confirmCardPayment()

glacial scroll
#

Where is a tutorial for the latest version that doesn't dump a monolithic iframe?

trim matrix
#

@glacial scroll is that what you were looking for?

glacial scroll
#

So...

  1. I ask for help with server code and am told about client code.
  2. I get the server code working but it's old.
  3. I ask for a modern client code and you send me a link to server code!

...I'm asking this with only a respectful intention: do you know the difference between client and server?

trim matrix
#

yep I do

#

You asked for code, I explained exactly what to do, you asked for a doc, I gave you an exact doc, which has both client-side and server-side code.
Clearly you understand you need code client-side since you're already using our CardElement UI component and were calling createSource() in Javascript create a Source object (deprecated).

So you can yell at me all you want and demand server-side code, but ultimately you need both sides and you know that because you already wrote the client-side part. What you need to do now is modify that client-side code to properly finish this

1/ Create a PaymentIntent server-side for the amount/currency you're trying to charge
2/ Client-side, collect card detais with Elements (you're using the legacy CardElement components because you don't like the full iframe for PaymentElement)
3/ Confirm the PaymentIntent client-side using the card details collected securely in that UI element by calling confirmCardPayment() instead of createSource

#

batler-cardelement-confirmation

glacial scroll
#

let me get a quick screenshot in here to help visualize this...

trim matrix
#

Earlier you shared this: stripe.createSource(cardNumberElement, {}
That's what you need to modify to switch to stripe.confirmCardPayment() which is covered in details in that doc I linked you to.

glacial scroll
#

So here is the card form with each field being it's own iframe...

#

I've got the result object using either the stripe.createSource or stripe.createToken

trim matrix
#

Just to be clear: I'm an experienced developer, I know our products inside and out. I know exactly what you're doing

#

do not call createSource() nor createToken() at all. Replace that entire part of the code with what's covered in the doc I shared

glacial scroll
#

Okay, I'm clear on that, so work with me on this...

#

I'm not using anyone's PHP code other than (if I can even get it to work) see what cURL raw outpit it produces.

#

I was using Square for a few years and their format was also similar.

trim matrix
#

Sure but I'm not going to teach you how to do url form encoding or curl requests

glacial scroll
#
  1. hash generated at client
  2. I AJAX it to my server
  3. I do my records at my server.
  4. I PHP / cURL to the API server.
trim matrix
#

it's your right to refuse to use our official PHP library but you're on your own here

#

and no, the steps you're doing are not how you use our product. So you can do it this way

#

sorry you can not do it this way

#

I'm sure you want to, and you'll try. But you need to flip how you think about things. For example 3D Secure is more and more common in the world, even in the US. If you collect card details this way, when you try to charge that card you'll get a decline saying "well you need to do 3D Secure"

#

Re-posting what I said earlier, this is the flow:

1/ Create a PaymentIntent server-side for the amount/currency you're trying to charge
2/ Client-side, collect card detais with Elements (you're using the legacy CardElement components because you don't like the full iframe for PaymentElement)
3/ Confirm the PaymentIntent client-side using the card details collected securely in that UI element by calling confirmCardPayment() instead of createSource

glacial scroll
#

So...

#

You guys do the hash AND the payment via JavaScript then?

trim matrix
#

yep

#

and we handle 3DS at the same time if needed

#

I know it's mind bending at first. It does this to all developers because it's not how most competitors do it. But even for card payments when you start needing to handle 3D Secure, flipping things over where you start with "I want a payment for $100 please" and then client-side you go "Okay now use those card details and confirm it right now and show a decline if it fails or do 3DS if needed"

#

There are ways to do what you want, I can show you, but only after you grasp what I am trying to explain, otherwise in a few weeks you will be quite mad you didn't realize the downside

glacial scroll
#

Ah...

#

The issue I have is that we're not supposed to trust the client.

#

So what you're inferring in the process...

trim matrix
#

you don't have to trust the client. Your server initiated the payment request by creating the PaymentIntent explicitly.

glacial scroll
#

Well...

#

The form I have that generates the hash works without any interaction with my server, it's all JavaScript.

trim matrix
#

I understand all of that, that doesn't change what I am describing

#

Let's shift gears

#

you clearly want your answer and I won't convince you

glacial scroll
#

Okay, now this is starting to make sense!

trim matrix
#

I'm sure it does. You will regret this approach but I tried, and my team tried earlier. You can figure it out in the future once you start being stuck

glacial scroll
#

I already figured out how to create a customer and list cards (ironically enough hah)

#

So right now the only thing that isn't clear (and thank you for the clarifications)...

tropic oliveBOT
glacial scroll
#

I'm not sure how to word this, but using the latest JavaScript API how do I break out of the monolithic iframe? I can't do cookie-cutter styling for my clients.

trim matrix
#

you don't

#

We control this, you have limited styling possibilities for it and that's it. No other choice unless you want to do PCI compliance yourself (which you don't)

glacial scroll
#

Thank you for the clarifications and I apologize about the frustration. I'm not interested in egotism or anything like that. I changed the JavaScipt code and got the pm_id like you mentioned while keeping the separate iframe form fields as desired. Here is the JavaScript code:

function window_onload(event)
{
cardNumberElement.mount('#card-number-element');
cardExpiryElement.mount('#card-expiry-element');
cardCvcElement.mount('#card-cvc-element');
cardNumberElement.on('change', function(event) {setOutcome(event);});

document.querySelector('form').addEventListener('submit', function(e)
{
e.preventDefault();
var options = {address_zip: document.getElementById('postal-code').value};

console.log('e', e);
console.log('cardNumberElement', cardNumberElement);

stripe
.createPaymentMethod({
type: 'card',
card: cardNumberElement,
billing_details: {
name: 'Jenny Rosen',
},
})
.then(function(result) {
// Handle result.error or result.paymentMethod
console.log('result',result);
});

});
}

document.addEventListener('DOMContentLoaded', function (event) {window_onload(event);},false);

left pier
#

👋 taking over here

glacial scroll
#

I'm going to create the test PHP file for Attach a PaymentMethod to a Customer. I wish the documentation was a bit more clear from the start.

#

Okay, not a problem and I appreciate the patience, I've been on both sides of these kinds of conversations.

left pier
#

Good luck and LMK if you have more questions!

glacial scroll
#

I'll note the (hopefully successful) result here in a few minutes. I would be very happy to provide the absolute minimal JavaScript/PHP code used to accomplish what I'm doing so you guys have a minimal working example for other 100% hands on programmers.

glacial scroll
#

Question...

#

In regards to: "message": "No such PaymentMethod: 'pm_1Nap7s2eZvKYlo2CRphEgW3H';

#

That was in PHP after attempting to attach the customer to the card.

#

So I suppose my intuition leads me to this question:

#

After the paymentMethod object is created with the paymentMethod.id does it exist on Stripe's servers and I can send it to my server to attach or do I have to do a second action in JavaScript to "validate" that paymentMethod.id?

left pier
#

No you don't need to validate it. That is a different issue. Maybe you are using secret key on your server on a different Stripe account than whose the Publishable key belongs to

#

ie. you use secret key on account acct_A, but your Publishable key is on acct_B

glacial scroll
#

I have the client/server (or public / secret) keys defined very well in my documentation.

#

I wish they would call them client/server keys.

#

There is just one account (for me using Stripe). The account has a test mode and live mode.

left pier
#

LMK if you see it

glacial scroll
#

Yes.

#

I basically have a 2KB PHP/cURL file that I copy/paste and then modify the $method, etc. All the variables are defined at the top. So that way I don't have to figure stuff out a second time.

#

Oh, I might have two list files confused...ha, checking...

#

It's a bit odd, the way this setup works isn't attaching a card to a customer, it's attaching a customer to a card.

#

Oh, is there a CREATE method (on the server) that I need to do FIRST and THEN attach that method this way?

left pier
#

No

#

It should work, if you are using a secret key on the same Stripe Account

#

What is your account id? acct_xxx

glacial scroll
#

sec

#

Ah, how do I find that on the website? -__-

left pier
#

On the "Accounts section"

glacial scroll
#

Got it! Thank you, it's acct_1Aji0zCbr9UflH1h

#

Here is the full error, if that helps?

{
"error": {
"code": "resource_missing",
"doc_url": "https://stripe.com/docs/error-codes/resource-missing",
"message": "No such PaymentMethod: 'pm_1Nap7s2eZvKYlo2CRphEgW3H'; It's possible this PaymentMethod exists on one of your connected accounts, in which case you should retry this request on that connected account. Learn more at https://stripe.com/docs/connect/authentication",
"param": "payment_method",
"request_log_url": "https://dashboard.stripe.com/test/logs/req_iBOduQQ73unccc?t=1691024305",
"type": "invalid_request_error"
}
}

left pier
#

Okie so it's a different account

#

This is acct_1032D82eZvKYlo2C Your javascript was using a Publishable Key from acct_1032D82eZvKYlo2C

glacial scroll
#

Damn, thank you, looking to fix and I should be able to retest this quickly...

#

wait...

#

I think the problem is here (now fixed, I think, and will generate a new paymentMethod.id to test the server attach feature with):

var stripe = Stripe('pk_test_MkP3RBSXldJELDE9z6OngRHi');//pk_test_6pRNASCoBOKtIshFeQd4XMUh

#

SUCCESS! Thank you! Now the last thing I need to do is charge that saved payment method that I just attached.

Koop mentioned that the charge isn't done by my server via the API though via JavaScript?

left pier
#

Yeah the Charge should be done on server

#

Sorry