Issue with Tokenizing Credit Card and Creating Payment Intent Using Stripe Terminal

99 views
Skip to first unread message

jacob pourrahman

unread,
Feb 5, 2025, 10:57:18 PMFeb 5
to Stripe API Discussion

Hi there,

I’m currently facing an issue while trying to tokenize my customer’s credit card using Stripe Terminal. After successfully creating a setup_intent for my customer, I attempt to create a payment_intent to charge the customer. However, I encounter the following error:

“The provided PaymentMethod was previously used with a PaymentIntent without Customer attachment, shared with a connected account without Customer attachment, or was detached from a Customer. It may not be used again. To use a PaymentMethod multiple times, you must attach it to a Customer first.”

I’m calling the endpoints in the following order:

1- Create Customer
curl --location 'https://api.stripe.com/v1/customers' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Authorization: Bearer sk_test_test' \
--data-urlencode 'email=pourra...@gmail.com' \
--data-urlencode 'name=jacob pourrahman'

2- Create Setup Intent
curl --location 'https://api.stripe.com/v1/setup_intents' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Authorization: Bearer sk_test_test' \
--data-urlencode 'payment_method_types%5B%5D=card_present' \
--data-urlencode 'customer=cus_RicfigndVS4XQu' \
--data-urlencode 'usage=off_session'

3- Process Setup Intent On Terminal To Collect Credit Card Payment Method
curl --location 'https://api.stripe.com/v1/terminal/readers/tmr_test/process_setup_intent' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Authorization: Bearer sk_test_test \
--data-urlencode 'customer_consent_collected=true' \
--data-urlencode 'setup_intent=seti_1QpCqmKXNWYR2BxYs7uKm2jJ'

After thsetup_intent is successfully completed (succeed), I am attempting to charge my customers

4- Create Payment Intent
curl --location 'https://api.stripe.com/v1/payment_intents' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Authorization: Bearer sk_test_abDo85626hOE5cAHPFQgTJ2Z' \
--data-urlencode 'amount=50' \
--data-urlencode 'currency=CAD' \
--data-urlencode 'capture_method=automatic' \
--data-urlencode 'customer=cus_RieY9OTPB3Ot7J' \
--data-urlencode 'payment_method=pm_1QpD07KXNWYR2BxY5jJthlVA' \
--data-urlencode 'confirm=true' \
--data-urlencode 'payment_method_types%5B%5D=card'


I faced this error:
{
    "error": {
        "message": "The provided PaymentMethod was previously used with a PaymentIntent without Customer attachment, shared with a connected account without Customer attachment, or was detached from a Customer. It may not be used again. To use a PaymentMethod multiple times, you must attach it to a Customer first.",
        "request_log_url": "https://dashboard.stripe.com/test/logs/req_65361Smcf1Rcu1?t=1738781331",
        "type": "invalid_request_error"
    }
}

Could you please help me understand why this error is occurring and how I can resolve it? Specifically, I’d like to know the correct way to attach the PaymentMethod to a Customer to avoid this issue.

Remi J.

unread,
Feb 5, 2025, 11:05:57 PMFeb 5
to api-d...@lists.stripe.com
Hello Jacob,

The problem is that you are passing the wrong PaymentMethod id (pm_1234) in your PaymentIntent creation call. When you use Terminal to collect reusable card details, we create a PaymentMethod object pm_123 with `type: 'card_present'` that represents the physical card used on the physical reader. That object is single-use and can not be reused for a payment. What we do though as part of that payment method collection is create a separate PaymentMethod object pm_ABC with `type: 'card'` which is itself reusable. Both objects point to the same card in the physical world, but in our API they are conceptually different.

The error is quite confusing here and I'll flag it internally to improve it so it's definitely not your fault that you couldn't figure this out. What you need to do is look at the correct PaymentMethod id when the SetupIntent succeeds after step 3. This is documented here [1] where we talk about the `generated_card` property which is the concept I was explaining above: pm_123 is single use but we automatically generated a separate pm_ABC object that is reusable. This information is stored on the SetupAttempt which is associated with your SetupIntent. That object has the property `payment_method_details.card_present.generated_card` [2] which would be the `pm_ABC` you are looking for. We have code examples on that doc I mentioned which show you how to access that information in your preferred language.

I hope this helps! If you have follow up questions about this, please contact our support team [3] or talk to developers on our Discord server [4].
Best,
Remi


To unsubscribe from this group and stop receiving emails from it, send an email to api-discuss...@lists.stripe.com.

jacob pourrahman

unread,
Feb 6, 2025, 10:17:19 PMFeb 6
to api-d...@lists.stripe.com

Thanks, Remi! 


Your explanation about the reusable pm_ABC from generated_card cleared up my confusion—appreciate the detailed guidance and the effort to improve the error messaging!


Best, Jacob

Reply all
Reply to author
Forward
0 new messages