Skip to content

Commit bf21195

Browse files
fix: lazy-load payment method to prevent checkout page crash in MFTF tests
ConfigProvider constructor eagerly called getMethodInstance() which crashed the entire checkout page if it threw. Now deferred to getConfig() with try-catch so the checkout page always renders. Same lazy-load pattern applied to PaystackApiClient and AbstractPaystackStandard. Replaced concrete Store model with StoreManagerInterface.
1 parent 78f04a7 commit bf21195

6 files changed

Lines changed: 111 additions & 54 deletions

File tree

Controller/Payment/AbstractPaystackStandard.php

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
namespace Pstk\Paystack\Controller\Payment;
2424

2525
use Magento\Payment\Helper\Data as PaymentHelper;
26+
use Magento\Store\Model\StoreManagerInterface;
2627
use Pstk\Paystack\Gateway\PaystackApiClient;
2728

2829

@@ -42,6 +43,7 @@ abstract class AbstractPaystackStandard extends \Magento\Framework\App\Action\Ac
4243
*/
4344
protected $orderInterface;
4445
protected $checkoutSession;
46+
protected $paymentHelper;
4547
protected $method;
4648
protected $messageManager;
4749

@@ -51,6 +53,12 @@ abstract class AbstractPaystackStandard extends \Magento\Framework\App\Action\Ac
5153
*/
5254
protected $configProvider;
5355

56+
/**
57+
*
58+
* @var StoreManagerInterface
59+
*/
60+
protected $storeManager;
61+
5462
/**
5563
*
5664
* @var PaystackApiClient
@@ -89,6 +97,7 @@ public function __construct(
8997
PaymentHelper $paymentHelper,
9098
\Magento\Framework\Message\ManagerInterface $messageManager,
9199
\Pstk\Paystack\Model\Ui\ConfigProvider $configProvider,
100+
StoreManagerInterface $storeManager,
92101
\Magento\Framework\Event\Manager $eventManager,
93102
\Magento\Framework\App\Request\Http $request,
94103
\Psr\Log\LoggerInterface $logger,
@@ -98,16 +107,28 @@ public function __construct(
98107
$this->orderRepository = $orderRepository;
99108
$this->orderInterface = $orderInterface;
100109
$this->checkoutSession = $checkoutSession;
101-
$this->method = $paymentHelper->getMethodInstance(\Pstk\Paystack\Model\Payment\Paystack::CODE);
110+
$this->paymentHelper = $paymentHelper;
102111
$this->messageManager = $messageManager;
103112
$this->configProvider = $configProvider;
113+
$this->storeManager = $storeManager;
104114
$this->eventManager = $eventManager;
105115
$this->request = $request;
106116
$this->logger = $logger;
107117
$this->paystackClient = $paystackClient;
108118

109119
parent::__construct($context);
110120
}
121+
122+
/**
123+
* @return \Magento\Payment\Model\MethodInterface
124+
*/
125+
protected function getMethod()
126+
{
127+
if ($this->method === null) {
128+
$this->method = $this->paymentHelper->getMethodInstance(\Pstk\Paystack\Model\Payment\Paystack::CODE);
129+
}
130+
return $this->method;
131+
}
111132

112133
protected function redirectToFinal($successFul = true, $message="") {
113134
if($successFul){

Controller/Payment/Setup.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public function execute() {
3333

3434
$message = '';
3535
$order = $this->orderInterface->loadByIncrementId($this->checkoutSession->getLastRealOrder()->getIncrementId());
36-
if ($order && $this->method->getCode() == $order->getPayment()->getMethod()) {
36+
if ($order && $this->getMethod()->getCode() == $order->getPayment()->getMethod()) {
3737

3838
try {
3939
return $this->processAuthorization($order);
@@ -55,7 +55,7 @@ protected function processAuthorization(\Magento\Sales\Model\Order $order) {
5555
'email' => $order->getCustomerEmail(), // unique to customers
5656
'reference' => $order->getIncrementId(), // unique to transactions
5757
'currency' => $order->getCurrency(),
58-
'callback_url' => $this->configProvider->getStore()->getBaseUrl() . "paystack/payment/callback",
58+
'callback_url' => $this->storeManager->getStore()->getBaseUrl() . "paystack/payment/callback",
5959
'metadata' => array('custom_fields' => array(
6060
array(
6161
"display_name"=>"Plugin",

Gateway/PaystackApiClient.php

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,31 @@ class PaystackApiClient
1010
{
1111
private const BASE_URL = 'https://api.paystack.co';
1212

13-
/** @var string */
13+
/** @var PaymentHelper */
14+
private $paymentHelper;
15+
16+
/** @var string|null */
1417
private $secretKey;
1518

1619
public function __construct(PaymentHelper $paymentHelper)
1720
{
18-
$method = $paymentHelper->getMethodInstance(PaystackModel::CODE);
19-
$this->secretKey = $method->getConfigData('live_secret_key');
20-
if ($method->getConfigData('test_mode')) {
21-
$this->secretKey = $method->getConfigData('test_secret_key');
21+
$this->paymentHelper = $paymentHelper;
22+
}
23+
24+
/**
25+
* @return string
26+
*/
27+
private function getSecretKey(): string
28+
{
29+
if ($this->secretKey === null) {
30+
$method = $this->paymentHelper->getMethodInstance(PaystackModel::CODE);
31+
$this->secretKey = $method->getConfigData('live_secret_key');
32+
if ($method->getConfigData('test_mode')) {
33+
$this->secretKey = $method->getConfigData('test_secret_key');
34+
}
35+
$this->secretKey = (string) $this->secretKey;
2236
}
37+
return $this->secretKey;
2338
}
2439

2540
/**
@@ -55,7 +70,7 @@ public function verifyTransaction(string $reference): object
5570
*/
5671
public function validateWebhookSignature(string $rawBody, string $signature): bool
5772
{
58-
$computed = hash_hmac('sha512', $rawBody, $this->secretKey);
73+
$computed = hash_hmac('sha512', $rawBody, $this->getSecretKey());
5974
return hash_equals($computed, $signature);
6075
}
6176

@@ -104,7 +119,7 @@ private function request(string $method, string $endpoint, ?array $data = null):
104119
CURLOPT_URL => $url,
105120
CURLOPT_RETURNTRANSFER => true,
106121
CURLOPT_HTTPHEADER => [
107-
'Authorization: Bearer ' . $this->secretKey,
122+
'Authorization: Bearer ' . $this->getSecretKey(),
108123
'Content-Type: application/json',
109124
],
110125
CURLOPT_TIMEOUT => 30,

Model/Ui/ConfigProvider.php

Lines changed: 63 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,36 @@
33

44
use Magento\Checkout\Model\ConfigProviderInterface;
55
use Magento\Payment\Helper\Data as PaymentHelper;
6-
use Magento\Store\Model\Store as Store;
6+
use Magento\Store\Model\StoreManagerInterface;
7+
use Psr\Log\LoggerInterface;
78

8-
/**
9-
* Class ConfigProvider
10-
*/
119
class ConfigProvider implements ConfigProviderInterface
1210
{
1311

14-
protected $method;
15-
protected $store;
12+
protected $paymentHelper;
13+
protected $storeManager;
14+
protected $logger;
15+
private $method;
1616

17-
public function __construct(PaymentHelper $paymentHelper, Store $store)
17+
public function __construct(
18+
PaymentHelper $paymentHelper,
19+
StoreManagerInterface $storeManager,
20+
LoggerInterface $logger
21+
) {
22+
$this->paymentHelper = $paymentHelper;
23+
$this->storeManager = $storeManager;
24+
$this->logger = $logger;
25+
}
26+
27+
/**
28+
* @return \Magento\Payment\Model\MethodInterface
29+
*/
30+
private function getMethod()
1831
{
19-
$this->method = $paymentHelper->getMethodInstance(\Pstk\Paystack\Model\Payment\Paystack::CODE);
20-
$this->store = $store;
32+
if ($this->method === null) {
33+
$this->method = $this->paymentHelper->getMethodInstance(\Pstk\Paystack\Model\Payment\Paystack::CODE);
34+
}
35+
return $this->method;
2136
}
2237

2338
/**
@@ -27,51 +42,57 @@ public function __construct(PaymentHelper $paymentHelper, Store $store)
2742
*/
2843
public function getConfig()
2944
{
30-
$publicKey = $this->method->getConfigData('live_public_key');
31-
if ($this->method->getConfigData('test_mode')) {
32-
$publicKey = $this->method->getConfigData('test_public_key');
33-
}
34-
35-
$integrationType = $this->method->getConfigData('integration_type')?: 'inline';
45+
try {
46+
$method = $this->getMethod();
47+
48+
$publicKey = $method->getConfigData('live_public_key');
49+
if ($method->getConfigData('test_mode')) {
50+
$publicKey = $method->getConfigData('test_public_key');
51+
}
52+
53+
$integrationType = $method->getConfigData('integration_type') ?: 'inline';
54+
$baseUrl = $this->storeManager->getStore()->getBaseUrl();
3655

37-
return [
38-
'payment' => [
39-
\Pstk\Paystack\Model\Payment\Paystack::CODE => [
40-
'public_key' => $publicKey,
41-
'integration_type' => $integrationType,
42-
'api_url' => $this->store->getBaseUrl() . 'rest/',
43-
'integration_type_standard_url' => $this->store->getBaseUrl() . 'paystack/payment/setup',
44-
'recreate_quote_url' => $this->store->getBaseUrl() . 'paystack/payment/recreate',
56+
return [
57+
'payment' => [
58+
\Pstk\Paystack\Model\Payment\Paystack::CODE => [
59+
'public_key' => $publicKey,
60+
'integration_type' => $integrationType,
61+
'api_url' => $baseUrl . 'rest/',
62+
'integration_type_standard_url' => $baseUrl . 'paystack/payment/setup',
63+
'recreate_quote_url' => $baseUrl . 'paystack/payment/recreate',
64+
]
4565
]
46-
]
47-
];
48-
}
49-
50-
public function getStore() {
51-
return $this->store;
66+
];
67+
} catch (\Exception $e) {
68+
$this->logger->error('Paystack ConfigProvider: ' . $e->getMessage());
69+
return [];
70+
}
5271
}
53-
72+
5473
/**
5574
* Get secret key for webhook process
56-
*
75+
*
5776
* @return array
5877
*/
59-
public function getSecretKeyArray(){
60-
$data = ["live" => $this->method->getConfigData('live_secret_key')];
61-
if ($this->method->getConfigData('test_mode')) {
62-
$data = ["test" => $this->method->getConfigData('test_secret_key')];
78+
public function getSecretKeyArray()
79+
{
80+
$method = $this->getMethod();
81+
$data = ["live" => $method->getConfigData('live_secret_key')];
82+
if ($method->getConfigData('test_mode')) {
83+
$data = ["test" => $method->getConfigData('test_secret_key')];
6384
}
64-
85+
6586
return $data;
6687
}
6788

68-
public function getPublicKey(){
69-
$publicKey = $this->method->getConfigData('live_public_key');
70-
if ($this->method->getConfigData('test_mode')) {
71-
$publicKey = $this->method->getConfigData('test_public_key');
89+
public function getPublicKey()
90+
{
91+
$method = $this->getMethod();
92+
$publicKey = $method->getConfigData('live_public_key');
93+
if ($method->getConfigData('test_mode')) {
94+
$publicKey = $method->getConfigData('test_public_key');
7295
}
7396
return $publicKey;
7497
}
75-
76-
7798
}

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "pstk/paystack-magento2-module",
33
"description": "Paystack Magento2 Module using \\Magento\\Payment\\Model\\Method\\AbstractMethod",
4-
"version": "3.0.5",
4+
"version": "3.0.6",
55
"require": {},
66
"type": "magento2-module",
77
"license": [

etc/module.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0"?>
22
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
3-
<module name="Pstk_Paystack" setup_version="3.0.5">
3+
<module name="Pstk_Paystack" setup_version="3.0.6">
44
<sequence>
55
<module name="Magento_Sales"/>
66
<module name="Magento_Payment"/>

0 commit comments

Comments
 (0)