Stripe Subscription Schedule Testing - stripe-payments

1:How can I test and trigger subscription scheduled.
$plan = Plan::create([
'currency' => $currency,
'interval' => 'day',
'product' => $product,
'amount' => $amount
]);
$schedule = SubscriptionSchedule::create([
'customer' => $customer_id,
'start_date' => 'now',
'end_behavior' => 'release',
'phases' => [
[
'plans' => [
[
'price' => $plan->id,
'quantity' => 1,
],
],
'iterations' => 3,
'collection_method'=> 'charge_automatically'
],
],
]);
return $schedule;
So I create a subscription today, how I can test. Also when creating plan we can only specify billing frequency as either day, week, month or year.
Have already tried updating subscription Id with params
setting trial_end: Few seconds from now
prorate: false
But this creates invoice for the same month. Also its creates another invoice with amt:0.(Dont know why it created).
2: Is this the same approach for testing subscription schedule.

I use Stripe's Test Clocks. Basically you simulate progress of time by setting a date and time in the future in order to make your subscriptions happen. Unfortunately you cannot use your existing Test Subscriptions and Customers but you have to create them just for the specific simulation.

Related

Using Stripe Upcoming Invoice to preview changes in subscription

I want to use Stripe Upcoming Invoices to display how much a user will be billed when he makes changes to his subscriptions. But it seems that I miss something...
Why do I get 29 instead of 0?
dump($plans['basic_monthly']->price);
29.0
dump($plans['premium_monthly']->price);
49.0
$stripe_customer = step1_create_customer();
$stripe_subscription = step2_create_subscription($stripe_customer, $plans['basic_monthly']->stripe_price_id);
dump([
'reason' => 'Nohting was changed (price_id and quantity are the same), so 0 is expected. Why 29 is here?',
'expected' => 0,
'actual' => upcoming($stripe_subscription, $plans['basic_monthly']->stripe_price_id)->amount_due/100,
]);
array:3 [▼
"reason" => "Nohting was changed (price_id and quantity are the same), so 0 is expected. Why 29 is here?"
"expected" => 0
"actual" => 29
]
dump([
'reason' => 'Transition to more expensive plan was made. 49 - 29 = 20 is expected',
'expected' => 20,
'actual' => upcoming($stripe_subscription, $plans['premium_monthly']->stripe_price_id)->amount_due/100,
]);
array:3 [▼
"reason" => "Transition to more expensive plan was made. 49 - 29 = 20 is expected"
"expected" => 20
"actual" => 20
]
function step1_create_customer()
{
$stripe = new \Stripe\StripeClient(env('STRIPE_SECRET_KEY'));
$test_clock = $stripe->testHelpers->testClocks->create([
'frozen_time' => time(),
'name' => sprintf('Testing Upcoming Invoices'),
]);
$stripe_customer = $stripe->customers->create([
'test_clock' => $test_clock->id,
'payment_method' => 'pm_card_visa',
'invoice_settings' => ['default_payment_method' => 'pm_card_visa'],
'metadata' => [
'testing_upcoming_invoices' => 1,
],
'expand' => [
'test_clock',
'invoice_settings.default_payment_method',
],
]);
return $stripe_customer;
}
function step2_create_subscription($stripe_customer, $stripe_price_id)
{
$stripe = new \Stripe\StripeClient(env('STRIPE_SECRET_KEY'));
$stripe_subscription = $stripe->subscriptions->create([
'customer' => $stripe_customer->id,
'items' => [
[
'price' => $stripe_price_id,
'quantity' => 1,
],
],
'metadata' => [
'testing_upcoming_invoices' => 1,
],
]);
return $stripe_subscription;
}
function upcoming($stripe_subscription, $stripe_price_id)
{
$stripe = new \Stripe\StripeClient(env('STRIPE_SECRET_KEY'));
$stripe_invoice = $stripe->invoices->upcoming([
'subscription' => $stripe_subscription->id,
'subscription_items' => [
[
'id' => $stripe_subscription->items->data[0]->id,
'price' => $stripe_price_id,
'quantity' => 1,
],
],
'subscription_cancel_at_period_end' => false,
'subscription_proration_behavior' => 'always_invoice',
//'subscription_proration_date' => $now,
]);
return $stripe_invoice;
}
What your code is doing here is upgrading a Subscription from Price A ($29/month) to Price B ($49/month) immediately after creation. You're also passing subscription_proration_behavior: 'always_invoice'.
When you upgrade or downgrade a subscription, Stripe calculates the proration for you automatically. This is something Stripe documents in details here and here.
In a nutshell, since you move from $29/month to $49/month immediately after creation, what happens is that Stripe calculates that:
You owe your customer credit for the time they paid on $29/month that they won't use. Since it's immediately after creation, you owe them $29.
The customer owes you for the remaining time for the new Price. Since it's the start of the month they owe you the full price of $49.
In a default integration, the proration is created as 2 separate InvoiceItems that are pending until the next cycle. In your case you pass proration_behavior: 'always_invoice' so an Invoice is created immediately with only those 2 line items. -$29 + $49 = $20 which is where the amount comes from.

How to specify the duration of subscription in Stripe

I am implementing stripe subscriptions and I can't find anywhere in the api documentation how to specify the duration of the subscription when creating a checkout session. This is what I have so far:
const customer = await stripe.customers.create({
description: "My First Test Customer (created for API docs)",
email: "some.email#gmail.com",
address: {
city: 'Toronto',
country: 'CA',
line1: "Some Address",
line2: "Some unit number",
postal_code: "M5G0V1",
state: "ON",
},
name: "Some Name",
phone: "Some Number",
});
const price = await stripe.prices.create({
unit_amount: 599,
currency: 'cad',
recurring: {interval: 'month', interval_count: '1'},
product: 'prod_KZfHFK4nfCqlGS',
});
const subscriptionSchedule = await stripe.subscriptionSchedules.create({
customer: customer.id,
start_date: 'now',
end_behavior: 'cancel',
phases: [
{
items: [
{
price: price.id,
quantity: 1,
},
],
iterations: 24,
},
],
});
console.log(subscriptionSchedule);
const session = await stripe.checkout.sessions.create({
success_url: 'http://localhost:8080/stripeSessionSuccessHook',
cancel_url: 'http://localhost:8080/stripeSessionCancelHook',
payment_method_types: ['card'],
customer: customer.id,
line_items: [
{price: price.id, quantity: 1},
],
mode: 'subscription',
});
I am trying to create a subscription that the customer pays monthly for 24 months. I am using Subscription Schedule suggested in the answers, and indeed such subscription with 24 months is being created. However, when creating a new checkout, and in case the payment is successful, it will create a Subscription that spans for 12 months... In the end, I have 2 subscriptions. One created by Subscription Schedule (24 months, desired one), and other Subscription (12 months). Is there a way I can somehow pass this subscription schedule to checkout, so 2 subscriptions don't get created.
A Subscription would typically auto-renew after every billing cycle if it is paid for. The recurring.interval is set in the Price and the max recurring interval is a year.
If you want to end the subscription after 2 years, you would use Subscription Schedules : https://stripe.com/docs/billing/subscriptions/subscription-schedules.
For your use case, with a Price that has recurring.interval=year, you would create a Subscription Schedule that has a single Phase with iterations=2 and end_behavior=cancel.
You can refer to this example : https://stripe.com/docs/billing/subscriptions/subscription-schedules/use-cases#installment-plans
Note that Subscription Schedules does not currently work with Checkout or the Customer Portal. If you want to use Checkout, a workaround is :
The customer pays for the subscription via Checkout
Create a Subscription Schedule for the existing (and already paid for) subscription : https://stripe.com/docs/billing/subscriptions/subscription-schedules/use-cases#existing-subscription
Update the newly created Subscription Schedule parameters to end the subscription after 2 years : https://stripe.com/docs/api/subscription_schedules/update
You should not depend on the success redirect to perform any important actions on the client. On the client, the customer could close the browser window or quit the app before the redirection occurs. You would want to setup a webhook to listen for the checkout.session.completed event and create the Subscription Schedule upon receipt of this event.
You can read more about setting up webhooks here :
https://stripe.com/docs/payments/checkout/fulfill-orders
https://stripe.com/docs/webhooks

Why is it an error to use "token_xxxx" not associated with a Customer object for payment?

In the following PHP code, token_xxxx is associated with the Customer object
\Stripe\Stripe::setApiKey("sk_test_xxxx");
\Stripe\Customer::create([
"description" => "hoge",
"source" => "tok_amex"
]);
In the PHP code below, "token_xxxx" not associated with the Customer object is used for payment
\Stripe\Stripe::setApiKey('sk_test_xxxx');
$charge = \Stripe\Charge::create([
"amount" => 888,
"currency" => "USD",
"customer" => "cus_xxxx",
'source' => 'tok_visa',
]);
・An error occurred
Customer cus_xxxx does not have a linked source with ID tok_xxxx

Sensu subdue alerts outside working hours and weekends

I want to subdue some sensu checks outside working hours and weekends. The documentation is not clear on how it works. Sensu subdue documentation
'subdue' => {
'days' => {
'all' => [
{
'begin' => '8:00 PM',
'end' => '10:00 AM'
}
],
'saturday' => [
{
'begin' => '12:00 AM',
'end' => '11:59 PM'
}
],
'sunday' => [
{
'begin' => '12:00 AM',
'end' => '11:59 PM'
}
]
}
}
My question is: will the specific day override the all attribute?
Also: is there a better way to do this check?
Thanks!
Yes, Specific day override all attribute. We should add subdue configurations in our client.json file.

issue in stripe connected account to bank transfer

i have an issue in transfer.
my stripe connected account available bal is $200.00 and i have an transfer my $200.00 and pandding balance is $150.00 balance to my bank account.
to showing error insuficient funds in your stripe connected account
see my code:
\Stripe\Stripe::setApiKey($_REQUEST['secret_id']);
$transfer = \Stripe\Transfer::create(array(
"amount" => 20000,
"currency" => "usd",
"destination" => "default_for_currency",
"description" => $_REQUEST['description'],
"source_type" => "bank_account"
));
see output :
{
msg = "You have insufficient funds in your Stripe account for this transfer. Your ACH balance is too low. You can use the the /v1/balance endpoint to view your Stripe balance (for more details, see stripe.com/docs/api#balance).";
status = 0;
}
i need solution please.
Your account actually has more than one balance -- funds are split by payment source type.
If you send a balance retrieval request, you will get a result similar to this:
{
"available": [
{
"amount": 20000,
"currency": "usd",
"source_types": {
"card": 12000,
"bank_account": 8000
}
}
],
"livemode": false,
"object": "balance",
"pending": [
{
"amount": 0,
"currency": "usd",
"source_types": {
"card": 0,
"bank_account": 0
}
}
]
}
When you create a transfer, you should specify the source type via the source_type attribute. E.g. in PHP, you'd do something like this:
\Stripe\Transfer::create(array(
"amount" => 8000,
"currency" => "usd",
"destination" => "default_for_currency",
"source_type" => "bank_account"
));
On an unrelated note, it seems you're setting the API key via a client-side parameter:
\Stripe\Stripe::setApiKey($_REQUEST['secret_id']);
You should never share the secret API key with your client-side code. It would be very easy for an attacker to retrieve it and use it to issue API requests on your behalf. They'd be able to look at your transactions, delete saved customers, etc.
When any charge is succeeded in stripe, it takes some time to actually available it in stripe account.
If You want to create the transfer based on any amount collected by any charge, then you can directly use the charge id.
So your code should be like:
\Stripe\Stripe::setApiKey("your_secret_key");
$transfer = \Stripe\Transfer::create(array(
"amount" => 1000,
"currency" => "usd",
"source_transaction" => "{CHARGE_ID}",
"destination" => "{CONNECTED_STRIPE_ACCOUNT_ID}",
));
By using source_transaction, the transfer request succeeds regardless of your available balance and the transfer itself only occurs once the charge’s funds become available.
It is documented here

Resources