How to update Braintree Customer default payment method - php

Now what I want to do is show all the payment methods a customer used before and let him to choose for the next transaction.
I have successfully fetch all the payment methods, however I find if a customer used use a PayPal account before, I can not set a credit card as the default one by use
$updateResult = Braintree_PaymentMethod::update(
‘credit_card_token',
[
'options' => [
'makeDefault' => true
]
]
);
or
$updateResult = Braintree_Customer::update(
$customerId,
array(
'creditCard' => array(
'paymentMethodNonce' => $nonceFromTheClient,
'options' => array(
'makeDefault' => true
)
)
)
);
The drop-in UI will still show the PayPal account first. Although I can see the this credit card is shift to the default on by query
$paymentMethod = Braintree_PaymentMethod::find('token’);
$paymentMethod -> default
So my question is can I set directly show credit card as the default payment method in drop-in UI even the user use PayPal before?

I work as a developer at Braintree. The Drop-in UI is configured to display the most recently used payment method that was successful, not the PayPal account or the default payment method. Currently, you cannot override this behavior in the Drop-in UI, but the team is working on a way to offer this functionality.
I recommend reading through this related GitHub issue to see if any of the proposed alternatives might work for you. You can also subscribe to the issue if you would like to be notified of any updates.

Related

Laravel Cashier - where does $stripeToken come from?

The documentation on Laravel Cashier is quite vague and misses some very important details like what the $stripeToken is and where does it come from?
So to create a new subscription we do this:
$user->newSubscription('main', 'premium')->create($stripeToken);
This is the first time a user will be subscribing so where does $stripeToken come from exactly?
In the docs it says:
The create method, which accepts a Stripe credit card / source token,
will begin the subscription as well as update your database with the
customer ID and other relevant billing information.
Does this mean I have to manually create the customer object in Stripe first and then pass the customer id as the $stripeToken? It mentions card details but how do I pass them? What is the format and what do I expect in return?
If $stripeToken is the customer id in Stripe then Cashier is assuming that we already have customers created in Stripe which we won't have the first time.
Can anyone shed some light on this?
It turns out that the stripeToken is usually generated by stripe.js forms when they are submitted.
As I am using API driven checkout forms and not standard html submission forms I need to use the Stripe API to create the token from the card details provided.
$stripeToken = Token::create(array(
"card" => array(
"number" => $request->get('number'),
"exp_month" => str_before($request->get('expiry'), '/'),
"exp_year" => str_after($request->get('expiry'), '/'),
"cvc" => $request->get('cvc'),
"name" => $request->get('name')
)
));
Then I use $stripeToken->id and pass it:
$user->newSubscription('main', 'premium')->create($stripeToken->id);
You can use the Stripe JS to get the stripeToken but if you are using the custom form then you can use Stripe checkout method.
Using both the ways you will get stripeToken in javascript and then you have to pass this token to your REST API for further processing.

Pass additional field to Laravel Cashier subscription

I have successfully created a subscription using Laravel Cashier however I have a problem regarding the payouts.
My use case is that I collect the amount from the user in a form of a subscription and then after specific action of the user, a certain amount is transferred further to the vendor.
I am using Manual Transfers for payouts and it seems it has everything I need (https://stripe.com/docs/connect/charges-transfers).
However in order to create a transfer from one Stripe account to another I have to assign a field "transfer_group" to my charge. Since I'm not using Charge for my subscriptions but Cashiers methods I don't have this option.
Looking into the implementation of "newSubscription" method or "create" method inside Billable class I couldn't find anything where I could pass this.
Can this be achieved or I have to reimplement my subscription using plain Stripe SDK?
Here's how my subscription code looks like:
$response = $customer->newSubscription($plan->name, $plan->plan_id)->create($request->token, [
'email' => $user['profile']['email'],
'description' => $user['profile']['biography'],
'metadata' => [
'name' => $user['profile']['name'],
'uuid' => $request->uuid
]
]);
All these options passed here are related to a Customer object and not Charge. According to Stripe docs I need something like:
$charge = \Stripe\Charge::create(array(
"amount" => 10000,
"currency" => "eur",
"source" => "tok_visa",
"transfer_group" => "{ORDER10}",
));
Since you don't control the charge creation here, you won't be able to pass transfer_group. What you should do instead is pass source_transaction: "ch_XXXX" when you create the transfer via the API. This will ensure that the Transfer is associated with the charge associated with the subscription and suit Stripe's requirements.
This is documented directly in Stripe docs here.

Generating multiple Braintree payment method nonce using one hosted form

My application is using Braintree to collect payments on my application. I want to have a checkbox on payment form which can be ticked to store the credit card details to the braintree customer record
However, I cannot reuse the same nonce that is generated to make the payment (I am getting error saying I cannot use the same nonce multiple times).
This is what I am trying to do:
...
$paymentMethodNonce = $this->input->post("payment_method_nonce");
//make payment
Braintree_Transaction::sale(['paymentMethodNonce' => $paymentMethodNonce,
'orderId' => $orderId,
'merchantAccountId' => $merchantAccountId,
'amount' => $amount,
"options" => ["submitForSettlement" => true]
]);
//create card for existing customer
Braintree_PaymentMethod::create(['paymentMethodNonce' => $paymentMethodNonce,
'customerId' => $customerId,
'options' => ['verifyCard' => true]
]);
...
I do not want to force user to re enter their credit card details again to be able to save it.
Is there a way in Braintree to generate more than one nonce for one hosted form? Or is there a better way to save card than having a checkbox?
Many thanks
Full disclosure: I work at Braintree. If you have any further questions, feel free to contact support.
If you are using version 3 of Braintree's javascript SDK, you can create multiple nonces from the same credit card information by calling hostedFieldsInstance.tokenize() multiple times. Each call to tokenize will create a new nonce from the information present in the payment form.
If you are using the Drop-In form, or version 2 of the javascript SDK, you cannot create multiple nonces from the same set of credit card information. However, you can still use a single nonce to create a credit card for the customer and create a transaction. To do this, create a credit card record in the Braintree Vault for the customer with the nonce. The nonce is consumed by the operation, so you cannot use it again to create the transaction. Instead, use the payment method you just created to create the transaction. Note that you can use this workflow with a single nonce generated from version 3 of the JS SDK as well.
$paymentMethodResult = Braintree_PaymentMethod::create([
'paymentMethodNonce' => $paymentMethodNonce,
'customerId' => $customerId,
'options' => ['verifyCard' => true]
]);
// now use the payment method you just created to run the transaction
$newPaymentMethodToken = $paymentMethodresult->paymentMethod->token;
$transactionResult = Braintree_Transaction::create([
'paymentMethodToken' = $newPaymentMethodToken,
'amount' = '20.00',
'options' => ['submitForSettlement' => true]
]);

Create a new Stripe user on a paid plan, setting a trial period, without a Credit Card

Using the Stripe API, Creating a new user on a paid plan with a trial period doesn't seem to work without a credit card token.
I am using the PHP SDK and doing the following:
$customer = \Stripe\Customer::create(array(
"source" => NULL,
"plan" => 'PROFESSIONAL',
"email" => $email_address,
"trial_end" => $unix_timestamp
);
Which returns the error:
Error: Invalid source object: must be a dictionary or a non-empty string.
There are two reasons I think this should work, which is why I think I am doing something wrong.
Adding trial_end adds a trial to the subscription, so no payment is needed which means it doesn't need a Credit Card at that point in time.
Using the Stripe online Portal, you can create a user on a paid subscription, and also move existing users on to a paid subscription without the need for a Credit Card, when you specify a trial period. If you can do it in the portal, why can't you do it via the API?
Is there something I have missed in the Documentation to allow me to do this?
Just tried the following which worked.
$customer = \Stripe\Customer::create(array(
"plan" => 'PROFESSIONAL',
"email" => $email_address,
"trial_end" => $unix_timestamp
);
Basically I just removed the source key/value completely. It then created the user on the paid plan with the trial.
Odd behaviour as when you create a user on a FREE plan, you can have the source key there with a value of NULL and it works. Also not documented as far as I can see.
Follow these step
Create a customer using
\Stripe\Customer::create(array(
"description" => $descriptions,
"email" => $email
));
Store the returned customer ID from stripe
Now subscribe the customer for that plan
$customer = \Stripe\Customer::retrieve($customer_id);
$subscriptions = $customer->subscriptions->create(array("plan" => $plan_id));
Please make sure plan is already created on stripe.

Embedded Adaptive Payments for digital goods between 2 users - confused about the need for an IPN

I'm building a site for a client that wants to enable users on the site to put ebooks for sale, which can be bought by both site members and non-members. The site itself is not involved in the transaction at all.
I've gone with adaptive payments as that seems to facilitate "peer to peer" transactions between two users where the site is not involved and does not take a cut or any payment. I'm using the guide found at https://developer.paypal.com/webapps/developer/docs/classic/adaptive-payments/integration-guide/APIntro/
Unfortunately the hosting uses php 5.2.17, which means I cant use the PHP API code on github, so i've had to roll my own using PHP. This isnt a problem, i've done similar many times before. I've managed to get the sandbox working the following way
user initiates purchase
my site makes a call to https://svcs.sandbox.paypal.com/AdaptivePayments/Pay
with the following json encoded array :
$payload = array(
'actionType' => 'PAY',
'currencyCode' => $currencyCode,
'receiverList' => array(
'receiver' => array(
array(
'amount' => $amount,
'email' => $receiverEmail,
'paymentType' => "DIGITALGOODS"
)
)
),
'returnUrl' =>$successUrl,
'cancelUrl' => $cancelUrl,
'requestEnvelope' => array(
'errorLanguage' => 'en_US',
'detailLevel' => 'ReturnAll'
)
);
This gives me a pay ID
i then put into the form which submits to https://www.sandbox.paypal.com/webapps/adaptivepayment/flow/pay
when the user clicks "Pay Now" the paypal light box pops up
if the payment is completed paypal returns me to my return url
i then display the download link
However when I look in the sandbox I see that The latest payments are under review ( apparently making my sandbox balance 10,000 has flagged me as a potential terrorist under australian law. go figure ) so this makes me think that perhaps I need to make an IPN, even though the developer documentation listed above makes no mention of it. The last thing i want to do is enable a download whos payment gets rejected.
So i guess my question is:
Is the fact that paypal called my return URL enough to allow the download of a digital good or should I setup an IPN and wait for paypal to hit it before authorising the download ?
PayPal is a PITA! And there's no argument about it.
Back to your question. You should verify if the payment when through when it calls your return URL. It should send you a token/transaction which you can query and check its payment status. Haven't used Adaptive Payments that much but you should always make sure a payment is completed before granting access.

Categories