The strategy pattern is applied in the code below in the payment separation solution. Please evaluate if it is well done according to standards. I would be very grateful for suggestions.
<?php
interface PaymentMethod
{
public function processPayment(Module $module, $order_id, array $client);
public function paymentRepository(Repository $repository);
}
class Module {
public $currentOrder = 1;
}
class Repository {}
class PaymentA implements PaymentMethod
{
private $name = 'payment_a';
private $clientData;
private $repository;
public function getName() {
return $this->name;
}
public function paymentRepository(Repository $repository) {
$this->repository = $repository;
}
public function processPayment(
Module $module,
$order_id,
array $client
)
{
$this->clientData = $client;
return $this->responsePayment();
}
public function responsePayment() {
return (array) [
'status' => 'success',
'order_id' => 123
];
}
}
class PaymentB implements PaymentMethod
{
private $name = 'payment_b';
private $clientData;
public function getName() {
return $this->name;
}
public function paymentRepository(Repository $repository) {
$this->repository = $repository;
}
public function processPayment(
Module $module,
$order_id,
array $client
)
{
$this->clientData = $client;
$gateway = 2;
return $this->responsePayment();
}
public function responsePayment() {
return (array) [
'status' => 'failed',
'order_id' => 123
];
}
}
class OrderClient
{
public function getClient($cart, $type)
:array
{
$data = [
'amount' => 100,
'name' => 'Imie',
'cart' => $cart,
'type' => $type,
];
return $data;
}
}
class PaymentFactory
{
public static function getPaymentMethod(string $type)
:PaymentMethod
{
switch ($type) {
case "payment_a":
return new PaymentA();
case "payment_b":
return new PaymentB();
default:
throw new \Exception("Wrong");
}
}
}
class PaymentController
{
private $module;
private $repository;
private $order_client;
private $payment_method;
private $data;
public function __construct(
Module $module,
OrderClient $order_client,
Repository $repository,
array $data = []
) {
$this->module = $module;
$this->repository = $repository;
$this->order_client = $order_client;
$this->data = $data;
}
public function setMethods($payment_method)
{
$this->payment_method = $payment_method;
$this->paymentRepository();
$this->getPayment();
}
public function paymentRepository() {
$this->payment_method->paymentRepository($this->repository);
}
public function getPayment()
{
$result = $this->payment_method->processPayment(
$this->module,
$this->module->currentOrder,
$this->order_client->getClient(
'cart',
$this->payment_method->getName()
)
);
var_dump($result);
if($result['status'] === 'success') {
$this->setCompleteOrder($result);
}
}
public function setCompleteOrder($result) {
/// send sql complete order
$this->setRedirectOrder($result['order_id']);
}
public function setRedirectOrder($order_id) {
/// redirect
return var_dump('redirect ' . $order_id);
}
}
/// Init
$data = [
'payment_type' => 'payment_a',
'payment_gateway' => 10
];
$module = new Module();
$client = new OrderClient();
$repository = new Repository();
$payment_class = PaymentFactory::getPaymentMethod($data['payment_type']);
$controller = new PaymentController(
$module,
$client,
$repository,
$data
);
$controller->setMethods(
$payment_class
);
var_dump($controller);