Reputation: 1830
I am using Stripe's API to pay for orders.
My plan is generally the following:
Creation of the payment form with Stripe Elements
Card authentication (3d secure security SCA) through the use of a PaymentIntent then the creation of a PaymentMethod.
Creation of the Customer object, to which I attach the payment method, and which I define as default
$customer = $this->stripeConnector->updateCustomer($customer->id, [
'invoice_settings' => [
'default_payment_method' => $paymentMethod->id,
],
]);
Normally it works fine.
But not for the Order. I create Order Object following the documentation : https://stripe.com/docs/api/orders/create with the orders items and the associated Customer
And I pay it following the following documentation https://stripe.com/docs/api/orders/pay
So, just by passing the Order id (because the customer is already associated to the order).
But I've the following error : Cannot charge a customer that has no active card
Why ? And how can I 'activate' the customer card ?
This is an example of a Customer data that I have :
{
"id": "cus_JocNLLNhqHuOD6",
"object": "customer",
"address": {
"city": "paris",
"country": "FR",
"line1": "5 rue pompidou",
"line2": null,
"postal_code": "75000",
"state": null
},
"balance": 0,
"created": 1625758082,
"currency": null,
"default_source": null,
"delinquent": false,
"description": null,
"discount": null,
"email": "[email protected]",
"invoice_prefix": "D46F6A15",
"invoice_settings": {
"custom_fields": null,
"default_payment_method": "pm_1JAz8uGgCQgXBLKX2hoxLQHr",
"footer": null
},
"livemode": false,
"metadata": {
},
"name": "admin admin",
"next_invoice_sequence": 1,
"phone": null,
"preferred_locales": [
"fr"
],
"shipping": null,
"tax_exempt": "none"
}
And my PaymentMethod response :
{
"id": "pm_1JAz8uGgCQgXBLKX2hoxLQHr",
"object": "payment_method",
"billing_details": {
"address": {
"city": null,
"country": null,
"line1": null,
"line2": null,
"postal_code": null,
"state": null
},
"email": null,
"name": "qsvsf",
"phone": null
},
"card": {
"brand": "visa",
"checks": {
"address_line1_check": null,
"address_postal_code_check": null,
"cvc_check": "pass"
},
"country": "US",
"exp_month": 5,
"exp_year": 2025,
"fingerprint": "oV7uH07M2JEz7jQm",
"funding": "credit",
"generated_from": null,
"last4": "4242",
"networks": {
"available": [
"visa"
],
"preferred": null
},
"three_d_secure_usage": {
"supported": true
},
"wallet": null
},
"created": 1625758080,
"customer": "cus_JocNLLNhqHuOD6",
"livemode": false,
"metadata": {
},
"type": "card"
}
Looking at the doc on the payment of an Order object, I wonder if I should instead use the 'source' option and therefore use a Source object instead of a PaymentMethod. But the problem is, the Source Object is deprecated in favor of the PaymentMethod to favor 3d secure, so I have to use it.
Upvotes: 0
Views: 880
Reputation: 3311
Orders is a long deprecated Stripe API, so I would recommend moving away from it, to PaymentIntents or one-off Invoices.
Since it is a legacy API, it only works with Cards/Sources and not PaymentMethods.
Right now your integration is attaching a PaymentMethod to your Customer.
Orders doesn't look for your Customer's PaymentMethods but instead it looks under the sources:
param on your Customer.
Orders also don't support SCA, so if a payment requires authentication, that would just surface as a decline and not give you the authentication life-cycle functionality that PaymentIntents give you.
That is why it works as you said, when you save a "Source" object under the Customer's source:
.
The right approach would be to move away from using deprecated Card/Source objects and the Orders API, and integrate PaymentMethods (which you already have integrated) and PaymentIntents or Invoices or CheckoutSessions.
Upvotes: 2