#pinho-paymentelement-php

1 messages ยท Page 1 of 1 (latest)

digital mapleBOT
little viper
#

Hi ๐Ÿ‘‹ what's your question?

dusty junco
#

Hi

#

In this point:

#

const {error} = await stripe.confirmPayment({ //Elements instance that was used to create the Payment Element elements, confirmParams: { return_url: 'https://example.com/order/123/complete', }, });

#

The documentation says:

#

"Make sure the return_url corresponds to a page on your website that provides the status of the payment. When Stripe redirects the customer to the return_url, we provide the following URL query parameters:"

#

However, when stripe redirects, the URL does not contain any query parameters

#

So I thought about adding the parameter manually, like such:

#

confirmParams: { return_url: window.location.href = Helper.getBaseUrl() + app/cart/${storeId}/checkout/finish/${orderId}?payment_intent_token=${stripePaymentIntentToken}, },

#

Which works, but when validating in PHP if the payment has been succeeded:

#

`public function getPaymentIntent(string $paymentIntentToken): array
{
$result = $this->stripe->paymentIntents->retrieve($paymentIntentToken);

    return $result;
}`
#

I get the error: "You passed a string that looks like a client secret as the PaymentIntent ID, but you must provide a valid PaymentIntent ID. Please use the value in the id field of the PaymentIntent."

little viper
#

Taking a look now

dusty junco
#

Ok, I solved by passing the paymentIntentID and not the "client_secret".

#

Tell me other thing please:

little viper
#

Ah, okay. That was the first thing I was going to ask

dusty junco
#

is this the correct way to check if certain intent has been paid?

little viper
#

Yeah, you would check the status on the Payment Intent in order to decide what to show the customer

dusty junco
#

Status says

#

"requires_payment_method"

#

Stripe\PaymentIntent JSON: {
"id": "pi_3M7N2NCENMAgnvaD0PdAYR0E",
"object": "payment_intent",
"amount": 97090,
"amount_capturable": 0,
"amount_details": {
"tip": []
},
"amount_received": 0,
"application": null,
"application_fee_amount": null,
"automatic_payment_methods": null,
"canceled_at": null,
"cancellation_reason": null,
"capture_method": "automatic",
"charges": {
"object": "list",
"data": [],
"has_more": false,
"total_count": 0,
"url": "/v1/charges?payment_intent=pi_3M7N2NCENMAgnvaD0PdAYR0E"
},
"client_secret": "pi_3M7N2NCENMAgnvaD0PdAYR0E_secret_BVIZD3KeJ58zTVEGQv2UBf9vg",
"confirmation_method": "automatic",
"created": 1669225627,
"currency": "eur",
"customer": null,
"description": null,
"invoice": null,
"last_payment_error": null,
"livemode": false,
"metadata": [],
"next_action": null,
"on_behalf_of": null,
"payment_method": null,
"payment_method_options": {
"card": {
"installments": null,
"mandate_options": null,
"network": null,
"request_three_d_secure": "automatic"
}
},
"payment_method_types": [
"card"
],
"processing": null,
"receipt_email": null,
"review": null,
"setup_future_usage": null,
"shipping": null,
"source": null,
"statement_descriptor": null,
"statement_descriptor_suffix": null,
"status": "requires_payment_method",
"transfer_data": null,
"transfer_group": null
}

#

"requires_payment_method" is the status.

#

This doesn't tell me the user has indeed paid

#

My main problem is that the flow is the following:

Redirect URL = https://mywebsite.com/store/2921/checkout/finish/2919
Checkout > Confirm Payment > Paid > Redirect URL > Set order as paid

However, the user can try to hack the system and directly access the RedirectURL manually without paying. This is why I need to check the status of the IntentToken created, to see if indeed the user has paid certain order before proceeding to tell that the order is paid.

little viper
#

I'm not sure I understand the problem here though. If you're checking the status of the Payment Intent during the redirect (e.g. before the return_url page renders), isn't this a non-issue?

dusty junco
#

It's after the redirect.

#

Again, the process is the following:

return_url = https://mywebsite.com/store/2921/checkout/finish/2919

Checkout page > Confirm payment (stripe.confirmPayment() javascript function) > Goes to return_url > Sets order as paid

What prevents the user from acessing the return_url directly? Nothing.

low saddle
#

๐Ÿ‘‹ taking over as there are 20 people asking questions in parallel

#

The URL is client-side so it's normal that anyone can see it and visit it. What you need to do is when someone visits that page, you check their PaymentIntent and its status, either in the API or in your own database

#

pinho-paymentelement-php

dusty junco
#

Yes, the status of payment intent for the ID "pi_3M7N2NCENMAgnvaD0PdAYR0E" is returning "requires_payment_method".

#

I'm using the TEST Cards 4242..

low saddle
#

so that means you never confirmed, or the confirmation failed.

dusty junco
#

How did I never confirmed if the redirect has been made by await stripe.confirmPayment() ?

low saddle
#

this is you calling confirm with no info

#

server-side with a secret key

#

so doesn't look like you confirmed that specific PaymentIntent client-side at least

dusty junco
#

Do you see any error here?

#

The stripeElements is OK?

#

Because the stripeelements is later used on the confirmation

#

Also, if there was a problem with the confirmation, supposedly, stripe wouldn't redirect to redirect_url, right? It's redirecting just fine.

low saddle
#

Please don't share pictures of code. We're both devs, way easier to read code as text. Right now I don't follow what you need really. Step 1 is to debug what is going on since you clearly never called confirmPayment() on the PaymentIntent you think you did
So I'd recommend adding clear logs to see the PaymentIntent client_secret you're using, what the API returns, etc.

#

if it redirects fine, it means the confirmPayment() call worked. And so my guess is that you are looking at the wrong PaymentIntent afterwards

low saddle
#

did you figure it out @dusty junco ?

dusty junco
#

Kind of...I'm making two requests simultaneously, I saw that in the logs, because the number of seconds between them is too low. And I just figure out it was a fucking chrome extension that was calling the page twice without me even noticing!

#

Im gonna test it now again

#

Ok, now I know that only one request was made and it's ok.

I confirmed the payment by using the Stripe 4242 Test Card > Stripe redirected to my url > I checked the status of the intent_id and it is still requires_payment_method

#

If the payment has not been done, stripe wouldn't redirect me.

low saddle
#

ah gotcha so you were creating two PIs by mistake and caching the wrong one

dusty junco
#

yes, it was a problem that I wasn't aware. However, still doesn't work..or at least the status is always requires_payment_method and I believe at this point I should be getting succeeded

low saddle
#

I mean minutes ago you duplicated the PI. So it's likely the same problem here again. You need to carefully log all data and see what happens. It's almost certain that you confirm the PI pi_123 but then look at the PI pi_ABC

dusty junco
#

As you can see the ID's are correct now.

#

(I believe....)

low saddle
#

Please try to provide actionable inforamtion in pure text. Sorry but Discord is really busy right now and you're rushing through too quickly

#

1/ Create a PI
2/ Confirm it client-side
3/ Look in the Dashboard and check if you had a payment or an error

#

I mean what happens client-side? Are you really calling confirmPayment()?

#

or are you mistakenly just redirecting/submitting the page on click with your submit button

dusty junco
#

What d'hell is "Customer has not enterered their payment method"?

#

I submitted the credit card details

low saddle
#

I mean you didnt

#

if you look at your logs you can see you never called anything but POST /v1/payment_intents

#

my guess is that your code is incorrectly redirecting when you click the submit button without ever calling confirmPayment()

#

Add some console.log() before/after the call to confirmPayment() and you'll see it's likely never called

dusty junco
#

omfg

#

The return_url is filled like this: "return_url: window.location.href = Helper.getBaseUrl() + app/cart/${storeId}/checkout/finish/${orderId}?payment_intent_id=${stripePaymentIntentId}"

#

do you see the problem? I'm using window.location.href !!!!

low saddle
#

oh lol I saw this earlier and I thought it'd just crash so it was just "pseudocode" ๐Ÿ˜น

#

browsers and javascript can be the weirdest sometimes, why wouldn't you immediately crash on code like this!!!

dusty junco
#

I'm receiving now the error In order to create a payment element, you must pass a valid PaymentIntent or SetupIntent client secret when creating the Elements group.

My stripe instance is created like such:

`const options =
{
locale: 'pt',
fonts: [{ cssSrc: 'https://fonts.googleapis.com/css?family=Poppins:400,500' }],
appearance:
{
theme: 'stripe',
variables:
{
fontFamily: 'Poppins, sans-serif',
fontWeightNormal: 500,
fontSizeBase: '14px',
fontSizeSm: '14px',
}
},
};

stripeElements = stripe.elements({ stripePaymentIntentToken, options });
const paymentElement = stripeElements.create('payment');`

Yes, I double checked and the value of stripePaymentIntentToken is pi_3M7OcMCENMAgnvaD1nHUAm7V_secret_x7Flf6OmQkhFpg05FAvucusKv

#

If I follow strictly the documentation:

#

stripeElements = stripe.elements({ stripePaymentIntentToken }); const paymentElement = stripeElements.create('payment');

#

I get the error: "In order to create a payment element, you must pass a valid PaymentIntent or SetupIntent client secret when creating the Elements group."

low saddle
#

I mean that simply means you don't

#

log that secret and you will see it's not there

#

sorry to push back but server is really busy and this is an introductory question, if you clearly log the parameter/options you give to Elements you'll see if it works

#
  clientSecret: '{{CLIENT_SECRET}}',
};

// Set up Stripe.js and Elements to use in checkout form, passing the client secret obtained in step 3
const elements = stripe.elements(options);```
#

like are you passing the right option with the right name? You see to pass something called stripePaymentIntentToken for some reason

dusty junco
#

Thats just the variable name, I just did a console.log(stripePaymentIntentToken); and it matches the logs

#

someone

#

please

#

kill me

#

ffs

#

you guys require the variable names

#

to be exactly like in the documentation

#

!!!!

#

even the elements variable, can't be called anythingElse !!!

#

It's working man. Thanks for your extensive help, much appreciated. I just gained 100 white hairs.

#

๐Ÿ˜…

low saddle
#

@dusty junco I think you might just misunderstand some parts of javascript

#

When you create the PaymentElement we have an option/parameter named clientSecret. We need that value, if you pass { blablabla: 'random value', } how would we know that you meant to pass this in clientSecret? Naming matters

#

what you can do is this stripeElements = stripe.elements({ clientSecret: stripePaymentIntentToken, });
like you use whatever variable name you want and you explicitly pass it as the right parameter. The short hand version you used {stripePaymentIntentToken} assumes that you pass an option named stripePaymentIntentToken with the value of that variable, that's a JS behaviour, not a Stripe specific thing