1

So what I am trying to do is have my eccomerce site handle both Paypal and Stripe payments. However, I am not sure how this is done.

This is what I have.

class BillingProvider extends ServiceProvider
{
    /**
     * Bootstrap the application services.
     *
     * @return void
     */
    public function boot()
    {
        //
    }

    /**
     * Register the application services.
     *
     * @return void
     */
    public function register()
    {
        $this->app->bind('App\Contracts\BillingInterface','App\Services\Billing\PaypalBilling');
    }
}

This works fine if I only need Paypal. However, I need both Paypal and Stripe.

Any idea how we can go about implementing this? So when we typehint this we can either get paypal or stripe.

public function stripe(Request $request, BillingInterface $bill){// Handle stripe payment.}

public function paypal(Request $request, BillingInterface $bill){// Handle paypal payment.}
Nello
  • 1,737
  • 3
  • 17
  • 24
  • 1
    If the stripe() and paypal() methods are in the same class and you're trying to inject a different dependency object depending on the `BillingInterface`, you can just use `$this->app->make('PayPalClass')` inside the method and not use the DI. – thefallen May 25 '16 at 08:44
  • Don't use the Container resolution, instantiate and pass the instance manually. – naneri May 25 '16 at 08:44
  • Some links to look at: http://stackoverflow.com/questions/31887870/laravel-service-provider-bind-multiple-classes https://laracasts.com/discuss/channels/general-discussion/multiple-services-implementing-same-interface-switching-at-runtime – haakym May 25 '16 at 08:44

1 Answers1

1

Imho, there are many ways to do it.

First of all, take a look to the contextual binding of the Service Container. If you're using different classes on your checkout procedure, you can set a resolve strategy based on who is actually using the contract.

However, I would probably choose something different.

Let's apply the strategy design pattern for this.

Basically, in two separate steps:

  • create a "top" class named, for example, BillingManager;
  • a class for each payment type (imho, make a paypal() and a stripe() method in a single class is wrong because of this) that implement your billing interface. Let's say that this interface has a 'process($orderId)` method;

Now, the BillingManager class will be called. Probably, you will call a general method pay that will take, as a parameter, something to understand what strategy it will use.

Something like

public function pay($strategy, $orderId) {
    // use $strategy to understand which service must be used.
    // very raw example:

    $strategy = app()->make($strategy . 'Strategy');
    $strategy->process($orderId);
}

Of course, you will need a safe mechanism to understand what service you will need to use. After that, you will be able to use the BillingManager class every time, with many different payment systems, without worry about anything else.