Laravel Cashier - Prevent duplicated Payment Methods - laravel

I'm trying to update the payment method of a subscription. I collect the card information using Stripe's js (using a provided setup intent). Then I send the payment method id, provided by Stripe's js, to Laravel to actually update the User's default payment method.
Now, the problem is I want to prevent the User to insert duplicated cards, and the only way to prevent that would be to retrieve all the user current payment methods ($user->paymentMethods();), and check if any of those has the same fingerprint of the one I'm adding as default.
To get the fingerprint of the new payment method I'd need to get the Stripe PaymentMethod object for the id provided by the Stripe's js. The Cashier method to do that would be $user->findPaymentMethod(id).
The problem is that the payment id is not yet added to the User payments methods, so $user->findPaymentMethod($request->payment_method); fails because that payment method does not belong to $user.
The only solution I can think of would be to first add the new payment method, then check for duplicates and remove them ?

It seems like you’ve already found the best approach of adding the method to the user and then looking to see if there are any duplicated fingerprints, even if it is a little inconvenient.
Reviewing the Cashier documentation doesn’t show any obvious way to access the PaymentMethod before it’s attached to the user. It may be worth reaching out to the Laravel devs to see if there is functionality that would make this flow easier to accomplish.

Related

Laravel Cashier - Updating the Payment Method of a Subscription

I'm trying to figure out how to update the Stripe payment method associated with a subscription.
Is it fine if I simply update the default payment method of the user ?
I would use Stripe's JS to get the card information and make a payment method token with it, then update the default payment method server side. Would that be ok ?
Yep, that's correct - follow https://stripe.com/docs/payments/save-and-reuse to create and save a Payment Method to a Customer for future use. After which, pass the newly created Payment Method in invoice_settings.default_payment_method[0].
[0] https://stripe.com/docs/api/customers/update#update_customer-invoice_settings-default_payment_method

Should I call verifyBuyer for off-session payments

I'm integrating Square payment gateway into our system. And want it to support SCA.
In their dev docs it says that I should call verifyBuyer each time I want to charge CoF. Also, "If a challenge is required, Square automatically displays the challenge to the buyer". It's ok for on-session payments. But what about off-session payments, like cars rental service does - without customer online (automatically)?
In their dev docs it says nothing or I'm missing something.
Did anybody face with such case?
Our docs state:
Important
The SCA flow must not be initiated for a card on file transaction where the buyer is not present. In this scenario, do not call the verifyBuyer function. You can still charge the card but be prepared to handle the CARD_DECLINED_VERIFICATION_REQUIRED error.
Basically, don't call verifyBuyer, and don't pass a token to the payment endpoint. The payment could still technically fail, so you should build functionality to handle that.
https://developer.squareup.com/docs/payment-form/cookbook/verify-buyer-on-cof

Setting a default payment method using the braintree dropin

I am using Braintree to charge customers for their subscriptions (annually). The customer enters his payment method using the Braintree dropin. The payment method is saved and used to pay for the service on a specific date.
Everything works fine until the customer enters another payment method. My backend uses the default payment method to pay for customers services. The problem is that you cannot change the default payment method using the Braintree dropin (setDefault parameter or similar does not exist, although it would be handy).
It has to be done using the backend SDK, where I can call "update" function on PaymentMethod object, like explained here. But that is not possible, because to update a payment method you need payment method token which is not available when changing the payment method using the dropin. With dropin only PaymentMethodNonce object is available, which according to documentation does not include payment method token. So it's basically impossible to set some payment method as default using the nonce information.
I'm looking for a way to enable the customer to change his default payment method using the Braintree dropin.

Braintree drop in UI generate new nonce

I've integrated the braintree drop in UI in my project and have added paypal, google pay and visa payments. Everything works fine, payments are submitting to the API etc. But if I use submit a payment which fails using the values from - https://developers.braintreepayments.com/reference/general/testing/php#transaction-amounts. The nonce has then been used, amending my basket price and submitting again fails as the nonce has already been used. I've looked through the documentation and all I can find about nonces is that it can only be used once (https://developers.braintreepayments.com/guides/payment-method-nonces) and nothing around refreshing or requesting a new nonce. Ideally I'd like to avoid having to force the user to enter the payment details again.
Is there another way of automatically requesting a new nonce?

Handle Different Cases Using Drop-In UI

I am trying to use the Braintree Drop-In UI with a subscription service on my website. How do I tell my server how to create the subscription?
For Instance:
A user already has a payment method in the vault so when they hit submit my server just uses the payment nonce given to create the subscription since they used a vaulted method.
BUT, what if a user adds a new payment method? How does my server know to create a new payment method for them since it is not vaulted and I cannot just use the nonce to make a new subscription?
Really what I need to know is how can my server know the user is adding a new method versus using one already vaulted in the Drop-In UI.
Full disclosure: I work at Braintree. If you have any further questions, feel free to contact support.
To create a subscription using an existing payment method, first generate a client_token, passing in a customer_id.
#client_token = Braintree::ClientToken.generate(
:customer_id => a_customer_id
)
After passing this client_token into your Drop-in UI, the customer's previous payment methods will be within the form. The customer can then select one of these payment methods, or create a new one, and the new one will be selected.
After form submission, a payment_method_nonce that corresponds to the selected payment_method will be sent to your server. You can then call Subscription.create, passing in the payment_method_nonce. See our payment_method_nonce documentation for more information.
result = Braintree::Subscription.create(
:payment_method_nonce => "payment_method_nonce",
:plan_id => "silver_plan"
)

Resources