Standard method of upgrading a subscription in Braintree? - braintree

I am working on an integration for Braintree and trying to adapt the subscriptions to a model which can account for subscriptions which are "upgraded" from one plan to another. I can see that you can change the plan, and then separately update the price. However, this seems less correct than just cancelling a previous subscription and creating a new one.
So in summary, is there a native way to indicate upgrading a subscription or at least a best practice that most would follow for Braintree?

Full disclosure: I work for Braintree.
I would suggest changing the plan and then updating the price for your business model. Assuming upgrading plans includes an increase in price, you can easily prorate a subscription when the price changes in the middle of a billing cycle. In Ruby it would look like this:
​
result = Braintree::Subscription.update(
"subscription_id_to_update",
:price => "14.00",
:plan_id => "new_plan",
:options => { :prorate_charges => true },
)
One use case for canceling and then creating new subscriptions upon upgrade would be if the plan upgrade is on a different billing cycle, e.g. yearly instead of monthly, because you cannot update to a plan with a different billing cycle.
More information on updating subscriptions.
If you have any additional questions, feel free to reach out to Braintree support.

Related

Managing Queued jobs / Database connections / performance on Laravel Vapor

We are running our website on the AWS serverless infrastructure through Laravel vapor now. It runs on a serverless Aurora database and uses Amazon SQS as the queue driver. Basically the defaults for a Laravel Vapor deploy.
We are currently running into a performance issue that while we are trying to resolve it, has us smash our head into other walls we meet on our journey. So here we go.
What we want to do
Our customers can have various types of subscriptions that need to be renewed. These subscriptions come in all kinds of flavours, can have different billing intervals, different currencies and different prices.
On our customer dashboard we want to present them with a nice card informing the customer about their upcoming renewals, with a good estimate of what the cost will be, so they can make sure they have enough credits:
As our subscriptions come with different flavours, we have one table that holds the basic subscription details, such as net_renewal_date. It also references a subscriptionable_id of subscriptionable_type which is a morph relation ship to the different types of models that a user can have a subscription for.
Our first attempt
In our first attempt, we basically added a REST endpoint which fetched the upcoming renewal forecast.
It basically took all Subscriptions that were up for renewal the coming 30 days. For each of those items, we would calculate the current price in its currency, and add tax caculations.
That was then returned into a collection that we further used to:
1/ calculated the total per currency
2/ filter that collection for items within the next 14 days, and calculate the same total per currency.
We would then basically just convert the different amounts to our base currency (EUR) and return the sum thereof.
This worked great for the vast majority of our clients. Even customers with 100 subscriptions were no issue at all.
But then we migrated one of our larger customers to the new platform. He basically had 1500+ subcsriptions renewing in the upcoming 30 days, so that didn't go well...
Our second attempt
Because going through the above code simply doens't work in an acceptable amount of time, we decided we had to move the simulation calculation into a seperate job.
We added an attribute to the subscriptions table and called it 'simulated_renewal_amount'
This job would need to run every time when:
- a price changes
- the customer's discount would change (based on his loyalty, we provide seperate prices
- the exchanges rates change.
So the idea was to listen for any of these changes, and then dispatch a job to recalculate the simulated amount to any of the involved subscriptions. This however means that a change in an exchange rate for instance can easily trigger 10,000 jobs to be processed.
And this is where it becomes tricky.
Even though running just one job only takes less than 1200ms in most cases, it seems that dispatching a lot of jobs that need to do the same calculations for a set of subscriptions is causing jobs running 60+ seconds when they are being aborted.
What is the best practice to setup such a queued job? Should I just created one job in stead and process them sequentially?
Any insights on how we can best set this up to start with, would be very welcome. We've played a lot with it, and it always seems to be ending up with the same kind of issues.
FYI - we host the site on laravel vapor, so serverless on AWS infrastructure with an Aurora database.
We have got the same issue. Vapor supports multiple queues but it does not allow you to set job concurrency on a per queue basis, so its not very configurable for drip feeding lots of jobs. We have solved this by making a seeder job that pulls out serialized jobs from an "instant jobs" table. We added a sleep loop also to allow granular processing throughout the whole minute (a new seeder job is scheduled each minute).
public function handle()
{
$killAt = Carbon::now()->addSeconds(50);
do{
InstantJob::orderBy('id')->cursor()->each(function(InstantJob $job){
if($job->isThrottled()){
return true;
}
$job->dispatch();
});
sleep(5);
} while (Carbon::now()->lessThan($killAt));
}
The throttle, if you are interested works off a throttle key (job group/name etc.) and looks like:
public function isThrottled(): bool
{
Redis::connection('cache')
->throttle($this->throttle_key)
->block(0)
->allow(10) //jobs
->every(5) // seconds
->then(function () use(&$throttled) {
$throttled = false;
}, function () use(&$throttled){
$throttled = true;
});
return $throttled;
}
This actually solves our problem of drip feeding jobs onto the queue without actually starting them.
One question for you... We are currently using a small RDS instance and we get a lot of issues with too many concurrent connections. Do you see this issue with serverless db's? Do they scale fast enough to ensure no drop outs?

Upgrade plan on the next billing cycle - Laravel Cashier

I have a functionality where I need to upgrade a plan for a subscription but only on the next billing cycle.
Default behaviour, when using swap() method, is that the prorate is calculated and then Cashier figures out how much to charge. In my case that is not a good scenario since i'm selling fixed amounts through another table and my quantity is always 1.
I've manage to find a partial solution and implement it like this:
$customer->subscription($current_subscription->name)->noProrate()->swap($plan->plan_id);
And it does not calculate prorate, which is fine, however it upgrades the plan immediately without charging the customer. I'm looking for either to delay this upgrade until the next billing cycle (have a webhook tell me when to switch plans, or to charge the customer right away, which probably isn't the best solution).
I couldn't find anything on Cashier docs i'm wandering is there a solution to this, or should I just go with manually implementing logic for canceling the plan and then staring a new one with the trial.

Validate Command in CQRS that related to other domain

I am learning to develop microservices using DDD, CQRS, and ES. It is HTTP RESTful service. The microservices is about online shop. There are several domains like products, orders, suppliers, customers, and so on. The domains built in separate services. How to do the validation if the command payload relates to other domains?
For example, here is the addOrderItemCommand payload in the order service (command-side).
{
"customerId": "CUST111",
"productId": "SKU222",
"orderId":"SO333"
}
How to validate the command above? How to know that the customer is really exists in database (query-side customer service) and still active? How to know that the product is exists in database and the status of the product is published? How to know whether the customer eligible to get the promo price from the related product?
Is it ok to call API directly (like point-to-point / ajax / request promise) to validate this payload in order command-side service? But I think, the performance will get worse if the API called directly just for validation. Because, we have developed an event processor outside the command-service that listen from the event and apply the event to the materalized view.
Thank you.
As there are more than one bounded contexts that need to be queried for the validation to pass you need to consider eventual consistency. That being said, there is always a chance that the process as a whole can be in an invalid state for a "small" amount of time. For example, the user could be deactivated after the command is accepted and before the order is shipped. An online shop is a complex system and exceptions could appear in any of its subsystems. However, being implemented as an event-driven system helps; every time the ordering process enters an invalid state you can take compensatory actions/commands. For example, if the user is deactivated in the meantime you can cancel all its standing orders, release the reserved products, announce the potential customers that have those products in the wishlist that they are not available and so on.
There are many kinds of validation in DDD but I follow the general rule that the validation should be done as early as possible but without compromising data consistency. So, in order to be early you could query the readmodel to reject the commands that couldn't possible be valid and in order for the system to be consistent you need to make another check just before the order is shipped.
Now let's talk about your specific questions:
How to know that the customer is really exists in database (query-side customer service) and still active?
You can query the readmodel to verify that the user exists and it is still active. You should do this as a command that comes from an invalid user is a strong indication of some kind of attack and you don't want those kind of commands passing through your system. However, even if a command passes this check, it does not necessarily mean that the order will be shipped as other exceptions could be raised in between.
How to know that the product is exists in database and the status of the product is published?
Again, you can query the readmodel in order to notify the user that the product is not available at the moment. Or, depending on your business, you could allow the command to pass if you know that those products will be available in less than 24 hours based on some previous statistics (for example you know that TV sets arrive daily in your stock). Or you could let the customer choose whether it waits or not. In this case, if the products are not in stock at the final phase of the ordering (the shipping) you notify the customer that the products are not in stock anymore.
How to know whether the customer eligible to get the promo price from the related product?
You will probably have to query another bounded context like Promotions BC to check this. This depends on how promotions are validated/used.
Is it ok to call API directly (like point-to-point / ajax / request promise) to validate this payload in order command-side service? But I think, the performance will get worse if the API called directly just for validation.
This depends on how resilient you want your system to be and how fast you want to reject invalid commands.
Synchronous call are simpler to implement but they lead to a less resilient system (you should be aware of cascade failures and use technics like circuit breaker to stop them).
Asynchronous (i.e. using events) calls are harder to implement but make you system more resilient. In order to have async calls, the ordering system can subscribe to other systems for events and maintain a private state that can be queried for validation purposes as the commands arrive. In this way, the ordering system continues to work even of the link to inventory or customer management systems are down.
In any case, it really depends on your business and none of us can tell you exaclty what to do.
As always everything depends on the specifics of the domain but as a general principle cross domain validation should be done via the read model.
In this case, I would maintain a read model within each microservice for use in validation. Of course, that brings with it the question of eventual consistency.
How you handle that should come from your understanding of the domain. Factors such as the length of the eventual consistency compared to the frequency of updates should be considered. The cost of getting it wrong for the business compared to the cost of development to minimise the problem. In many cases, just recording the fact there has been a problem is more than adequate for the business.
I have a blog post dedicated to validation which you can find here: How To Validate Commands in a CQRS Application

Access and scheduling of FHIR Questionnaire resource

I am trying to understand how to use the FHIR Questionnaire resource, and have a specific question regarding this.
My project is specifically regarding how a citizen in our country could be responding to Questionnaires via a web app, which are then submitted to the FHIR server as QuestionnaireAnswers, to be read/analyzed by a health professional.
A FHIR-based system could have lots of Questionnaires (Qs), groups of Qs or even specific Qs would be targeted towards certain users or groups of users. The display of the questionnare to the citizen could also be based on a Care-plan of a sort, for example certain Questionnaires needing filling-in in the weeks after surgery. The Questionnaires could also be regular ones that need to be filled in every day or week permanently, to support data collection on the state of a chronic disease.
What I'm wondering is if FHIR has a resource which fits into organizing the 'logistics' of displaying the right form to the right person. I can see CarePlan, which seems to partly fit. Or is this something that would typically be handled out-of-FHIR-scope by specific server implementations?
So, to summarize:
Which resource or mechanism would a health professional use to set up that a patient should answer certain Questionnaires, either regularly or as part of for example a follow-up after a surgery. So this would include setting up the schedule for the form(s) to be filled in, and possibly configure what would happen if the form wasn't filled in as required.
Which resource (possibly the same) or mechanism would be used for the patient's web app to retrieve the relevant Questionnaire(s) at a given point in time?
At the moment, the best resource for saying "please capture data of type X on schedule Y" would be DiagnosticOrder, though the description probably doesn't make that clear. (If you'd be willing to click the "Propose a change" link and submit a change request for us to clarify, that'd be great.) If you wanted to order multiple questionnaires, then CarePlan would be a way to group that.
The process of taking a complex schedule (or set of schedules) and turning that into a simple list of "do this now" requests that might be more suitable for a mobile application to deal with is scheduled for DSTU 2.1. Until then, you have a few options for the mobile app:
- have it look at the CarePlan and complex DiagnosticOrder schedule and figure things out itself
- have a server generate a List of mini 1-time DiagnosticOrders and/or Orders identifying the specific "answer" times
- roll your own mechanism using the Other/Basic resource
Depending on your timelines, you might want to stay tuned to discussions by the Patient Care and Orders and Observations work groups as they start dealing with the issues around workflow management starting next month in Atlanta.

Recurring Profile and Bundled Item

I have a subscription service that people pay monthly for, so I’ve setup a “Virtual Product” with a Recurring Profile. At the same time, I want to have it so they can add different one time products. To accomplish this I’ve tried creating a “Bundled Product” with all the different one time products and adding the “Virtual Product” to that “Bundled Product”.
However, when I go to checkout it says “Nominal item can be purchased standalone only. To proceed please remove other items from the quote.” How do I allow people to subscribe to the service and purchase the products at the same time?
Note: I am using Paypal Website Payment Pro as my merchant account.
Here's the comment from Magento code:
/**
* Temporary workaround for purchase process: it is too dangerous to purchase more than one nominal item
* or a mixture of nominal and non-nominal items, although technically possible.
*
* The problem is that currently it is implemented as sequential submission of nominal items and order, by one click.
* It makes logically impossible to make the process of the purchase failsafe.
* Proper solution is to submit items one by one with customer confirmation each time.
*/
Actually you can remove the code below:
if ($item->isNominal() && $this->hasItems() || $this->hasNominalItems()) {
Mage::throwException(Mage::helper('sales')->__('Nominal item can be purchased standalone only. To proceed please remove other items from the quote.'));
}
Magento still handles multiple nominal products, however, you use that with your own risk.
Unfortunately this is a hardcoded restriction in the Mage_Paypal code.
You can see in Mage_Sales_Model_Service_Quote::submitAll() that it executes submitNominalItems() which contains:
$this->_validate();
$this->_submitRecurringPaymentProfiles();
$this->_inactivateQuote();
$this->_deleteNominalItems();
So, it kills the Cart after submitting nominal items. I'm not exactly sure why it does that, but I assume it's due to the way that subscriptions are created at Paypal.
Here is the code that prevents adding items to a cart that contains nominals in Mage_Sales_Model_Quote::addItem():
if ($item->isNominal() && $this->hasItems() || $this->hasNominalItems()) {
Mage::throwException(Mage::helper('sales')->__('Nominal item can be purchased standalone only. To proceed please remove other items from the quote.'));
}
I'm working on using Magento's Recurring Profiles for other payment providers at the moment (its a background task: Magento Recurring Profiles with non-Paypal payment method) and it is possible to checkout both nominal (aka subscription) and real products at the same time, but it does make it quite a bit more complex.
If this is a big deal, it should be possible to refactor the Mage_Paypal code to do this, but it's a complicated task that can't really be answered in a single post.

Resources