#Srujan-PaymentRequest
1 messages · Page 1 of 1 (latest)
I believe I am, the key starts with pk_test_ and works for the card element flow I have setup
A test publishable key starts with pk_test_
yup^^
Is the complete key used in your react app
Yes
Can you share with me the code?
I believe it's working since I am able to call other stripe functions and I integrated the CardElement and have gotten successful payments with that flow
Sure
import fetchClientSecret from '../../../utils/Payments/fetchClientSecret';
interface PaymentOptionsProps {
totalPrice: number;
}
const PaymentOptions = ({ totalPrice }: PaymentOptionsProps) => {
const elements = useElements();
const stripe = useStripe();
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
if (!stripe || !elements) {
return;
}
try {
const clientSecret = await fetchClientSecret(totalPrice);
const cardElement = elements.getElement(CardElement);
if (cardElement) {
const confirmPaymentResponse = await stripe.confirmCardPayment(
clientSecret,
{
payment_method: {
card: cardElement
}
}
);
const paymentIntent = confirmPaymentResponse.paymentIntent;
console.log(paymentIntent, 'paymentIntent');
}
} catch (error) {
console.error(error); // handle stripe error
}
};
// TO DO:
// This page will be Payment Options
// It will contain the bottom sheet that contains Google Pay button (if available) and CC input option
// CC Input Option will move to another bottom sheet with the form that is below and a submit pay button
return (
<>
<h1>Payment Options</h1>
<form id="payment-form" onSubmit={handleSubmit}>
<label htmlFor="card-element">Card</label>
<CardElement id="card-element" />
<button>Pay</button>
</form>
</>
);
};
export default PaymentOptions;```
import { Elements } from '@stripe/react-stripe-js';
import { loadStripe, Stripe } from '@stripe/stripe-js';
import { stripeConfig } from '../../config/stripeConfig';
interface StripeWrapperProps {
children: React.ReactNode | React.ReactNode[];
}
const StripeWrapper = ({ children }: StripeWrapperProps) => {
const [stripeObject, setStripeObject] = useState<Stripe | null>(null);
const accountId = stripeConfig.accountId;
// This function will re-run if the accountId prop changes.
useEffect(() => {
const fetchStripeObject = async () => {
// If there is no accountId, do not run the loadStripe function.
if (accountId) {
const res = await loadStripe(stripeConfig.publicKey, {
stripeAccount: accountId
});
// When we have got the Stripe object, pass it into our useState.
setStripeObject(res);
}
};
fetchStripeObject();
}, [accountId]);
//To do: If not loaded, implement spinner or loading status
// Once we have the Stripe object, load everything.
return <Elements stripe={stripeObject}>{children}</Elements>;
};
export default StripeWrapper;
^^I created this StripeWrapper since the app will have different stripe accounts associated with it
Can you check if the stripeObject is ready when the nested component is rendered?
Sure
It seems that the stripeObject is ready at the time I click the PaymentRequestButton
Also are you guys hiring haha? I wanna apply
Where is the PaymentRequestButton ? I only see CardElement in your code.
const stripe = useStripe();
const [paymentRequest, setPaymentRequest] = useState<PaymentRequest>();
useEffect(() => {
if (stripe) {
const pr = stripe.paymentRequest({
country: 'US',
currency: 'usd',
total: {
label: paymentItem.label,
amount: paymentItem.amount
}
});
// Check the availability of the Payment Request API.
pr.canMakePayment()
.then((result) => {
if (result) {
setPaymentRequest(pr);
}
})
.catch((err) => console.error(err));
}
}, [stripe, paymentItem]);
if (stripe && paymentRequest) {
paymentRequest.on('paymentmethod',
// Confirm the PaymentIntent without handling potential next actions (yet).
const clientSecret = await fetchClientSecret(paymentItem.amount);
const { paymentIntent, error: confirmError } =
await stripe.confirmCardPayment(
clientSecret,
{ payment_method: ev.paymentMethod.id },
{ handleActions: false }
);
if (confirmError) {
// Report to the browser that the payment failed, prompting it to
// re-show the payment interface, or show an error message and close
// the payment interface.
ev.complete('fail');
} else {
// Report to the browser that the confirmation was successful, prompting
// it to close the browser payment method collection interface.
ev.complete('success');
// Check if the PaymentIntent requires any actions and if so let Stripe.js
// handle the flow. If using an API version older than "2019-02-11"
// instead check for: `paymentIntent.status === "requires_source_action"`.
if (paymentIntent.status === 'requires_action') {
// Let Stripe.js handle the rest of the payment flow.
const { error } = await stripe.confirmCardPayment(clientSecret);
if (error) {
// The payment failed -- ask your customer for a new payment method.
} else {
// The payment has succeeded.
}
} else {
// The payment has succeeded.
}
}
});
}
if (paymentRequest) {
return <PaymentRequestButtonElement options={{ paymentRequest }} />;
}
return <></>;
};
export default PaymentButton;```
Should I put the event listener in the parent component?
Is the <PaymentButton> wrapped inside <Elements> ?
Yeah
It's far down the list but the StripeWrapper wraps the whole App, we have routes to /checkout which renders the Checkout page which renders PaymentOptions and PaymentButton posted above
The odd thing is though that I can get a successful payment and a paymentIntent obj returned from calling stripe.confirmCardPayment on the CardElement flow, but none of my console logs from within the event listener get triggered when I hit the pay button from the google pay sheet
I'm also running the app locally and porting through ngrok so I can serve https and ssl since stripe requires that
Can you share with me your merchant ID? you can find it from the Stripe Dashboard -> Settings ->Account Details
is that the same as accountID? I don't have access to stripe dashboard currently, but I can get access tomorrow
Would it start with acct_?
Yes
'acct_1LG9DeR8BkSiL135'
Thanks, give me a sec to check your account
Appreciate it Jack!
Hmm, this is custom account. and I don't see you are making any destination charges.
one sec, lemme try with the CC input see if anything shows up
I mean you are making direct charges on custom account, which is not recommended.
Hmm, so what is recommended?
We have a backend team that set this account up so I'm trying to understand what the heck they did
You should use destination charge or separate charges and transfers
Could you send me a link to some docs?
Stripe recommends using destination charges for Express or Custom accounts.
Thank you
But I guess the question remains, is the error because these accounts aren't properly configured? It seems only related to google pay as far as I can tell
It's not related, but i just want to let you know the best practices of using Stripe Connect.
Is there a public URL where I can visit and reproduce the issue?
Yes, in order to reproduce you'll need to run chrome to see google pay. If you want to test out the card element input you'd either have to run chrome with cors disabled somehow or with safari cors disabled. This is local testing...in production we won't have cors error since the endpoint for the client secret fetch will have the same origin
Any way I can share this link with you privately?
You don't get an error after clicking Pay?
No error
Yes, and I just have an active card in my Google Pay account
So you're using a real card or test card? You're not using the test card suite ?
Real card
That's probably the issue then for me...I was using the test card suite
Hmm...I'm still getting the same error with a real card
Test again in incognito mode?
I just keep getting unexpected developer error for some reason
Can you share with me a screenshot?
Any errors in the console?
Ah, I shouldn't advise the incognito mode, your Google account is not logged in.
Timed out waiting for a PaymentResponse.complete() call. No other error showing this time
Ah I see
Can you try another Google account?
I mean I signed in fine and saw my saved cards
Did you save the card in Google Pay account or in Chrome browser? because they are different