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.
Related
Consider sample chat application where user purchase monthly/annual subscriptions (subscriptions like Amazon Prime, etc).
As soon as the subscription expires, user should not be able to send messages in app.
User can end their subscription before the original subscription end date.
One solution in my mind (Frontend) - to cache the end date in app and before every "send message" operation, compare the end date and current date.
But the problem is - if user ends the subscription early, user will still be able to send the message.
How can I push update the new subscription end date in cache.
Another solution was (Backend) - I have a table in backend storing subscription details like subscription_id, user_id, subscription_enddate. So before any "send message" operation, query the subscription table and compare the dates and then continue/cancel further operations.
Q1. Should I go with Backend solution or can you please share some improvements to frontend method or any best practice for this scenario?
Q2. Also is storing subscription details in separate table best practice or any good design instead. ?
PS- Sample chat app is based on AWS Amplify Datastore
Let me try to breakdown the answer and give my opinion. I would also like to mention solutions to such problems are determined by the scale and various tradeoffs.
Q1-
If sending messages has an adverse effect, you should never rely on the frontend solution only as it is easy to bypass them. You can use a mixture to ensure that the load is not very high on the backend.
Adding a Frontend Cache for subscription will ensure you will be able to filter most of the messages on the frontend if the cache is not tampered with.
Adding a service before the queue, that validates whether the user subscription has expired adds one more layer of security. If the user subscription is valid it pushes the message to Queue else throws an error. This way any bad actor can also not misuse the system.
Q2-
Depending on the use-cases and load, you can have a separate table or a separate micro-service for the subscription itself.
When to have a separate micro-service?
When the subscription data is required from multiple applications in your system and needs to have its own scalability independent of others, it can be beneficial to have a separate micro-service.
When to have a separate table?
In other cases, where you feel adding a service would be overkill. You can keep the data separate in a different table/DB giving you the flexibility to change subscription and even extract it easily in the future.
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"
I have the following use case scenario for which I am considering aws services to see how I can come up with a scalable solution. Thanks in advance for your help!
Scenario:
Users can sign up to an application(which is named say 'Let's Remind' or something else) using their email and phone.
The app does one thing that is to send email and sms alerts to user.
User can create n number of tasks for which he wants to be reminded. For instance he can set up a
monthly reminder for paying card dues. Currently the value of n is from 5 to 10 per user.
The notifications are flexible meaning it can be daily, weekly, monthly, bi-weekly. User can also
specify the start date of a notification. The end date is the date when the event is due (for instance
the day the card payment is due). Once this date is expired the notification is rendered inactive for
the current month.
For weekly,daily,bi-weekly notifications, the notifications are deleted once the event date is passed.
These are not recurring in nature.
For monthly recurring events such as payment of apartment rent etc, notification itself is not
deleted but rendered inactive after the event due date. Once the next event cycle (typically next
month billing cycle for payments use case) starts, the notification comes back to life and starts all
over again.
Use can delete any event anytime he wants. If an event is deleted, the notifications for that event
will be deleted as well.
First of all, I hope the use case is clear. Now here's my thoughts so far about solving this use case -
1) Use SNS since I need to send email and sms both. SES only supports emails.
2) When a user registers for the app, create 2 subscriptions(one for his email and one for his sms endpoint) and also create a topic for the user(maybe a dynamically generated random userid)
3) Once user creates an event (e.g. reminder for monthly apartment rental), store the event data such as userid, startdate, duedate, frequency, isactive in a dynamodb table.
4) Create a lambda function that will wake up when an entry is written to the dynamodb table (step 3); it will do the following -
i) it will read the event data from the dynamodb table
ii) determine the next date of the notification to be sent based on the current date and event
data
iii) For active events (check isActive column of the dynamodb record) create a scheduled cron
expression rule based on ii above in cloudwatch events and add the
target as the user's topic (created in step 2 above). For now, the notification message is
static.
I have some doubts/queries about step iii -
Is it possible to create cloudwatch event cron rule dynamically and add the user's topic as target dynamically as I described? Or is it better to trigger a second lambda function dedicated for sending messages to the user's topic using SNS notification? Which approach will be better for this use case?
If user base grows large, is it recommended to create one topic per user?
Am I on the right track with my approach above in general from a scalability point of view?
If not, can anyone suggest any better idea for implementing this use case?
Thanks in advance!
This will not work.
For SNS email subscriber to receive email notification sent via SNS it has to first confirm the subscription. You cannot just create subscriptions on the fly and send them email notification
I don't think SNS fits your use case. You would be better off sending email notifications using SES.
You can write your scheduling logic in Lambda though
We are using authorize.net for payments in our checkout but in some cases we are not getting any response from authorize.net so we are unable to store transaction details in our database and also customers are being charged more than once. So to resolve this we are planning to get the transaction details before sending the payment but we don't have transaction id in our side, so we need a API to get the transaction details using invoice number.
I have searched lot in the API documentation but couldn't able to find it, so any reference might be helpful.
You cannot retrieve transaction information through their API with an invoice number. If you know the dates, and other helpful information about these missing transactions, you can use their Transaction Reporting API to get those day's transaction and retrieve the necessary information that way.
One way to avoid this in the future is to use either Silent Post1 or their new Webhooks API to get notified whenever a payment is made (and any other event you specify).
1 I am the author of that article.
I'm building a site on Rails using ActiveMerchant to clear payments through Authorize.net. We'd like to support paying for a subscription to the site using recurring credit card payments. The Authorize.net Gateway allows me to setup a schedule of recurring payments on a given interval from a specified date. I see (http://developer.authorize.net/tools/arberrorcodes/) that they will give me an error if the credit card's expiration date is before the start of the recurring payment period, or if the test transaction is not approved at the time that the recurring payment is setup.
What I'm unclear on is how best to handle transaction failures which may occur after the recurring payment has been setup. For example, what if the credit card used to setup the recurring payment is cancelled, or if the account has insufficient funds, before the end of the recurring period.
Should I be proactively checking the status of the subscriptions I have previously created in a cron job? Should I check the subscription status with Authorize.net each time my users login? Is there some other way in which I should expect to be notified if my previously valid subscriptions cease to be so?
Thanks.
Looks like the 'right' solution here is to support Authorize.net's 'Silent Post' callback. This will send transaction status on all cleared and failed transactions every night after they're run.
However, the status will only be sent once, so if it's not received for any reason, you'll still need to query subscription status through ARB proactively.