How to specify the duration of subscription in Stripe - stripe-payments

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

Related

Stripe preview invoice without an active subscription

Can we query Stripe with the subscription_items and a quantity to preview the incoming invoice without an active subscription with the Preview API https://api.stripe.com/v1/invoices/upcoming?
We tried to set subscription_items to preview an invoice without an active subscription. Its response contains a subscription and subscription_item. But when we query the subscription or subscription_item specifically, it threw an error Invalid subscription_item.
Eg, When calling /v1/invoices/upcoming with subscription_items
curl --location -g --request GET 'https://api.stripe.com/v1/invoices/upcoming?customer=cus_MIjwgFDqhg8uBf&subscription_items[0][price]=price_1LDx6JL3XoZTtiHnl5wAWtkg&subscription_items[0][quantity]=1' \
--header 'Authorization: Basic xxxxxx'
{
"object": "invoice",
"lines": {
"object": "list",
"data": [
{
"subscription": "sub_1LeoDVL3XoZTtiHn998jF9zp",
"subscription_item": "si_MNZM3MetxDd9Gu"
}
]
}
}
Then when we query the subscription or subscription_item with /v1/subscription_items/si_MNZM3MetxDd9Gu, it shows Invalid subscription_item:
{
"error": {
"message": "Invalid subscription_item id: si_MNZM3MetxDd9Gu",
"type": "invalid_request_error"
}
}
When you are viewing an upcoming invoice, you are simply viewing a preview – the invoice and subscription has not yet been created. So you cannot query the subscription or subscription item in the response from the upcoming invoice API.
https://stripe.com/docs/api/invoices/upcoming does not require an active Subscription. subscription is an optional parameter. The Stripe docs mention :
The identifier of the subscription for which you’d like to retrieve the upcoming invoice. If not provided, but a subscription_items is provided, you will preview creating a subscription with those items....
The below Node.js example code previews creating a subscription :
const invoice = await stripe.invoices.retrieveUpcoming({
customer: 'cus_...',
subscription_items: [
{
price : `price_...`,
quantity : 2
}
]
});

How to set products in Stripe Customer Portal

I have a Stripe account for a company selling subscriptions on two websites:
on website A: subscription plans A1, A2, A3 (these are Products in Stripe parlance)
on website B: subscription plans B1, B2 (also Products)
I would like to use the Customer Portal to allow the customers of both websites to manage their plan. I would like to show only show the respective plans on the portals created for each website.
Is it possible? How can I achieve this?
I see that we can provide a configuration built at runtime when creating a portal session, but I don't see how to specify the product set.
You can use the Customer Portal Configuration object’s features.subscription_update.products parameter to specify the products available in the portal session. This is what that would look like in Python:
stripe.billing_portal.Configuration.create(
business_profile={
"headline": None,
"privacy_policy_url": "https://example.com/privacy",
"terms_of_service_url": "https://example.com/tod"
},
features={
"subscription_update": {
"default_allowed_updates": ["price", "quantity", "promotion_code"],
"enabled": True,
"products": [
{
"product": "prod_B1",
"prices": [
"price_123",
"price_456"
]
},
{
"product": "prod_B2",
"prices": ["price_789"]
},
]
},
"payment_method_update": {
"enabled": True
},
},
)
session = stripe.billing_portal.Session.create(
customer="cus_123",
return_url='https://example.com/account',
configuration=configuration.id
)

Schema for inheriting content from central down to subsidiary

We have a content model where we set content at a central level, but users have the ability to edit the content down to subsidiary level if they want to. If they don't want to change anything from what gets set from central they don't have to.
Let's assume a simple api endpoint that just takes in companyId. This is how it would respond:
GET /offers (central values)
[{
offerId: 1,
title: "Central offer title",
paragraph: "Lorem ipsum central",
price: 100
}, {...more offers}]
Company 123
/offers?companyId=123
[{
offerId: 1,
title: "Company offer title",
paragraph: "Lorem ipsum central", // Inherited from central
price: 125
}, {...more offers}]
Company 456 which is a subsidiary to 123
/offers?companyId=456
[{
offerId: 1,
title: "Company offer title", // Inherited from Company 1
paragraph: "Lorem ipsum subsidiary",
price: 125, // Inherited from Company 1
custom_field: "A completely custom field for subsidiary" // Field only available for subsidiary
}, {...more offers}]
In previous implementations we have done something in the lines of:
{
offerId: 1,
values: [
{
companyId: null,
title: "Central offer title",
paragraph: "Lorem ipsum central",
price: 100
},
{
companyId: 123,
title: "Company offer title",
price: 125
},
{
companyId: 456,
paragraph: "Lorem ipsum subsidiary",
custom_field: "A completely custom field for subsidiary"
}
]
}
And then in the application we have compiled this down so values are specific for subsidiary, but still inheriting data from central or parent company.
Now that we're about to write new applications that should once again allow this type of content inheritance, we're having doubts about this approach and wonder if there's another way to model this.
What other ways exist to model this type of behavior?
Are you using mongoose? If so - use Discriminators:
const event1 = new Event({ time: Date.now() });
const event2 = new ClickedLinkEvent({ time: Date.now(), url: 'google.com' });
const event3 = new SignedUpEvent({ time: Date.now(), user: 'testuser' });
More on that topic in this fine read: https://dev.to/helenasometimes/getting-started-with-mongoose-discriminators-in-expressjs--22m9
If not - then I think you should follow the same approach as in mongoose - have each company as a separate document. Because in your old setup, there are a few things:
Company resides in Offer document
If multiple offers use the same companies, you'd duplicate company data, right?
There's no easy way to search for company - you get offers.values and search for a property inside. That's basically traversing your entire database.
If you only search by company (and not offer ID as you said), you can reverse them. But it's still weird. I'd split them in two separate things and use references between them. This way you could:
Find company by id
Find it's parent (do this until there is no parent; use aggregate to make it in a single query)
Get a list of offers for that company (document property) and query them
This approach would allow you to do the opposite (offer to company).

Quota exceeded for quota group 'AnalyticsDefaultGroup' and limit 'Requests per user per 100 seconds'

I'm trying to pull data from google anlytics using googleapis npm.
let res= await analyticsreporting.reports.batchGet({
requestBody: {
reportRequests: [
{
viewId: defaultProfileId,
dateRanges: dateRanges,
metrics: [
{
expression: 'ga:users',
},
{
expression: 'ga:sessions',
},
{
expression: 'ga:bounces',
],
dimensions: [
{
name: 'ga:source'
},
{
name: 'ga:medium'
},
{
name: 'ga:channelGrouping'
}
]
},
],
},
});
where dateRanges contains the date
{
startDate: "2017-01-01",
endDate: "2017-01-01",
}
to
{
startDate: "2020-05-13",
endDate: "2020-05-13",
}
When calling this, error says Error: Quota exceeded for quota group 'AnalyticsDefaultGroup' and limit 'Requests per user per 100 seconds' of service 'analyticsreporting.googleapis.com'.
How can I increase quota?
Documentation says By default, it is set to 100 requests per 100 seconds per user and can be adjusted to a maximum value of 1,000. From where it can be increase the limit quota?
There are two types of Google quotas.
project based
user based.
Project based quotas effect your full project. You can by default make 50000 request per day over your full project. This quota can be extended.
User based quotas are mostly for flood protection to ensure that your application doesnt run to fast and spam the server.
Error: Quota exceeded for quota group 'AnalyticsDefaultGroup' and limit 'Requests per user per 100 seconds' of service 'analyticsreporting.googleapis.com'.
The quota you are hitting is a user based quota you can max make 100 request per 1000 seconds. This quota can not be extended byond that point you need to slow your application down. Using exponential backoff
To increase it go to the google developer console under library -> google analytics -> manage -> quota menu and there is a penile icon near the quota in question.

O365 Calendar API recurring meeting info not returned

I am using the O365 API for Calendar, which I understand is currently in preview. When querying the /Calendar/Events endpoints, all created events are returned, but does not seem to be returning the correct "Recurrence" info. I made several events in O365 that recur every workday with no end date, but the API does not seem to return this info.
Is there a workaround for this to get meeting recurring info?
Photohunts,
To see the recurrence information, you will need to navigate to the specific Event.
For example:
https://outlook.office365.com/EWS/OData/Me/Events('AAMkADU5OWRjMWIwLThmNTMtNGM0NC1iM2UwLWEzODE3NjZlOTAwYQBGAAAAAABhjWDlvPXlRIwLplz9WovhBwAGqPuO3lPFTZQQq7HNVCBIAAAB3pf9AABBCWIB9tA-TaTLczumGiYyAACHmWVwAAA=')
you will see information like this below:
Recurrence: {
Pattern: {
Type: "Weekly",
Interval: 1,
Month: 0,
Index: "First",
FirstDayOfWeek: "Sunday",
DayOfMonth: 0,
DaysOfWeek: [
"Thursday"
]
},
Range: {
Type: "EndDate",
StartDate: "2014-07-03T00:00:00-07:00",
EndDate: "2014-12-31T00:00:00-08:00",
NumberOfOccurrences: 0
}
}

Resources