Handle Different Cases Using Drop-In UI - braintree

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"
)

Related

How to make a braintree subscription with dropin UI and 3DS2?

I want to create a subscription page using drop-in UI.
Client Side:
I am done with the client-side. I have Drop-in UI implemented and I obtain a payment nonce.
Server Side:
On the server side I receive the nonce from the client but I can't create a subscription with that nonce(I received an unvaulted payment method). I need to create a payment method with this nonce. After this the nonce is consumed, so I need another nonce with 3DS secure (for the subscription creation).
From their documentation I understand that I need to create a second nonce (payment method nonce) and send again to the client for verification. I didn't found any sample of this verification...
The question is how I obtain a second nonce that I need for subscription creation?
Just checked the documentation for 3DS + subscriptions, I can see where there's confusion. You need to switch to Hosted Fields, not Drop-In.
This is because you need to do the following workflow, which Drop-In doesn't support:
Generate a payment method nonce out of a vaulted payment method token (server-side)
Verify that nonce using 3D Secure in your client. Successful results will have a new payment method nonce that is enriched with 3D Secure data. (on the client)
Use the generated 3D Secure enriched nonce in the Subscription.create() call.
3D Secure is a complex workflow, if you have additional questions on implementing this particular workflow, contact Support
The drop-in UI generates a nonce, but this nonce is associated with a vaulted payment method, only if you provide a customer_id when you generate the client_token. In this way you can obtain a bounce that you can use in gateway.subscription.create.
To summary the steps are:
(server) Create a customer without a payment method
(server) Generate a client_token with customer_id from step 1
(client) Generate drop-in UI using client token from step 2
(client) When the end-user adds his payment details drop-in generate a nonce associated with an already vaulted payment method
(server) Call subscription.create with the nonce from step 4
gateway.subscription.create({
"payment_method_nonce": clientNonce,
"plan_id": planId,
"merchant_account_id": merchantAccountId
})

Laravel Cashier - Prevent duplicated Payment Methods

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.

Laravel Cashier (Stripe) subscribing using the existing customer with token

I am developing a Laravel application that involves subscription payment. Now I am struggling with subscribing the user with token but using the existing customer. This is the scenario. In my application, user can update their payment/ billing information (basically card). When they update the payment info, they are just adding the card information. Then later, user can make payment or subscribe to whatever they want.
First user will add they payment method or card information. So I create the customer like this.
$user->createAsStripeCustomer($token, array_merge($options, [
'email' => 'email address',
]));
So the above method will create the stripe customer for the user along with the card. Then tomorrow, user might want to subscribe to a channel. Laravel Cashier provide the following method to subscribe.
$user->newSubscription('subscription-name', 'my-plan')->create($token);
Then issue with the above code is that, I have to pass the token again. If I have to pass the token, again, I will have to generate the token again in the Javascript. If I have to generate the token again in the javascript, I will have to ask the user to enter the card information again to get token. So what can I do to get user to subscribe using the existing customer info? How can I do that?
One method is whenever you create a stripe customer, add the user to a free subscription plan so that he doesn't have to pay anything until he subscribes. When the user starts subscription we can simply change the subscription plan to the desired plan using the following method:
$user->subscription('main')
->skipTrial()
->swap('provider-plan-id');
Another method is whenever we create a stripe customer, ask the user to select a subscription plan and put him on the trial period until he subscribes.

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.

Is it ok to pass payment_method_tokens from client to server?

I am currently using the braintree server package (Node.js) and am working towards implementing subscriptions.
As an intermediate step, I'm managing a list of payment methods for each customer, which is found inside a customer object: customer.paymentMethods.
I want to be sure that passing this list directly to the client is an ok thing to do. Essentially, I'd like to list all of the current payment methods, and also create a way to add new ones / remove existing ones. When a payment method is selected, I can pass the payment_method_token to the server to perform a particular action with this payment method.
As I'm only passing payment tokens to the user when they have the proper session, it seems safe to be passing tokens around in this way, but I want to be positive that I'm doing this correctly.
Can somebody verify whether or not this approach is ok?
Seems to me that 1) this is a lot of unneeded work and 2) not really what you should be doing...
You should be passing the payment nonce around - the SDKs do all the other work for you - https://developers.braintreepayments.com/start/overview
Specifically, for the subscription flow, see https://developers.braintreepayments.com/guides/recurring-billing/create/node - you need the paymentMethodToken, which comes from the nonce (either from the client or one stored on your server) and a planID that is set up in the Control Panel. The paymentMethodToken is not passed around, it is created (and can/should be stored) server side.

Resources