For some reason, when you create a "Subscription Schedules" stripe, it has very odd behavior where instead of trying to charge the customer, it keeps the invoice in draft for 1 hour and then closes the invoice and charges the customer.
I already have the card in the customer. I wonder if there is any way I can force the first phase of the subscription to be charged immediately.
My code:
$phases = [
[
'items' => [
[
'price_data' => [
'currency' => 'usd',
'product' => $product->stripe_product_id,
'recurring' => [
'interval' => $payment_plan['frequency'],
],
'unit_amount' => $payment_plan['stripe_amount']
],
'quantity' => 1,
],
],
'iterations' => (int) $payment_plan['total_payments']
],
];
$subscription = $stripe->subscriptionSchedules->create([
'customer' => $customer->stripe_customer_id,
'start_date' => 'now',
'end_behavior' => 'cancel',
'phases' => $phases,
]);
If you want to create a subscription immediately, you can do that without a Subscription Schedule and then set the schedule for that existing subscription:
https://stripe.com/docs/billing/subscriptions/subscription-schedules/use-cases#existing-subscription
Alternatively, if creating with the schedule like you're doing, once the subscription/invoice is created (as a draft) you can use the API to finalize it manually to proceed with the payment:
https://stripe.com/docs/api/invoices/finalize
Here is the solution:
$subscription = $stripe->subscriptionSchedules->create([
'customer' => $customer->stripe_customer_id,
'start_date' => 'now',
'end_behavior' => 'cancel',
'phases' => $phases,
]);
// now the invoice is a draft so we go get this invoice
$invoice = $stripe->invoices->all([
'limit' => 3,
'status' => 'draft',
'subscription' => $subscription->subscription,
'customer' => $customer->stripe_customer_id,
]);
//get the most recent draft
$invoice = $invoice->data[0];
//finalize the invoice (but this don't generate the payment for some reason)
$stripe->invoices->finalizeInvoice(
$invoice->id, [
'auto_advance' => true
]
);
//finaly pay the invoice
$invoice = $stripe->invoices->pay($invoice->id,[
'payment_method' => $token
]);
Related
I have a function a stripe function that slashes the price of a product, and I am trying to charge the newly slashed price after 5 minutes.
in my checkoutController I have
public function secondHalf($id){
// fetch the price
$productprice = Product::where('id', $id)
->pluck('price')
->firstOrFail();
// slash price into half
$slashPrice = intdiv($productprice,2); // divide by 2
// commence payment
\Stripe\Stripe::setApiKey(config('stripe.sk'));
$session = \Stripe\Checkout\Session::create([
'line_items' => [
[
'price_data' => [
'currency' => 'gbp',
'product_data' => [
'name' => 'tax online payment',
],
'unit_amount' => $slashPrice*100,
],
'quantity' => 1,
],
],
'mode' => 'payment',
'success_url' => route('success'),
'cancel_url' => url('/single-product/'.$id),
]);
$details = ['email' => 'thomsontochi#gmail.com'];
$emailJob = (new AfterPayment($details))
->delay(Carbon::now()
->addMinutes(5));
dispatch($emailJob);
return redirect()->away($session->url);
}
it basically find the product, slash the price and I then charge the slashed price.
I have tried making a job , called LatePaymentCharge and I took the function that handles the charge to the job like so
public function handle()
{
$slashPrice = $this->slashPrice;
//dd('stipe checkout');
\Stripe\Stripe::setApiKey(config('stripe.sk'));
$session = \Stripe\Checkout\Session::create([
'line_items' => [
[
'price_data' => [
'currency' => 'gbp',
'product_data' => [
'name' => 'staxo online payment',
],
'unit_amount' => $slashPrice*100,
],
'quantity' => 1,
],
],
'mode' => 'payment',
'success_url' => route('success'),
// 'cancel_url' => url('/single-product/'.$id),
]);
return redirect()->away($session->url);
}
I am currently having issues on how to pass the slash price value from my checkoutController to my job and im not sure if this is the right way to do it . please help
I'm using Stripe for one-time payments and subscriptions.
To create a payment, I use Stripe Checkout:
\Stripe\Checkout\Session::create([
'customer' => 'cus_XXXXX',
'success_url' => '',
'cancel_url' => '',
'payment_method_types' => ['card'],
'mode' => ($isSubscription ? 'subscription' : 'payment'),
'line_items' => [...]
]);
header('Location: '.$checkout_session->url);
exit;
This code automatically create an invoice for subscription mode but not for one-time payments.
I've tried this to create a new invoice but how can I do to make it related to previous payment, closed and paid?
$stripe = new Stripe\StripeClient('xxx');
$stripe->invoiceItems->create([
'customer' => 'cus_XXXXX',
'amount' => '1000',
'currency' => 'eur',
'description' => 'Lorem ipsum...'
]);
$invoice = $stripe->invoices->create([
'customer' => 'cus_XXXXX',
]);
I found a way to create an invoice for each payment mark paid.
This, however, doesn't link them to a payment.
On the webhook checkout.session.completed do the following:
$stripe = new Stripe\StripeClient('xxx');
// Create invoice lines
$stripe->invoiceItems->create([
'customer' => 'cus_XXXXX',
'amount' => '1000',
'currency' => 'eur',
'description' => 'Lorem ipsum...'
]);
// Create invoice
$invoice = $stripe->invoices->create([
'customer' => 'cus_XXXXX',
]);
// Finalize and mark invoice paid outside of Stripe
$invoice->finalizeInvoice();
$invoice->pay(['paid_out_of_band' => true]);
I believe you are looking for this: https://stripe.com/docs/payments/checkout/post-payment-invoices
To enable invoice creation, set invoice_creation[enabled] to true when
creating a Checkout session.
The old way of doing this was as follows
$customer = \Stripe\Customer::create(array(
"description" => $domain,
"email" => $email,
"source" => $token,
"metadata" => array(
"name" => $name,
"phone" => $phone
),
));
$cus = $customer->id;
\Stripe\Subscription::create(array(
"customer" => $cus,
"plan" => "1",
));
But now I do not see the "PLAN" option on the subscription create. Here is what I have so far...
$customer = $stripe->customers->create([
'description' => 'Description text here nomadweb.design',
'name' => 'Sammy Malones',
'email' => 'name#email.com',
'phone' => '5124592222'
]);
$cus = $customer->id;
$stripe->subscriptions->create([
'customer' => $cus,
'plan' => '1'
]);
In the API Docs is says that it's required to use the items parameter.
My question is how to I add a subscription to a customer with the newer api?
This is their code but I don't understand
$stripe->subscriptions->create([
'customer' => 'cus_J34i3JonNQQXdO',
'items' => [
['price' => 'price_0IQyZLH7HxDXZRHqJfpwwqBB'],
],
]);
https://stripe.com/docs/api/subscriptions/create
In my stripe dashboard I have a product created which is a monthly subscription, it has an ID like prod_BlMuxdEQJSxfKJ So I'm guessing I need to pass that ID in somehow as an item?
I would encourage you to read about Prices, the successor to Plans, but you can also provide an existing Plan like plan_123 to the subscription creation request, and it will be converted to a Price for you:
$stripe->subscriptions->create([
'customer' => 'cus_123',
'items' => [
['price' => 'plan_123'],
],
]);
You can't provide a Product here directly, as Products are not directly tied to any amount or interval. You need to create Prices for those Products, either using the API or your Dashboard.
When creating a subscription, you can optionally define the recurring pricing ad-hoc, using price_data (API doc) and referencing the Product to be used:
$subscription = $stripe->subscriptions->create([
'customer' => 'cus_123',
'items' => [[
'price_data' => [
'unit_amount' => 5000,
'currency' => 'usd',
'product' => 'prod_456',
'recurring' => [
'interval' => 'month',
],
],
]],
]);
Thank you to Nolan, it looks like you need to grab the product pricing API ID which is provided in the dashboard.
Here is the updated code
$stripe->subscriptions->create([
'customer' => $cid,
'items' => [['price' => 'price_0IR0OGH7HxDXZRHq3sIg9biB'],],
]);
Here the price ID is attaching the product which is a subscription to the customer.
if you are using laravel and stripe php sdk with it then you can do it like this below:
\Stripe\Stripe::setApiKey(env('STRIPE_PRIVATE_KEY'));
// Use an existing Customer ID if this is a returning customer.
// $customer = \Stripe\Customer::create([
// "description" => $domain,
// "email" => $email,
// "source" => $token,
// "metadata" => [
// "name" => $name,
// "phone" => $phone
// ],
// ]);
$customer = \Stripe\Customer::create();
// $customer_id = $customer->id;
$Subscription = \Stripe\Subscription::create([
'customer' => $customer->id,
'items' => [[
'price' => $price_id,
]],
'payment_behavior' => 'default_incomplete',
'expand' => ['latest_invoice.payment_intent'],
]);
$ephemeralKey = \Stripe\EphemeralKey::create(
['customer' => $customer->id],
['stripe_version' => '2020-08-27']
);
// $paymentIntent = \Stripe\PaymentIntent::create([
// 'amount' => $amount,
// 'currency' => $currency,
// 'customer' => $customer->id
// ]);
$response = [
'request' => $data,
'paymentIntent' => $subscription->latest_invoice->payment_intent->client_secret,
'ephemeralKey' => $ephemeralKey->secret,
'customer' => $customer->id,
'subscriptionId' => $subscription->id,
];
return response($response, 200);
And then in your front end you can process the payment with the help of your paymentIntent secret.
I'm using Stripe PHP SDK to create a subscription plan dynamically.
use \Stripe\Plan;
Plan::create(array(
"amount" => 2000,
"interval" => "month",
"name" => "Amazing Gold Plan",
"currency" => "usd",
"id" => "gold")
);
I wanted to ask is there a way to mention/handle the duration of a plan. Like I wanted to make a subscription by the plan for a limited time suppose 3 months and after 3 months I wanted the plan to automatically get removed from the subscription. I don't want to cancel the whole subscription as in my case there could be multiple plans associated with a subscription. SO I simply want to remove/detach the plan from the subscription.
I had gone through the Stripe SDK docs to find this but to no avail.
A Subscription Schedule [1] will be what you require here to automate changes to the underlying Subscription using phases [2].
The use of a schedule will allow you to specify, for example, a monthly Price that will iterate for 3 months in the first phase. Then you can define in the next phase what will happen, for example change the Prices in some way, like adding or removing Prices. An example may look like this:
\Stripe\SubscriptionSchedule::create([
'customer' => 'cus_xxx',
'start_date' => 'now',
'end_behavior' => 'release',
'phases' => [
[
'items' => [
[
'price' => 'price_print', # Monthly Price
'quantity' => 1,
],
],
'iterations' => 3, # Iterates for 3 months
],
[
'items' => [
[
'price' => 'price_print',
'quantity' => 1,
],
[
'price' => 'price_digital', # An extra price
'quantity' => 1,
],
],
'iterations' => 1, # Iterate for 1 month
],
],
]);
[1] https://stripe.com/docs/billing/subscriptions/subscription-schedules#managing
[2] https://stripe.com/docs/api/subscription_schedules/object#subscription_schedule_object-phases
I believe you need to create price instead of plan and the code would be like this (Not sure I use different platform but you can try)
use \Stripe\Plan;
$price = \Stripe\Price::create([
'product' => '{{PRODUCT_ID}}',
'unit_amount' => 1000,
'currency' => 'usd',
'recurring' => [
'interval' => 'month',
'interval_count' => 2 //Try tweaking this value for change
],
]);
When transferring money to a connected account on Stripe using this code
// // Create a PaymentIntent:
$method = \Stripe\PaymentMethod::create([
'type' => 'card',
'card' => [
'number' => '4242424242424242',
'exp_month' => 12,
'exp_year' => 2020,
'cvc' => '314',
],
]);
$paymentIntent = \Stripe\PaymentIntent::create([
'amount' => $AMOUNT1,
'currency' => 'nzd',
'payment_method_types' => ['card'],
'payment_method' => $method->id,
'customer' => CUSTOMER_ID,
'transfer_group' => '{ORDER'.$_SESSION['order_id'].'}',
]);
// Create a Transfer to a connected account (later):
$transfer = \Stripe\Transfer::create([
'amount' => $AMOUNT2,
'currency' => 'nzd',
'destination' => $ACC_ID,
'transfer_group' => '{ORDER'.$_SESSION['order_id'].'}',
]);
The payment stores on the connected account's dashboard and says its completed but when it stores on my Payments tab it says that the payment is incomplete and that the buyer has not completed the payment
Prev1
Prev2
You need to confirm the payment intent, either by providing confirm=true at creation or by making a call to /confirm.
You're creating a transfer from your account to the connected one, which succeeds, and a payment that you never complete.