You want to charge or refund for user when User is doing order via ZaloPay or MomoPay. However, if you inject Concrete ZaloPay/MomoPay class into Controller so you can't change from ZaloPay <> MomoPay.
At here, You're only injecting PaymentGateway interface and mapping that interface with MomoPay or ZaloPay via AppServiceProvider.php when you want to use Concrete class. They're ZaloPay or MomoPay.
The way design is called Contract (Hợp Đồng) in Laravel above.
You only need to implement PaymentGateway interface (contract) at Concrete class that are MomoPay/ZaloPay.....
<?php namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Contracts\PaymentGateway;
class PaymentController extends Controller
{
protected $paymentGateway;
public function __construct(PaymentGateway $paymentGateway)
{
$this->paymentGateway = $paymentGateway;
}
public function charge()
{
if ($charged = $this->paymentGateway->charge(100000))
var_dump($charged);
return false;
}
public function refund()
{
if ($refunded = $this->paymentGateway
->refund('transaction123'))
var_dump($refunded);
return false;
}
}
<?php namespace App\Contracts;
interface PaymentGateway
{
public function charge($amount);
public function refund($transactionId);
}
<?php namespace App\Services;
use App\Contracts\PaymentGateway;
class MomoPaymentGateway implements PaymentGateway
{
public function charge($amount)
{
return (object) [
'provider' => 'Momo',
'service' => 'charge',
'amount' => number_format($amount + 1000) . ' vnd',
'fee' => '1.000 vnd',
'message' => 'Success'
];
}
public function refund($transactionId)
{
return (object) [
'provider' => 'Momo',
'service' => 'charge',
'amount' => '99.000 vnd',
'fee' => '1.000 vnd',
'message' => 'Success'
];
}
}
<?php namespace App\Services;
use App\Contracts\PaymentGateway;
class ZaloPaymentGateway implements PaymentGateway
{
public function charge($amount)
{
return (object) [
'provider' => 'Zalo',
'service' => 'charge',
'amount' => number_format($amount) . ' vnd',
'fee' => '0 vnd',
'message' => 'Success'
];
}
public function refund($transactionId)
{
return (object) [
'provider' => 'Zalo',
'service' => 'charge',
'amount' => '100.000 vnd',
'fee' => '0 vnd',
'message' => 'Success'
];
}
}
<?php namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\Contracts\PaymentGateway;
use App\Services\ZaloPaymentGateway;
use App\Services\MomoPaymentGateway;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* @return void
*/
public function register()
{
$this->app->bind(PaymentGateway::class, function ($app) {
// Return the desired payment gateway implementation here.
// Example: return new MomoPaymentGateway();
return new ZaloPaymentGateway();
});
}
public function boot() {}
}