#resin - requires payment method
1 messages ยท Page 1 of 1 (latest)
Yeah so you never add a payment method to the payment intent. You need to confirm with a payment method first. Here's the only 2 requests related to the payment intent: https://dashboard.stripe.com/logs/req_GOIBEnXZhytvW9 and https://dashboard.stripe.com/logs/req_4AM9yDITK9fmCt
Sign in to the Stripe Dashboard to manage business payments and operations in your account. Manage payments and refunds, respond to disputes and more.
Sign in to the Stripe Dashboard to manage business payments and operations in your account. Manage payments and refunds, respond to disputes and more.
What integration guide are you following?
Unfortunately I dont have access to those logs. They are a client of ours (the Chicago Cubs). So wont be able to review them.
FYI, out of thousands of successful payments, we only see this happen a couple times.
Awesome! thanks for the help
Hello ๐ Stepping in to help out since the server is running a little busy
Hi. Thanks!
So it looks like you're using manual capture for the payments
Can you share what your collectPaymentMethod and processPayment functions look like?
private void collectPayment(@NotNull PaymentIntent paymentIntent,
StripePaymentResponseHelper stripePaymentResponse) {
Terminal.getInstance().collectPaymentMethod(paymentIntent,
new ReaderDisplayListener() {
@Override
public void onRequestReaderInput(@NotNull ReaderInputOptions readerInputOptions) {
stripePaymentResponse.onReaderMessage(readerInputOptions.toString());
}
@Override
public void onRequestReaderDisplayMessage(@NotNull ReaderDisplayMessage readerDisplayMessage) {
stripePaymentResponse.onReaderMessage(readerDisplayMessage.toString());
}
},
new PaymentIntentCallback() {
@Override
public void onSuccess(@NotNull PaymentIntent paymentIntent) {
processPayment(paymentIntent, stripePaymentResponse);
}
@Override
public void onFailure(@NotNull TerminalException e) {
stripePaymentResponse.onFailure(e);
}
});
}
private void processPayment(PaymentIntent paymentIntent,
StripePaymentResponseHelper stripePaymentResponse) {
Terminal.getInstance().processPayment(paymentIntent, new PaymentIntentCallback() {
@Override
public void onSuccess(@NotNull PaymentIntent paymentIntent) {
stripePaymentResponse.onSuccess(paymentIntent);
}
@Override
public void onFailure(@NotNull TerminalException e) {
stripePaymentResponse.onFailure(e);
}
});
}
if they are manual then how come only a few out of thousands fails when processing on the php server side?
So the reason you're seeing the error is somehow your code is trying to capture the payment intent before it has been confirmed with a payment method
For example
https://dashboard.stripe.com/logs/req_fpnYV9zQx4ymy1
If you look at this request, it confirms the PaymentIntent with the collected PaymentMethod information and moves the PaymentIntent to requires_capture status
For the PaymentIntent that you've shared above, that isn't the case. We're not seeing a request to confirm the PaymentIntent with the collected PaymentMethod. Instead your code is still trying to capture the PaymentIntent. Without additional logs from the device, its hard to tell what's exactly causing collectPaymentMethod to fail or why it still keeps on going with processPayment even without the payment method information.
wont be able to view those logs as its a clients account
looking at my code, theres no way to call processPayment without collectPaymentMethod returning onSuccess. so I agree, its strange. Just to give you more info on the process we have setup. Once processPayment is successful in our app, we send the payment to out backend for processing. It only at that point the error is thrown.
This is out backend code:
\Stripe\Stripe::setApiKey((string) Config::getInstance()->stripe->secretkey);
$intent = \Stripe\PaymentIntent::retrieve($order['reference']);
$intent = $intent->capture();
This is the error again:
This PaymentIntent could not be captured because it has a status of requires_payment_method. Only a PaymentIntent with one of the following statuses may be captured: requires_capture
Do you have the serial number of the reader that's running into this issue?
Also, have you observed any pending/un-captured PaymentIntents of the same amount getting created?
Unfortunately the devices are in Chicago and Im in Vancouver lol so wont have SN's. I could get them in a couple days but not right now.
Amounts on failed transaction are not always the same.
couple of questions:
- how/where is manual or automatic payment capture defined?
- can processPayment onSuccess return requires_capture status? Maybe this is whats missing in the code. the onSuccess is call but requires_capture is not checked, causing the payment processing on the backend to fail
1/ You're passing capture_method: manual while creating the PaymentIntent which tells the API to not automatically capture it when PaymentMethod is collected.
2/ With manual capture, you'd typically use processPayment's onSuccess block to tell your server to capture the PaymentIntent.
Terminal.getInstance().processPayment(paymentIntent,
You do get access to PaymentIntent object here though so you can theoretically check if the PaymentIntent is inrequires_capturestatus and if not, you can just re-runcollectPaymentMethod
this is our payment intent creation. maybe Im missing something. I dont see where to set the capture method
private void initiatePayment(int amount,
String currency,
StripePaymentResponseHelper stripePaymentResponse) {
PaymentIntentParameters params = new PaymentIntentParameters.Builder()
.setAmount(amount)
.setCurrency(currency != null ? currency.toLowerCase(Locale.ENGLISH) : "usd")
.build();
Terminal.getInstance().createPaymentIntent(params, new PaymentIntentCallback() {
@Override
public void onSuccess(@NotNull PaymentIntent paymentIntent) {
collectPayment(paymentIntent, stripePaymentResponse);
}
@Override
public void onFailure(@NotNull TerminalException e) {
stripePaymentResponse.onFailure(e);
}
});
}
huh interesting, as you can see we're getting capture_method manual as part of the POST request params
https://dashboard.stripe.com/logs/req_GOIBEnXZhytvW9
sorry mate, again, wont be able to see these logs. I dont have the Cubs dashboard login access
OH, I see. My bad, I thought you didn't have access to device logs ๐
no worries lol now you see what im working with
Do you know if that capture_method manual POST is coming from the php backend or the android app?
The creation request's source is Android SDK so I believe its coming from the app
So the app's processPayment call is sending capture method of manual. Can you see if this is the case for all payments of only a few?
I believe its createPaymentIntent that's setting the capture method
Checking the API ref to make sure its not the SDK setting it by default
good idea. thanks
While I'm looking, if you have a test environment setup and are able to create a new PaymentIntent then it'd be faster to get there
also good idea. just check getCaptureMethod() ?
or just create a new PaymentIntent in test mode and I can just look up the request
heres a couple more intent id's to check if manual method was used
pi_3LfA9SJWQTk4ZLla1H2Ib5m4
pi_3LgDwzJWQTk4ZLla1MZn0eof
pi_3LgDwVJWQTk4ZLla1Kc5y42h
pi_3LfB0wJWQTk4ZLla0QOEIWrf
yup all of them have capture_method: manual
hmm strange that most process without error and only very few fail then
im assuming they are all manual captures at this point
I'd recommend modifying your code in processPayment to check wether the PaymentIntent has requires_capture status and only then proceed with capturing
in the docs it says "For manual capture of payments, a successful processPayment call results in a PaymentIntent with a status of requires_capture.".
Wont all payments return requires_capture?
sorry, just so I understand, its possible for processPayment->onSuccess to be fired without requires_capture status and I should return an error to the user at that point?
sorry, just so I understand, its possible for processPayment->onSuccess to be fired without requires_capture status and I should return an error to the user at that point?
Yes, it's unlikely but I think that's what's happening here. I don't know why its happening (without looking into device logs, it isn't possible to know) but if you add in a conditional before calling the capture API then you should be able to handle this in the app gracefully and possibly trigger payment method collection again.