Simon
Simon

Reputation: 1733

Design Pattern for Multiple Payment Providers and notifying different users based on the implementation

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

Answers (2)

ekostadinov
ekostadinov

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

Sébastien
Sébastien

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

Related Questions