Stripe keep the current discount of a subscriber - django

I am currently working on a django project and I integrated stripe to manage monthly subscriptions and renew automatically. Everything is working fine but a problem persists.
I have a page to change payment information for a subscriber. For the sake of simplicity, when his card is updated, I recreate a new subscription and delete the old one.
If, for example, he has a reduction of 3 months and he has 1 month left, how to take his current reduction voucher and reintegrate it into the new subscription without restarting the period from zero?
here is the subscription creation code, when the user registers for the first time, it integrates the promo code ID if there is one. It works very well :
obj_sub_created = stripe.Subscription.create(customer=stripe_customer.id,coupon = discount_code,items=[{"plan": offer.stripe_plan_id
when a subscriber changes their credit card, I cancel their subscription and recreate a new one. At this moment of the code, I know if there is a current and valid reduction. So I try this:
stripe.Subscription.delete(subscription_id)
obj_sub_created = stripe.Subscription.create(customer=stripe_customer.id,items=[{"coupon": discount}])
The discount variable is a copy / paste json of what stripe returns to me. But it does not work.
Would you have a solution to resume a promotion where she was on a new subscription when changing your credit card ?
thank you very much for your answers

Related

Cannot create a solution version There should be updates to at least one dataset after last active solution version with training mode set to FULL

I am having an AWS personalize solution with 3 successful solution versions trained with trainingMode = "FULL" using both AWS console and AWS SDK python. However when I tried to create a new solution version with trainingMode="UPDATE" as shown in the code below:
import boto3
personalize = boto3.client('personalize')
personalize.create_solution_version(solutionArn = solution_arn, trainingMode = "UPDATE")
I've got back the following exception:
Exception has occurred: InvalidInputException
An error occurred (InvalidInputException) when calling the CreateSolutionVersion operation: There should be updates to at least one dataset after last active solution version with training mode set to FULL.
Anyone experiencing this issue, is there anything I miss to be able to train with an UPDATE mode?
The purpose of trainingMode="UPDATE" is to process new items added to the items dataset (via PutItems or a bulk upload) as well as impression data for new interactions added to the interactions since the last FULL/UPDATE training. The new items and impressions are used to update the exploration feature for solutions created with the aws-user-personalization recipe. That is, to bring in new/cold items for exploration and to adjust probabilities for existing cold items in further exploration. Note that UPDATE only brings in new items and impression data and does not retrain the model.
Therefore, if there are no dataset updates since the last FULL/UPDATE, there is no value in creating a new solution version with UPDATE.
Finally, keep in mind that Personalize automatically updates solution versions created with the aws-user-personalization recipe every two hours at no cost. This essentially does an UPDATE for you.
With User-Personalization, Amazon Personalize automatically updates the latest model (solution version) every two hours behind the scenes to include new data without creating a new solution version. With each update, Amazon Personalize updates the solution version with the latest item information and adjusts the exploration according to implicit feedback from users. This allows Amazon Personalize to gauge item quality based on new interactions for already explored items and continually update item exploration.
If you create a solution version with UPDATE, you will be charged for the server hours to perform the update. Practically speaking, the only time you would need to manually create a solution version with UPDATE is when you do not want to wait for the next automatic update.

Authorize.Net Query on recurring billing

We have been trying to integrate authorize.net payment gateway in one of our clients project based on Asp.net web API. We have few queries that we came across while implementing Recurring Planning scenarios.
Query 1
We checked the API’s for Creating Subscription, Getting Subscription, Updating Subscription. However once we have created subscription, is there any way we can update the amount in the subscription.
Let’s say for example.
We have a created a subscription for our user for 50$ amount on 01st Jan 2021 with 30 days interval.
And on 15th Jan 2021, our user wishes to purchase 1 more license which will cost him 10$ more.
Hence can we increase his billing cycle of subscription by updating the subscription?
We checked in Update Subscription API, & it is only allowing to update credit card info hence is there any way to update amount.
Query 2
Is there any way to implement Autorenewal, hence when a user wishes he/she can set auto renewal on/off for recurring billing.
Query 3
If there is any way to switch off auto renewal of recurring billing, then is there any link that we can generate & send them through which they can pay there next due.
Query 1: You cannot update a subscription amount. If the amount needs to change you either need to cancel the current subscription and create a new one for the new amount (being sure to prorate credit from the previous subscription payment) or use CIM to manage your subscription service which allows you to charge against their card at your discretion but requires you to also manage the subscription yourself.
Query 2: Not through Authorize.Net. If you want a subscription to start or end you need to explicitly do so through their API.
Query 3: Not through Authorize.Net. That application logic and, once again, you would be responsible for managing.
I'm assuming you are using or are aware of the API provided for Authorize.net here: https://github.com/AuthorizeNet/sdk-dotnet/tree/master/Authorize.NET/Api/Controllers
Query 1: As of now, there is a way to update the amount for a given subscription. You can use ARBSubscriptionType class. There is an amount property there you can set. Then you can create the request ARBUpdateSubscriptionRequest, passing in the ARBSubscriptionType class and the subscription Id.
Note: You might have to handle pro-rating.
Query 2: There isn't a built in renewal feature in Authorize.Net as far as I know. It seems like you could potentially update the totalOccurrences by some amount to act as a "renewal", when technically its an extension of the subscription. The method in which you check when to update, either a Modulo operation or a date check is up to you. You can use paymentScheduleType class to update totalOccurrences, passing it along to a ARBUpdateSubscriptionRequest.
Query 3: Authorize.Net does not have any in house link generation.

Stripe Webhooks: Invoice.paid vs Checkout.Session.Completed

I use Stripes' webhooks and want to get notified, if the customer successfully "paid the bill". I came across two webhooks, which in my opinion both could do the job:
Webhook "invoice.paid" - According to Stripe doc: Occurs whenever an invoice payment attempt succeeds or an invoice is marked as paid out-of-band.
Webhook "checkout.session.completed" - According to Stripe doc: Occurs when a Checkout Session has been successfully completed.
My questions are:
I don't understand the second part of the "invoice.paid" webhook: "invoice is marked as paid out-of-band" -> What does "out-of-band" mean? Is this to be considered a successful payment?
Regarding "checkout.session.complete" -> This can also occur, if payment fails - correct?
Which webhooks shall I consider (or are there other webhooks) to see the status "customer paid the bill successfully"?
What is more, I don't really know if disputes should be considered as successful payments or not: On one hand, I get a invoice.paid webhook, on the other hand, I get a charge.dispute.created webhook. geeezus...
I appreciate your help! Thanks.
I don't understand the second part of the "invoice.paid" webhook: "invoice is marked as paid out-of-band" -> What does "out-of-band" mean? Is this to be considered a successful payment?
This is specifically referring to marking an invoice paid out of band (ie, the customer paid you outside of Stripe and you want to mark the Stripe invoice paid without collecting a payment). This will not involve an actual payment, but does transition the invoice to status=paid so this event fires.
Regarding "checkout.session.complete" -> This can also occur, if payment fails - correct?
This event signals only that the Checkout session is complete. Depending on the mode use for Checkout, this may or may not involve a payment. If an immediate payment is expected, the session will only complete if that payment is successful. For example mode=setup or mode=subscription with a free trial will not involve an immediate payment. A subscription with trial, though, will create a $0 invoice and fire invoice.paid.
Which webhooks shall I consider (or are there other webhooks) to see
the status "customer paid the bill successfully"?
This depends on what you mean by "paid" and "bill". If you mean specifically for invoices (whether related to subscriptions or not), then invoice.paid is a good choice. You can then filter for amounts greater than $0 etc to further constrain was "paid" means.
What is more, I don't really know if disputes should be considered as
successful payments or not: On one hand, I get a invoice.paid webhook,
on the other hand, I get a charge.dispute.created webhook.
Disputes are not payments, and should be an entirely separate discussion. You can only have a dispute after a payment. Suggest starting by reading the docs on disputes.
To summarize: What are you really trying to do? These events are related and sometimes overlap, but not always. It highly depends on what you're doing.
What's going on?
When you create a checkout session it will have an id, which you'll store in your database next to the user who started the checkout session.
When you receive an invoice.paid webhook event, it does not have any link back to the checkout session! (so you'll know someone paid, but you won't know who paid!)
checkout.session.completed solves this because it contains the id of the checkout session and the stripe customer id, which allows you to link the two, so you basically have a mapping from your customer ids to stripe's customer ids.
So simply grab the customer id from the checkout.session.completed event and store it in your database next to the relevant user, that way you'll be able to tell which one of your users is paying you when you receive an invoice.paid event!
How can this be implemented?
When a checkout session is started, store the checkout session id next to the user who started the session so you can look it up later
When you see checkout.session.completed, look at the accompanying JSON and take the stripe customer number and store it in your database (e.g. a column like stripe_id in users table). To figure out which of your users it's for, use the checkout session id to look it up in your database (i.e. the data you stored in step 1)
Now that you have the stripe customer id stored in your users table, whenever you see invoice.paid, look at the accompanying JSON, take the stripe customer number, look it up in your users table to find who paid, and update the expiry date of their subscription to 1 month into the future.
That's it!
Also good to know
Both checkout.session.completed and invoice.paid events are triggered when someone new subscribes, and only invoice.paid is triggered each month thereafter (presuming the user had enough funds and didn't cancel)
You can get to the stripe customer number in both webhook events like so (this is ruby, but should be similar with js or python):
payload = request.body.read
data = JSON.parse(payload, symbolize_names: true)
data.object.customer
=> "cus_Lvyv721cJGpYB1"

People.Connections.List nextSyncToken expires after one week

I am working on an contact sync solution to be able to keep the contacts in our app in sync with the google contacts of the user.
Our code uses the php library for the google people api latest Version (v1).
Everything is working fine for one week with each user but after that week we get:
400 - Error "Sync token is expired.
Clear local cache and retry call without the sync token".
My question now:
Is this intended behaviour that you have to clear all your cache after one week with no changes or am I doing something wrong?
Is there any possibility to renew a syncToken if there were no changes?
I already checked the whole code to be sure that the new received nextSyncToken is saved at our side and used for the next incremental sync request. It seems that the new sync Token is always the same as the one sent in the request. Thus it is just clear that we get that errors if a sync token expires after exactly one week.
I also tried to set the option requestSyncToken to true for every list request, even if also a syncToken is set. No success. Sync token stays the same after each request with no changes.
Just in case someone is also facing this problem (syncToken expiration after one week without changes in the persons/contacts list):
Our solution was:
Save the creation date and time of a new syncToken each time you
get one together with the syncToken.
When you receive a syncToken in an incremental sync process compare that token to the stored one. If the syncToken is a new
one, overwrite the old one and its creation date/time.
Use a continuous process that checks each syncToken. If one is about one week old (for security reasons we used 6 days) create a new
syncToken (process see below). As the people API does not offer
things like the watch-channels of the calendar API you would anyway
need some continuous processes that do list-calls in fixed time
intervals for a complete real-time synchronization - so maybe you
could combine these tasks depending on your solution for this
problem?!
Process for creation of a new SyncToken:
Do a new list request without providing a syncToken.
For additional security do some checkups like compare the total persons received with the total persons expected by the old/current
data. And do this renew process at a time of the day when almost no
one does changes generally, for example like 2am.
Overwrite the old syncToken and date/time with the new one and the current date/time.
That's it.
But attention! You can still miss some changes that were made if your syncToken renew process is running exactly at the time a change is made!
Create a dummy contact before the sync to get a new syncToken. After the sync delete the dummy contact from both Google Contacts and your cache.

Partially apply a CreditMemo on NetSuite API

im working on an integration between our company systems and NetSuite using PHP. Before the newest release of the NetSuite platform we were able to partially apply an existing credit memo to an specific pending invoice, but since their last release a couple of weeks ago every time we try to apply the credit to an specific invoice through our middle PHP system, it also applies all the other pending invoices in the account.
Let me specify a little more:
We have customer accounts, every account can have any number of open invoices. Lets say we have 3 invoices in the account 1. The first is for $20, the second for $30 and the last for $25. Then we create a credit memo associated to the account 1 for $75.
Then a week later we want to kill the first invoice of the account 1, the one with the $20 value. Then we command the credit memo to kill that invoice through our system. That would mean the first invoice is cancelled, we used $20 from the $75 we had in the credit and we still have $55 without use. Right?
Well, now for some reason the credit kills all the 3 invoices the account 1 had pending, even though we specify that only the first one should be applied. That consumes all the $75 of the credit memo, which of course messes up our accounting and prevents us from using it later in other invoices as we need it.
Just a few more points:
We are uploading our credit memos with property "autoapply" set on false.
When we want to apply an invoice we set its "apply" property as true and the ones from the other invoices as false, then we make an update request for the credit memo with that info. Thats how we always did it but now for some reason it doesnt works.
Sorry if its a little long, but i wanted to be really specific. If you have had a similar problem or have any insight on the matter i would greatly appreciate any help you can give. Thanks.
One suggestion you can try as I have experienced this as well. I had an issue where the user whose log in I was using for the integration entered a new credit memo, checked the box to auto apply and from then on every CM I imported through web services auto applied and did not respect the Auto Apply setting I submitted.
Log in as the user that you are authenticating with for the integration. Open a new credit memo and see if the Auto Apply check box is checked by default. This is a "sticky" setting in NetSuite. Enter a new CM As the user with the box unchecked and then delete it if you like. When I did this it stopped checking the box automatically and my CM import worked as expected again.