Open RobertBoes opened 4 years ago
Just to understand, can you give me a use case for using a preprocessor on the first payment?
We have a few base plans, like regular and pro for example. But we also have some more dynamic "add-ons" for those plans. For example a user has a regular plan which includes x items, but they can purchase additional items for that plan (also monthly billed). In the code sample above you can see I'm adding 2 OrderItems to the plan. So an invoice would look like this:
Description | Units | Unit price | Total |
---|---|---|---|
Regular subscription | 1 | € 10.00 | € 10.00 |
Extra items | 2 | € 2.50 | € 5.00 |
Another option would be to add a separate subscription for the add-ons, but that can cause the subscriptions to easily go out of sync. For example when the user decides to buy the add-ons a few days after they have purchased the main subscription.
Thanks for clearing that up. I understand the requirement now :).
Seems like we're looking for a way to have different behaviour between a) first payment preprocessing and b) mandated payment preprocessing.
I'm not sure about using a flag (boolean) on the preprocessor. What if the preprocessor's default handle method has external effects other than modifying the OrderItemCollection (like with coupons)?
I feel there may be a need for a dedicated handleFirstPayment
method on the preprocessor to cater for this.
But this would result in a BC.
How about adding a dedicated handleFirstPayment
method to the preprocessors for handling firstPayments, which only gets called if the method_exists
?
Thinking out loud here, not entirely convinced yet.
Seems like we're looking for a way to have different behaviour between a) first payment preprocessing and b) mandated payment preprocessing.
And c) optionally have the same behavior.
The difficulty with this is finding a solution that keeps the package modular so it can suit as many use cases as possible.
In the case of offering addons through preprocessors, the first charge is basically the same as any recurring charge.
I think the most powerful option is when a preprocessor or coupon can decide if it should be applied on all charges, or only on the first charge, or only on recurring charges.
I have a very limited understanding of how the preprocessors and coupons work internally, but would it be an option to use Concerns for this? Let a Coupon(handler) or preprocessor determine if it should be added on the first payment by using a concern, like ShouldBeAppliedOnFirstPayment
, similar to how Laravel Excel uses Concerns (https://docs.laravel-excel.com/3.1/architecture/concerns.html)
I don't have a good view on all the different use cases, and how a Concern structure effects all of them, though.
The charges may be the same on both the first payment Order and subsequent mandated Orders, but the business logic does not have to be. I.e. on a mandated payment you may want to reset a monthly bandwidth counter. Basically you don't want to persist anything on the first payment.
That's why I'm rooting for separating the handle()
and the handleFirstPayment()
methods.
Concerns/traits are a great way for adding modular behavior, but I'd go for capturing the logic first, then figure out if Concerns are a viable way to go here.
@RobertBoes what do you think?
I think more use-cases should be figured out, since I would assume the preprocessors would always be called, even on the first payment. But that's also where it gets complicated, since the first payment requires a different flow.
I don't have a complete overview how the first payment differs from a mandated payment, so it's quite difficult for me to know what exactly needs to be handled differently. For example the coupon and persist order, seems to me it should be handled the same on first and mandated payment. Storing the order on first payment makes sense, as you could list those orders in your application and show the user the order was cancelled. But there's probably a very good reason why the first payment does this differently and doesn't use the preprocessors right now.
There are essentially three scenario's in which the preprocessors should be used:
I agree that in 99% (perhaps even 100%) of the cases the preprocessors should fire on both first payments and mandated payments, but there's an important distinction between scenario 1 and 2 in my previous message we should cater for.
Perhaps simply having a prepareFirstPayment
method pointing to the default handle method is enough. And override it where necessary.
Any update on this, will this be attributed in v2? We have the same use case. Base subscription of x users per month, plus an add-on for using an integration for a fixed price per month. I would like to keep the same billing cycle for both, so using two separate subscriptions would break that.
Maybe the one-off payment function can be used for this too, to add the on-off payment every month before processing payment.
We have the same issue here :(
We don't directly address this issue in v2.
But we do introduce the option of setting the payment mandate using a one-off charge. This way you can have a minimal first payment (add it to the customer's balance even) to obtain the mandate, and then start billing using mandated payments - and the preprocessors. I think that covers your use case.
I have also been seeing big companies like Stadia ask for a minimal payment amount for the mandate, start the free trial, and then refund that amount.
Note that there's a small fee for refunding transactions, so refunding may not be your cup of tea depending on your trial-to-paid conversion rate.
While I think that covers your use cases, I will keep this issue on the radar to see if we can further improve the customer and developer experiences later on (v3?).
@sandervanhooft Thanks for your response and really appreciate your work. Is there a way we can get access to cashier-mollie v2? I saw that is a closed repo and not available the for public yet. We are implementing mollie integration for a Laravel application that we need to go live at end of this year. We can save time upgrading to v2 if you can give us access to the closed repo if possible.
Preprocessors are currently not applied to the first payment. What I'm trying to do is adding extra items to the subscription, as a very basic test I've created the following preprocessor:
This does add two items to subsequent payments, but not to the first payment.
After reading through the code, I'm want to try to create a PR, but I'm not sure if I'm on the right track. It seems like the coupons and
PersistOrderItems
are handled differently on the first payment, basically they're added "manually".My idea is to add a property to
ProcessCoupons
andPersistOrderItems
to indicate that those two preprocessors should not be handled on the first payment. Then in the create method of theFirstPaymentSubscriptionBuilder
I can fetch all the preprocessors, filter out those which shouldn't be applied and then add them to the $actions array.Now my question is, would this work and would this be the correct way to handle preprocessors on the first payment?