#barry-terminal-reactnative
1 messages ยท Page 1 of 1 (latest)
Hi ๐
I'm not going to re-open the thread
But can you summarize what the question was?
barry-terminal-reactnative
I'm using Stripe Terminal for a POS systme for a brewery. I want to be able to start tabs for customers and get the card holder name with a card swipe. I have been able to do this with the readReusableCard call, but I am getting charged fees for "online purchase" instead of a "present card" purchase.
Okay do you have some Payment Intent IDs that I can review?
Here is the paymentIntent that gets returned when I make collect using the "in person" collectPayment call...
{
"paymentIntent": {
"amount": 772,
"amountCapturable": 0,
"amountDetails": {
"tip": {}
},
"amountReceived": 0,
"applicationFeeAmount": 0,
"canceledAt": 0,
"captureMethod": "manual",
"charges": {
"data": []
},
"clientSecret": "pi_3NbnzbGPoenFLLiH1oohW2MY_secret_WLZrRkZXZ1PIFPswfRoLGIReI",
"confirmationMethod": "automatic",
"created": 1691255419,
"currency": "usd",
"id": "pi_3NbnzbGPoenFLLiH1oohW2MY",
"livemode": false,
"metadata": {
"cashierId": "XwLG3Umdg7VN5blSRg7n71qpqdA3",
"deliveryMethod": "barOrder",
"tabId": "n0iJlsiNTq6SrB6Xa8NN"
},
"paymentMethodOptions": {
"cardPresent": {}
},
"status": "REQUIRES_CONFIRMATION"
}
}
I use the readReusableCard call. I get a lot more detailed information including the payment method info:
Yes and I do see the confirmation request is passing the card present type with all the data
For which call?
the confirmation call, when the payment method details are provided
And when the funds are captured we can see the Payment Intent still has the only payment method type is card_present
https://dashboard.stripe.com/test/logs/req_Xyz3RzC1UhulxS
Sorry, I think I sent you two object with the same payment intent ID. Let me get one that is from a card present transaction.
This one is a card present transaction in Test mode
{
"status": "requires_payment_method",
"application_fee_amount": null,
"processing": null,
"next_action": null,
"last_payment_error": null,
"application": null,
"receipt_email": null,
"charges": {
"object": "list",
"url": "/v1/charges?payment_intent=pi_3NcXbUGPoenFLLiH16KVvSGF",
"has_more": false,
"total_count": 0,
"data": []
},
"cancellation_reason": null,
"customer": null,
"setup_future_usage": null,
"payment_method_types": [
"card_present"
],
"invoice": null,
"amount": 772,
"capture_method": "manual",
"transfer_data": null,
"created": 1691430748,
"object": "payment_intent",
"payment_method": null,
"canceled_at": null,
"payment_method_options": {
"card_present": {
"request_extended_authorization": false,
"request_incremental_authorization_support": false
}
},
"on_behalf_of": null,
"currency": "usd",
"statement_descriptor_suffix": null,
"automatic_payment_methods": null,
"transfer_group": null,
"livemode": false,
"confirmation_method": "automatic",
"statement_descriptor": null,
"latest_charge": null,
"review": null,
"amount_received": 0,
"source": null,
"client_secret": "pi_3NcXbUGPoenFLLiH16KVvSGF_secret_OFGpyKyzRTOdZrP180EgAQH7m",
"metadata": {
"cashierId": "XwLG3Umdg7VN5blSRg7n71qpqdA3",
"deliveryMethod": "barOrder",
"tabId": "pAtS7GXbf0x0gaCDULV3"
},
"shipping": null,
"id": "pi_3NcXbUGPoenFLLiH16KVvSGF",
"amount_capturable": 0,
"description": null,
"amount_details": {
"tip": {}
}
}
Please just provide the id property. It's the only thing I need/can use
Ok, but what I am trying to show is that the data coming back is different. This is missing the payment method info.
So you are attempting to pass an existing payment method when creating this payment intent?
https://dashboard.stripe.com/test/logs/req_K2HLcHCgybxUJR
This is handled by the Stripe Terminal API. I first create a payment intent. Then call the Stripe Terminal collectPayment method and pass it the payment intent.
I am not using the REST API directly. This is handled by Stripe Terminal SDK. https://github.com/stripe/stripe-terminal-android/tree/master
I call that later when I want to close the customers tab, but I need to get the customers name after I call collectPayment and before I call process payment.
The flow is:
- Customer orders a few items
- Create payment intent
- Collect payment (with Stripe Terminal)
- I'd like to get the customer name here
- Customer adds items
- Payment intent is updated
- processPayment is called and card is charged
Okay what is preventing you from getting the customer's name? The card isn't charged until the funds are manually captured in another API call
I'm not following. How can I get the customer's name? Isn't the card charged when processPayment is called?
You said the customer keeps adding items and the PI is updated. But you don't appear to be using our Incremental Auth flow for this:
https://stripe.com/docs/terminal/features/incremental-authorizations
That is the kind of scenario this flow was designed to support
But to answer your question directly, when you call Terminal.getInstance().processPayment() the Intent is confirmed and the amount is authorized but the card is not charged
The customer will see the funds held in their card statement but that's the authorization, not the charge. The card is actually charged once you capture the payment server-side.
You can see that API call for the previous Payment Intent here: https://dashboard.stripe.com/test/logs/req_Xyz3RzC1UhulxS
Sign in to the Stripe Dashboard to manage business payments and operations in your account. Manage payments and refunds, respond to disputes and more.
I was unaware of the Incremental Auth Flow. I will look at it.
So if processPayment does not capture, what does it do? I am not calling capturePayment and it is capturing. Maybe because I have my payment intent set up to automatically capture?
The Dashboard link I posted above is what captured the previous payment intent. It was triggered from a Node.js server
But getting back to your question about collecting the name. What is stopping you from providing that functionality between the collectPaymentMethod() and processPayment() calls?
I'm trying to get the customers name from the card swipe, not asking them manually.
The payment intent that is returned after collectPayment() does not have a reference to the payment method.
Are you referring to this snippet? https://stripe.com/docs/terminal/payments/collect-payment?terminal-sdk-platform=android#collect-inspect-payment-method
I actually have not used that function. Will it return the cardholders name?
That is in beta so I don't know for certain but the cardholder's name is part of the payment method that is attached when confirming the payment intent with processPayment()
Which, getting back to the Incremental Authorization flow, is how you initially collect card details.
Ok, I can try that. Back to a question I had before. What happens after processPayment()? Am I still able to update a payment intent after that?
If you are talking about changing the amount, without using incremental authorization we do not recommend it. Banks may reject the charge since the amount is greater than what was authorized. That's why we have the incremental auth flow.
Ok. I will look into it. For the collectPaymentInformation() call, you said it is in Beta. Is there an SDK available that has access to this call?
How is the behavior of this different from collectPayment()?
It is specific to returning the payment method to your android integration using the callback
override fun onSuccess(paymentIntent: PaymentIntent) {
val pm = paymentIntent.paymentMethod
val card = pm?.cardPresentDetails ?: pm?.interacPresentDetails
// Placeholder for business logic on card before processing paymentIntent
}
And it's also attaching the payment method to the payment intent? So I can still process and capture the payment later?
That occurs in the processPayment() step
Ok. I will give that a try. Thanks for your help.
I'm happy to shed what ๐ก I can ๐
It's why we're here
๐
So, I just tried the link to get the card info with collectPaymentMethod(). The card holdername comes back as "CARDHOLDER/VISA" instead of the actual name. This is consistent with what I have seen in the past using the "in person" payments.
Not I am using a Stripe test card and when it returns the actually card holder name it always says "TEST/STRIPE".
pm_1NcYnVGPoenFLLiHdcX23iAC
pi_3NcYnEGPoenFLLiH0pvnSyUD
hi @small otter , I'm around now, mind quickly recapping what your question is re: card holder name on Terminal?
I'm trying to get the card holder name when using Stripe Terminal collectPaymentMethod()'
yep but what's the issue you're facing exactly?
that the format Stripe has on the test card is TEST / STRIPE and not NAME / VISA ?
or something else? (that is how I read your earlier comment)
No, when I try and get the card holder name with collectPaymentMethod() the card holder name comes back as "CARDHOLDER/VISA" instead of the actual name. As a workaround, I was using readReusableCard() which gives me the actual name, but I am getting charged for "online" payments which greatly increases my fees.
So with readReusableCard() it would come back in the format "SMITH/JOHN" which is what i am looking for with collectPaymentMethod().
with collectPaymentMethod() the card holder name comes back as "CARDHOLDER/VISA" instead of the actual name
hmm isCARDHOLDER== actual name with card network prefixed?
Or literally the stringCARDHOLDERwhat you see in the response?
ah in your PaymentIntent above, it is literally CARDHOLDER / NAME (that exact string)
isn't that expected with the Stripe test card? which is what you said you're using?
(which is non ideal I agree given the name expected is LAST/FIRST iirc)
No, if I use readReusableCard() the name comes back as "TEST/STRIPE".
When not in test mode, using my John Smith example, collectPaymentMethod() would return "CARDHOLDER/VISA" and readReusableCard() would return "SMITH/JOHN".
oh that's odd - can you share the live mode example
When not in test mode using my John Smith example, collectPaymentMethod() would return "CARDHOLDER/VISA" and readReusableCard() would return "SMITH/JOHN".
Here is one from a completed transaction...
pi_3NcZJ5GPoenFLLiH1w9OcMU8
๐
Yes
I think that's expected to be a generic text then?
Cardholder name is typically not available on swipe or contactless payments, such as those made with Apple Pay and Google Pay.
from https://stripe.com/docs/api/charges/object#charge_object-payment_method_details-card_present
That's the issue. I just tested when inserting the card and it is showing up as "TEST/STRIPE".
That's why it works with readReusableCard(). This function doesn't allow you to tap.
yeah so my understanding is that
- when cardholder name is available (i.e. insert), in test mode it returns
TEST/STRIPE - when cardholder name is available (i.e. insert) in live mode, it returns
LAST/FIRST - when card holder name is not available (tap) in test or live , it returns
CARDHOLDER/VISA
so it is working as expected
The problem is that we'll ask people to insert their card, but most people will still tap.
Is there a way to block the tap functionality with collectPaymentMethod()?
yeah there's no way to do that, and also, I think you're doing this so you can guarantee cardholder name through insert? basically that isn't guaranteed even on insert since it is all up to issuers etc so if you need it, just collect it outside of the payment flow to guarantee it
I'm not sure what you mean "collect it outside of the payment flow", like just ask for the name manually?
yes
I'm inferring from your question that you want cardholder name for some purpose
but cards won't guarantee it even with insert
That's what I'm trying to avoid. We are a very high paced brewery and it would slow down the staff too much to ask for a name each time. I have been using readReusableCard() for the last 6 months and haven't had issues getting the name. Would this be any different?
Would this be any different?
I think so cause readReusableCard() reads the card differently as you said earlier, as it doesn't result in a card_present payment
why do you need card holder name for your flow, out of curiousity? tracking orders?
It's for customers starting a tab. They order a beer, start a tab, then come back up to the bar and just give their name so we can add the next beer to their tab. When they are done I update the payment intent and process and capture it.
would offering a quick input for PoS operator / bartender to enter the customer name on the PoS before accepting the card?
That's what I'm saying would slow us down too much. I think I'll play around with forcing them to insert the card. Maybe I can detect if it comes up with "CARDHOLDER" and just make them insert the card again.
yeah you could try that though in cases where you won't get a name from card holder at all, you'll still need fallback