Closed manikkang closed 4 years ago
I've just been investigating this myself. It looks as though spree_gateway doesn't currently support this. It supports v3 of the Stripe api, but still uses the old methods for creating a token and active merchant to process the payment. This doesn't work for supporting 3D secure which appears to by default require using Stripe payment intents functions. I could be wrong, this is how I interpreted it.
There is a pull request for active merchant which seems to support the new Stripe payment intents api (https://github.com/activemerchant/active_merchant/pull/3290).
Once this is merged into active merchant, this gem will need updating to use the new functionality. I'm hoping this will enable support for SCA and 3D Secure, I guess by redirecting the user to the 3D secure confirmation page?
It would be really helpful to have an update from someone who knows more about the spree_gateway gem, because the deadline is just over a month away. I'm happy to help writing a pull request.
Few days ago Active Merchant added the new gateway Stripe Payment Intents to support SCA and 3D Secure. Is anyone working on updating this gem to be able to use this gateway??
Hey @dyerc @waaux we're always happy reviewing and merging PR with this feature, thanks!
Any news about Stripe Payment Intents API implementation? In Europe it's mandatory since September...
@damianlegawiec @dyerc @manikkang - Any update on this?
@AnkurVyas-BTC you can track progress here: https://github.com/spree/spree_gateway/pull/355
@damianlegawiec - Cool :+1:
Any word on this being updated? I just got an email from Stripe warning that payments are going to be declined
Any updates about when this PR #355 will be merged?
Are we there yet? #355 seems complete or am I wrong?
I'm interested in an update as well
Hello @damianlegawiec In pull request mentioned above #355 we only give support for processing payments using Stripe's PaymentIntent in Spree UI. Are we going to add support for Spree Storefront API V2 too? I'm working on a project which requires SCA supported payments. I'm no expert here, but it'll be great if you can lead me in the right direction.
Currently, I tried to use the code of #355 PR, and I can easily process normal payments by using Stripe's createToken method. But it seems that the method doesn't support SCA. So now, I'm wondering how to make it work with Stripe's PaymentMethod creation method.
I'm using https://github.com/spree/spree-storefront-api-v2-js-sdk and stripe/react-stripe-js v1.1.2 and stripe/stripe-js v1.5.0
Here's the code snippet. `const result = await stripe.createPaymentMethod({ type: 'card', card: elements.getElement(CardElement), billing_details: { name: 'ABC XYZ' } });
if (!result.error) { const order = {payments_attributes: [{payment_method_id: '7'}]}; const { userAddress } = getState(); const { firstname, lastname } = userAddress; const { exp_year, exp_month, last4 } = result.paymentMethod.card; const paymentSource = {'7': { gateway_payment_profile_id: result.paymentMethod.id, number: last4, month: exp_month, year: exp_year}}; const response = await client.checkout.orderUpdate({ bearerToken: token }, {...params, include: 'payments'}); // Here I get error from backend server, that it cannot }`
And in the backend, I get below error message.
You cannot supply a PaymentMethod ID as the
source
parameter. Please use thepayment_method
parameter instead. If you wish to set a default payment method for this Customer for future Invoices, set invoice_settings.default_payment_method.
Thanks.
I believe #355 handles all Spree UI stuff. I need to make it work for API V2, so it'll be great if you can lead me in the right direction. @damianlegawiec
I believe #355 handles all Spree UI stuff. I need to make it work for API V2, so it'll be great if you can lead me in the right direction. @damianlegawiec
I found the solution. Thanks for implementing Stripe SCA.
@satyakam-nividata could you share that solution? Yes, our plan is to have this also in the headless API mode as well
Here's how I managed to make it work in API mode. In frontend code, I've added Stripe's CardElement, configured it in the checkout form.
const result = await stripe.createToken(elements.getElement(CardElement), { name: 'First Name + Last Name', });
I used result.token.id in the below code.
` const { token } = nextCookie({});
const payment = await client.checkout.paymentMethods({ bearerToken: token, });
if (payment.isSuccess()) { const { id } = payment .success() .data.find( item => item.attributes.type === 'Spree::Gateway::StripeElementsGateway', ) || {}; const order = { payments_attributes: [ { payment_method_id: id, }, ], };
const paymentSource = { [id]: { gateway_payment_profile_id: result.token.id } };
const checkout3 = await dispatch(
orderUpdate({ order, payment_source: paymentSource }),
);
// I'll add below Axios call to Spree sdk
const pc_data = await axios.patch(
`https://localhost:3000/api/v2/storefront/checkout/payment_confirm`,
{ access_token: token },
);
if (pc_data.data.client_secret) {
const ccp_resp = await stripe.confirmCardPayment(
pc_data.data.client_secret,
{},
);
// I'll add below Axios call to Spree sdk
const hr_data = await axios.patch(
`https://localhost:3000/api/v2/storefront/checkout/handle_response`,
{ access_token: token, response: ccp_resp },
);
if (!hr_data.data.success) {
dispatch(handlePaymentFailure());
toast.error(<ToastError>Payment declined.</ToastError>);
dispatch(updateCheckoutStatus('error'));
return;
}
}
// Order complete
const complete = await client.checkout.complete(
{ bearerToken: token },
{
include: 'variants',
fields: orderCompleteFields,
},
);
`
I added 2 methods in CheckoutControllerDecorator
`module MyProject module CheckoutControllerDecorator
def payment_confirm
spree_authorize! :update, spree_current_order, order_token
if spree_current_order.intents?
spree_current_order.tap do |order|
order.process_payments!
order.reload.payments.valid.where.not(intent_client_key: nil).last.tap do |payment|
client_secret = payment.intent_client_key
pk_key = payment.payment_method.preferred_publishable_key
render json: {client_secret: client_secret, pk_key: pk_key}, status: :ok and return
end
end
end
render json: {client_secret: '', pk_key: ''}, status: :ok
end
def handle_response
spree_authorize! :update, spree_current_order, order_token
if params['response']['error']
payment = spree_current_order.payments.find_by!(response_code: params['response']['error']['payment_intent']['id'])
payment.update(state: 'failed', intent_client_key: nil)
render json: {success: false}, status: :ok
else
render json: {success: true}, status: :ok
end
end
end end
Spree::Api::V2::Storefront::CheckoutController.prepend MyProject::CheckoutControllerDecorator `
In routes.rb
namespace :api do namespace :v2 do namespace :storefront do resource :checkout, controller: :checkout, only: %i[update] do patch :payment_confirm patch :handle_response end end end end
I think it's good to go. Any suggestions are much appreciated.
Hello @damianlegawiec, Any suggestions for the above solution? And it creates customers in stripe per order. Is it normal? I think we should assign only one Stripe customer to Spree::User rather than having multiple stripe customers.
Stripe Api uses new methods for creating the charge. Has the gem being updated to accordingly?