#Truu

1 messages · Page 1 of 1 (latest)

grave flameBOT
alpine reef
#

You are close. Just don't change your frontend and React code. When you create the Subscription on backend, takes its latest_invoice.payment_intent 's client_secret and pass back to frontend as if you were created a PaymentIntent

muted crystal
#

that's what I have I think, the backend now has the line:

#

$output = [
'subscriptionId' => $subscription->id,
'clientSecret' => $subscription->latest_invoice->payment_intent->client_secret
];

#

so it has that more thorough 'clientSecret' taken from deeper within the $subscription object

#

the original line from the previous paymentIntent example was:

#

$output = [
'clientSecret' => $paymentIntent->client_secret,
];

#

Just so I know I'm on the right track, I started with the link you posted above

#

in it I see the line:

#

$subscription = $stripe->subscriptions->create(

#

I changed that in my project to be:

#

$subscription = \Stripe\Subscription::create(

#

is that the right thing to do for PHP? it better matches the first PaymentIntent example that worked before

alpine reef
#

I think you should trust the Doc for $stripe->subscriptions->create

#

Does it not work for you?

muted crystal
#

that project that you sent in the link has a bunch of variables I'm not familiar with that are not in my project

#

$app, Request $request, Response $response,

#

$stripe

alpine reef
#

Um sorry, it's general idea but it's the official Doc

muted crystal
#

like, in that example, what is $app at the very top?

#

is this a standalone PHP page that generates the entire form?

#

or does it still call back to the client side React

alpine reef
#

That's framework specific code. You can ignore and focus on the call to create Subscription

muted crystal
#

I feel like my php is working

#

it echoes this as output:

#

{"subscriptionId":"sub_1MHirEFtGvcbRuR6pmlVvWyk","clientSecret":"pi_3MHirEFtGvcbRuR61QBwZbK7_secret_MIaExdLDLNityCrfZ1EM72JoF"}

#

so I feel like it's passing through the php correctly, creating the subscription, and the incomplete subscription shows up for the new customer on my Stripe Dashboard

#

but then the React has that error:

#

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

alpine reef
#

You should compare with when you were creating PaymentIntent and returns its client_secret, vs. when you are currently creating Subscription and returns its latest_invoice.payment_intent.client_secret

#

Are you returning the same format? like pi_xxx_secret_yyy

muted crystal
#

I didn't check what the paymentIntent example was producing

alpine reef
#

So, let double check what value you supply to the Payment Element. It should be the Payment Intent client_secret

muted crystal
#

ok I just ran it, the PaymentIntent old example

#

it produced:

#

{"clientSecret":"pi_3MHjaDFtGvcbRuR60879eSDK_secret_XmkzOEfzOPZciswghtDPO1l21"}

alpine reef
#

So it depends on how your frontend takes that response and parse to the React app

muted crystal
#

same way the old example worked

#

const stripeElementsOptionsAppearanceObj = {
theme: 'stripe',
};

const stripeElementsOptionsObj = {
clientSecretStringFromServer,
stripeElementsOptionsAppearanceObj
};

return(
<Elements options={stripeElementsOptionsObj} stripe={stripePromise}>
<CheckoutForm />
</Elements>
);

#

Elements takes in the stripePromise and options contains the clientSecret

#

CheckoutForm is just like the example, where it has:

#

<form id="payment-form" onSubmit={functionOnSubmitPaymentForm}>
<PaymentElement id="payment-element" options={stripePaymentElementOptionsObj} />...

#

a PaymentElement wrapped in a Form

#

does the exact wording of the 'id' fields in those HTML tags matter?

alpine reef
#

What produces clientSecretStringFromServer

muted crystal
#

like, does it have to be 'payment-form' and 'payment-element' exactly

#

const [clientSecretStringFromServer, f_setClientSecretString] = useState("");

useEffect(() => {
// Create PaymentIntent as soon as the page loads
fetch(k_sgtCreatePhpFileLoc, {
method: "POST",
headers: {"Content-Type":"application/json"},
body: JSON.stringify({ items: [{ id: "xl-tshirt" }] }),
})
.then((res) => res.json())
.then((data) => f_setClientSecretString(data.clientSecret));
}, []);

#

same as the example code, a useEffect() takes 'clientSecret' passed from PHP and stores it into clientSecretStringFromServer

#

I may have found it

#

there's a line in the original that I still have here:

#

const clientSecretStringFromServer = new URLSearchParams(window.location.search).get("payment_intent_client_secret");

#

(client side React inside of <CheckoutForm>)

#

that "payment_intent_client_secret", is it a different set of GET variable names that appear in the URL bar for subscriptions?

alpine reef
#

Not sure if I follow the last question, but yes looks like you want to make sure f_setClientSecretString(data.clientSecret) got the correct value for you

#

Probably console.log the clientSecretStringFromServer variable

muted crystal
#

I do have that printing and it all seems to be set ok with those examples I pasted above

#

I want to reask my last question

#

does the exact wording of the 'id' fields in those HTML tags matter?

#

like, does it have to be 'payment-form' and 'payment-element' exactly

#

also thanks for getting back to me on this, I've been changing and retesting constantly and still getting the same error over and over, even when going back to my original script that used to work

alpine reef
#

The Id only matters in non-React approach, when we need the id to mount the HTML element

muted crystal
#

ok thanks, I'll keep working at this, thanks for your help and responses

alpine reef
#

Good luck!

muted crystal
#

I figured it out in case someone else needs help

#

this page shows the example for the 'options' prop different from the other example

#

const options = {
clientSecret: '{{CLIENT_SECRET}}',
};

return (
<Elements stripe={stripePromise} options={options}>
<CheckoutForm />
</Elements>
);

#

that led me to this page:

#

which clearly spelled out that the options prop needs 2 properties: 'clientSecret' and 'appearance'

rustic shoal
#

yes it's different if you're using the PaymentElement (which needs a PaymentIntent upfront) versus using other components like CardElement

muted crystal
#

so, to be clear, the example link that I posted above, has the correct definition for <Element>

#

but this link:

#

for React-PHP

#

has this code

#

const appearance = {
theme: 'stripe',
};
const options = {
clientSecret,
appearance,
};

return (
<div className="App">
{clientSecret && (
<Elements options={options} stripe={stripePromise}>
<CheckoutForm />
</Elements>
)}
</div>
);

#

which seems to be the wrong way to put 'clientSecret' as a property into the js object that goes into the 'options' prop

#

just want to point this out and help, if this guide needs to be updated on your developer website, or if I'm missing some simple javascript way of defining objects {}

#

but thanks for all your and orakaro's help, I'm all good moving forward here!

rustic shoal
muted crystal
#

that's really helpful, thanks for looking that up!

#

I changed the name of the variables and that must've broken that functionality