Reputation: 1733
I'm trying to come up with a generic way to add multiple implementations of payment providers in a system that only uses one for now.
I'd like to have a Company
object linked to a Subscription
. A Subscription
has multiple Invoice
objects connected to it. A Subscription
can only have one PaymentProviderInterface
linked to it but we have to option to replace the payment provider for the subscription. The PaymentProviderInterface
linked to the Subscription is build by a Factory.
The problem is that for different PaymentProviderInterface
implementations the logic to get the user to be notified might be different. For a special PaymentProviderInterface
an email must me send to our system instead of the actual end user. For Stripe the email should be send to the user connected to the Stripe account. For another service the user is stored in the Company object.
Is there a way to implement this without the PaymentProvider
object having to actually know about the Subscription
it's linked to?
The same thing for the BillingAddress
. The way we retrieve the billing address to put on the Invoice object is different per payment provider. If it's Stripe, it's the billing address stored on Stripe. If it's another one, the BillingAddress
is stored in our database.
Upvotes: 1
Views: 2428
Reputation: 6940
I guess that the concept of Observer design pattern is one of the possible solutions that you're after for. Since it main purpose is to ensure a way of notifying change to a number of classes. It defines a dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.
You can consider following implementation:
Subject (Subscription) knows its observers. Any number of Observer objects may observe a subject provides an interface for attaching and detaching Observer objects.
ConcreteSubject (ConcreteSubscription) stores state of interest to ConcreteObserver sends a notification to its observers when its state changes
Observer (IPaymentProvider) defines an updating interface for objects that should be notified of changes in a subject.
ConcreteObserver (PaymentProvider) maintains a reference to a ConcreteSubject object stores state that should stay consistent with the subject's implements the Observer updating interface to keep its state consistent with the subject's
Upvotes: 1
Reputation: 1948
You should be able to define custom arguments passed to the payment provider as parameters of the query and returned to your server "as it" after a payment attempt (wheter it is a successfull or failed attempt doesn't impact the presence of these custom args). When your Factory
elect the right PaymentProviderInterface
for the Subscription
, it can then select the User using the logic you want and pass it as parameter to the PaymentProvider
(as a string), then the server can know who to notify based on what's returned by the PaymentProvider
by parsing the content of this custom arguments field. Custom Arguments in PaymentProviders are usualy used for this kind of purpose.
Does this makes sense ?
Upvotes: 1