Sale transaction to multiple users at once with Braintree along with PHP - php

Is this possible with Braintree(payment gateway) along with PHP to make a sale transaction for all the users at once.
Like i want to make sale transaction only when minimum number of users are subscribed.
Here is the which I am trying to use:
// Make a sale transaction for all the users at once.
for ($x = 0; $x <= count($users); $x++) {
$result = \Braintree\Transaction::sale(array(
'amount' => Session::get('price'),
'paymentMethodNonce' => $request->payment_method_nonce,
'customer' => [
'id' => $user->id,
],
'options' => [
'submitForSettlement' => True,
]
));
}

Nonces are one time use only, so the only way this would work is if you used payment method tokens, which you would have to return from each customer's result object.

Related

Trying to charge before or after Subscription Schedule is created Stripe API

I am developing a wordpress website for a client.
He needs different types of packages. For most of these packages I developed a simple Stripe checkout webpage, using its documentation.
The problem is that I need this workflow:
first month x dollars
second month x dollars
after one year subscription y dollars
I've already done this using Subscription Schedule. But it needs a customer ofc. How can I charge before and after charging create this Subscription Schedule? I don't know how to deal with this, how to charge using Stripe checkout simple already built page or do I need to create one by myself, where user needs to add his card, pay, and get the customer_id?
function checkout3() {
// Set your secret key. Remember to switch to your live secret key in production.
// See your keys here: https://dashboard.stripe.com/apikeys
\Stripe\Stripe::setApiKey('sk_test_51e7DRPLRnISGb5vSFxnvvuDx1GzhlBIFeazcmpEevsUFf29jHXJ1YgE2xaJ1lGfzjtKzE8uoN0eR9Klaq00CnMFWvfB');
// The price ID passed from the front end.
// $priceId = $_POST['priceId'];
$priceId = 'price_1LPahmIne7DRPLRnFXV6Uz34';
$futureDate= strtotime(date('Y-m-d', strtotime('+1 year')));
$customer = \Stripe\Customer::create(
[
'description' => 'My First Test Customer (created for API docs at https://www.stripe.com/docs/api)',
]
);
$session = \Stripe\SubscriptionSchedule::create([
'customer' => $customer["id"],
'start_date' => 'now',
'end_behavior' => 'release',
'phases' => [
[
'items' => [
[
'price' => 'price_1LRF5CIne7DRPLRnwuLVE2pu',
'quantity' => 1,
],
],
//'end_date' => $futureDate,
'iterations' => 1,
],
[
'items' => [
[
'price' => 'price_1LRF5cIne7DRPLRngevvIZiw',
'quantity' => 1,
],
],
'iterations' => 1,
],
[
'items' => [
[
'price' => 'price_1LPujQIne7DRPLRnj3EOweJN',
'quantity' => 1,
],
],
],
],
]);
// Redirect to the URL returned on the Checkout Session.
// With vanilla PHP, you can redirect with:
//header("HTTP/1.1 303 See Other");
//header("Location: " . '$session->url');
}
So right now, the subscription schedule is added to the Stripe dashboard, the page it's keep loading infinitely, but without charging... How to deal with this?
public static function firebase_checkout3_func() {
$html = "";
$html .= "<form id='firebase-checkout' action='/wp-json/api/checkout2' method='POST'>
<button type='submit' id='checkout-button'>Începe acum</button>
</form>";
return $html;
}
Use Stripe hosted Checkout Page with setup mode to collect
a Customer's SetupIntent
Retrieve the Payment Method inside the SetupIntent
Set it as the customer's invoice_settings.default_payment_method
Create a Subscription Schedule with that Customer Id as normal

Stripe Checkout for recurring donations of variable amounts

I am trying to use Stripe Checkout to allow users to set up a monthly recurring donation for an amount of their choosing. When I set up the Session, it provides the correct inputs to the Stripe form, however when I look in Subscriptions in the back end of Stripe, nothing is created, and it seems to just take a single payment. Here is my code:
$checkout_values['success_url'] = $success_url;
$checkout_values['cancel_url'] = $cancel_url;
$checkout_values['payment_method_types'] = ['card','sepa_debit'];
$checkout_values['mode'] = 'subscription';
$checkout_values['metadata']['order_id'] = $order_id;
//Single line item for the dynamically created subscription and price info
$line_item = [
'price_data' => [
'recurring' => [
'interval' => 'month',
'interval_count' => 1
],
'currency' => $order->get_currency(),
'product_data' => [
'name' => $item->get_name()
],
'unit_amount' => $item_total
],
'quantity' => 1,
];
$checkout_values['line_items'][] = $line_item;
Maybe I need to create a subscription in Stripe and tie that in? In which case why doesn't it give me an error?
you don't need to explicitly create a subscription object. If you use Stripe Checkout, a subscription will be automatically created when your customer completed the payment flow in your checkout page.
You might want to firstly check if you are viewing the right mode (either Live or Test), and then take a look at the Dashboard Events to confirm subscription related events. You application can also listen to webhook events to get notified.

Stripe sca subscription php and charge automatically

I have implemented the Stripe SCA migration
my serve side code to create payment intent is as follows
$intent = \Stripe\PaymentIntent::create([
'payment_method' => $requestData['payment_method_id'],
'amount' => $requestData->amount,
'currency' => $requestData->currencyIso,
'payment_method_types' => ['card'],
'confirmation_method' => "manual",
'confirm' => true,
'setup_future_usage'=>"off_session",
]);
return $intent;
And my js code is as below to create card payment and handle response
stripe.createPaymentMethod('card', cardElement, {
billing_details: {name: cardholderName.value}
})
and handle the response:
function handleServerResponse(response) {
if (response.error) {
} else if (response.requires_action) {
stripe.handleCardAction(
response.payment_intent_client_secret
).then(function(result) {
if (result.error) {
} else {
// The card action has been handled
// The PaymentIntent can be confirmed again on the server
fetch('https://test.com/server.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
payment_method_id: result.paymentMethod.id,
amount: amount
})
}).then(function(confirmResult) {
console.log(confirmResult);
return confirmResult.json();
}).then(handleServerResponse);
}
});
}
}
}
$plan = Plan::create([
'currency' => $currency,
'interval' => 'month',
'product' => $product->id,
'nickname' => 'Payment Plan for order - ' . $order_id,
'amount' => $price,
'metadata' => [
'order_number' => $order_id,
'bgt_customer_number' => $customer_id,
],
]);
$schedule = SubscriptionSchedule::create([
'customer' => $customer->id,
'start_date' => 'now',
'end_behavior' => 'cancel',
'metadata' => [
'local_id' => $order_id,
'local_account_id' => $account_id,
'local_currency_id' => $currency_id,
'local_user_id'=> $user_id,
'local_installments_total' => $plan_length,
'bgt_customer_number' => $customer_id,
'order_number' => $order_id,
'invoice_description' => 'Payment Plan for order - ' . $order_id
],
'phases' => [
[
'items' => [
[
'plan' => $plan->id,
],
],
'collection_method'=> 'charge_automatically',
'iterations'=>$plan_length
],
],
]);
$metadata = [
'installments_paid' => '0',
'installments_total' => $plan_length,
'local_id' =>$order_id,
'local_account_id' =>$account_id,
'local_currency_id' =>$currency_id,
'subscription_schedule_id' => $schedule->id
];
$subscription_id=$schedule->subscription;
$result=Subscription::update($subscription_id,
[
'metadata' => $metadata,
'default_payment_method' => $paymentMethodParams['payment_method'],
'proration_behavior' =>'always_invoice',
//Create only after adding payment method id in customer
]
);
I am getting the SCA modal for sca cards and workflow is correct.
But what concerns me is testing the subscription created using sca
I tested using 4000000000003220 amd also 424242424242424.. and subscription is created with 3 installments.
The subscription is created with correct installments:
But what concerns me is the subscription first installment is not being charged immediately.
Invoice shows as:
This draft invoice was generated by a subscription. It can be edited
until it's automatically finalized in 1 hour.
.
When I try to complete the charge from stripe dashboard (as a part of test) it shows
The invoice was finalized, but the customer needs to complete 3D
Secure authentication for the payment to succeed. This additional
step is required by their bank to prevent fraud. 3D Secure emails are
disabled in your settings, so you'll need to notify the customer
manually
The invoice failed to capture.
Question:
1: I wanted the first installment or schedule to happen.
How do I accomplish this in staging env. Am I missing any points here in creating subscription or SCA methods?
2: What is really 'confirmation_method' => "manual". Really confused.
When using Stripe Subscriptions you typically won't be creating Payment Intents yourself. Instead you'll be creating and interacting with Billing objects like Subscriptions and Invoices. The Invoices will create the Payment Intents for you. Stripe has a guide that walks you through taking payment information and creating a Subscription. If you read through and follow that guide you should be able to build what you want.
To answer your specific questions:
Question: 1: I wanted the first installment or schedule to happen. How do I accomplish this in staging env. Am I missing any points here in creating subscription or SCA methods?
This is likely because you're creating a Payment Intent and paying that which is unrelated to the Payment Intent belonging to the Invoice of your Subscription.
2: What is really 'confirmation_method' => "manual". Really confused.
The confirmation_method property controls how a Payment Intent can be confirmed. However, if you're using Subscriptions and want to support SCA you should ignore this property and instead follow the guide linked above.

Amount must be greater than zero, PayPal/Braintree payment

I have an app that sells events, some events have zero-dollar price. Thus, I receive this message from PayPal:
Amount must be greater than zero
However, if I remove the need to make a payment, one user can order all the tickets for an event. So, what's the way to make users go through the payment process without making a charge.
Bear in mind, it'd be great to make as little change to the process in terms of generating a Nonce from frontend and sending it to backend to make the charge it.
I'm using this payment scenario.
This is the function that returns the error message:
public function chargeNonce($nonce) {
$gateway = $this->createPayPalGateway();
$amount = $this->payment_params['number_of_tickets'] * $this->payment_params['event_price'];
$result = $gateway->transaction()->sale([
'amount' => $amount,
'paymentMethodNonce' => $nonce,
'options' => [
'submitForSettlement' => True,
'paypal' => [
'description' => "Billing Notification",// For email receipt
],
],
]);
dd($result);
return $result;
}

Double customer entry in braintree vault issue

After completing transaction, there are two customer entry under vault.
Step I have followed:
1. Created customer.
//first customer vault entry is created at this point
$customerParams = Braintree_Customer::create(array(
'firstName' => $firstName,
'lastName' => $lastName,
));
2.Then generated clientToken
Braintree_ClientToken::generate(array(
"customerId" => $customerParams->customer->id
));
3.Then with help of api generated nonce in js successfully:
var client = new braintree.api.Client({clientToken: ctoken});
client.tokenizeCard({
...
...
});
4.Again at this point new customer is created
Braintree_Transaction::sale(array(
'amount' => $mapCidInvoiceID['amount'],
'orderId' => $redirectParams['invoiceID'],
'paymentMethodNonce' => $nonce,
'options' => array(
'storeInVaultOnSuccess' => true,
),
));
is there something wrong in my code? why for one transaction two customer record are created? For first record first and last name are recorded. But second case no such detail are stored.
First creation of customer is required for second and third step.
Full disclosure: I work at Braintree.
Your code is creating two separate customers because when you call Transaction::sale it does not have the customer from your Customer::create call tied to it, and you have the option set to store the payment method in the vault upon success. This creates a customer when saving the payment method from the transaction, because a payment method must be tied to a customer. To resolve your problem, pass the customer id returned from Customer::create as a customerId param when you call Transaction::sale.
Braintree_Transaction::sale(array(
'amount' => $mapCidInvoiceID['amount'],
'orderId' => $redirectParams['invoiceID'],
'customerId' => $customerParams->customer->id
'paymentMethodNonce' => $nonce,
'options' => array(
'storeInVaultOnSuccess' => true,
),
));

Categories