Skip to content

Commit eb74bba

Browse files
Merge pull request #8 from tolu-paystack/master
adds webhook support
2 parents 4067d9d + 784ffaf commit eb74bba

File tree

4 files changed

+84
-19
lines changed

4 files changed

+84
-19
lines changed

admin/controller/extension/payment/paystack.php

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,12 @@ public function index()
1616

1717
$this->session->data['success'] = $this->language->get('text_success');
1818

19-
$this->response->redirect($this->url->link('marketplace/extension', 'user_token=' . $this->session->data['user_token']. '&type=payment', true));
19+
$this->response->redirect($this->url->link('marketplace/extension', 'user_token=' . $this->session->data['user_token'] . '&type=payment', true));
2020
}
2121

22+
// Set webhook url
23+
$data['webhook_url'] = HTTPS_CATALOG . 'index.php?route=extension/payment/paystack/callback';
24+
2225
if (isset($this->error['warning'])) {
2326
$data['error_warning'] = $this->error['warning'];
2427
} else {
@@ -32,18 +35,18 @@ public function index()
3235
}
3336

3437
$data['breadcrumbs'][] = array(
35-
'text' => $this->language->get('text_home'),
36-
'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token'], true)
38+
'text' => $this->language->get('text_home'),
39+
'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token'], true)
3740
);
3841

3942
$data['breadcrumbs'][] = array(
40-
'text' => $this->language->get('text_payment'),
41-
'href' => $this->url->link('marketplace/extension', 'user_token=' . $this->session->data['user_token'].'&type=payment', true)
43+
'text' => $this->language->get('text_payment'),
44+
'href' => $this->url->link('marketplace/extension', 'user_token=' . $this->session->data['user_token'] . '&type=payment', true)
4245
);
4346

4447
$data['breadcrumbs'][] = array(
45-
'text' => $this->language->get('heading_title'),
46-
'href' => $this->url->link('extension/payment/paystack', 'user_token=' . $this->session->data['user_token'], true)
48+
'text' => $this->language->get('heading_title'),
49+
'href' => $this->url->link('extension/payment/paystack', 'user_token=' . $this->session->data['user_token'], true)
4750
);
4851

4952
$data['action'] = $this->url->link('extension/payment/paystack', 'user_token=' . $this->session->data['user_token'], true);
@@ -55,25 +58,25 @@ public function index()
5558
} else {
5659
$data['payment_paystack_live_secret'] = $this->config->get('payment_paystack_live_secret');
5760
}
58-
61+
5962
if (isset($this->request->post['payment_paystack_live_public'])) {
6063
$data['payment_paystack_live_public'] = $this->request->post['payment_paystack_live_public'];
6164
} else {
6265
$data['payment_paystack_live_public'] = $this->config->get('payment_paystack_live_public');
6366
}
64-
67+
6568
if (isset($this->request->post['payment_paystack_test_secret'])) {
6669
$data['payment_paystack_test_secret'] = $this->request->post['payment_paystack_test_secret'];
6770
} else {
6871
$data['payment_paystack_test_secret'] = $this->config->get('payment_paystack_test_secret');
6972
}
70-
73+
7174
if (isset($this->request->post['payment_paystack_test_public'])) {
7275
$data['payment_paystack_test_public'] = $this->request->post['payment_paystack_test_public'];
7376
} else {
7477
$data['payment_paystack_test_public'] = $this->config->get('payment_paystack_test_public');
7578
}
76-
79+
7780
if (isset($this->request->post['payment_paystack_live'])) {
7881
$data['payment_paystack_live'] = $this->request->post['payment_paystack_live'];
7982
} else {
@@ -148,10 +151,10 @@ public function index()
148151

149152
$this->response->setOutput($this->load->view('extension/payment/paystack', $data));
150153
}
151-
154+
152155
private function valid_key($value, $mode, $access)
153156
{
154-
return (substr_compare($value, (substr($access, 0, 1)).'k_'.$mode.'_', 0, 8, true)===0);
157+
return (substr_compare($value, (substr($access, 0, 1)) . 'k_' . $mode . '_', 0, 8, true) === 0);
155158
}
156159

157160
private function validate()
@@ -163,7 +166,7 @@ private function validate()
163166
$live_public = $this->request->post['payment_paystack_live_public'];
164167
$test_secret = $this->request->post['payment_paystack_test_secret'];
165168
$test_public = $this->request->post['payment_paystack_test_public'];
166-
169+
167170
if ($this->request->post['payment_paystack_live'] && (!$this->valid_key($live_secret, 'live', 'secret') || !$this->valid_key($live_public, 'live', 'public'))) {
168171
$this->error['keys'] = $this->language->get('error_live_keys');
169172
}

admin/language/en-gb/extension/payment/paystack.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
$_['text_paystack'] = '<a target="_BLANK" href="http://www.paystack.com"><img src="view/image/payment/paystack.png" alt="Paystack" title="Paystack" style="border: 1px solid #cccccc;" /></a>';
1010
$_['text_pay'] = 'Pay';
1111
$_['text_disable_payment'] = 'Disable Payment Method';
12+
$_['text_set_webhook'] = 'Optional: To avoid situations where bad network makes it impossible to verify transactions, set your webhook URL on your <a href="https://dashboard.paystack.co/#/settings/developer">Paystack Dashboard</a> to the URL below';
1213

1314
// Entry
1415
$_['entry_live_secret'] = 'Live Secret Key:';
@@ -19,9 +20,9 @@
1920
$_['entry_live'] = 'Live Mode';
2021
$_['entry_debug'] = 'Debug Mode';
2122
$_['entry_total'] = 'Total';
22-
$_['entry_order_status'] = 'Order Status';
23-
$_['entry_pending_status'] = 'Pending Status ';
24-
$_['entry_canceled_status'] = 'Canceled Status';
23+
$_['entry_order_status'] = 'Order Status';
24+
$_['entry_pending_status'] = 'Pending Status ';
25+
$_['entry_canceled_status'] = 'Canceled Status';
2526
$_['entry_failed_status'] = 'Failed Status';
2627
$_['entry_geo_zone'] = 'Geo Zone';
2728
$_['entry_status'] = 'Status';

admin/view/template/extension/payment/paystack.twig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
</h3>
3131
</div>
3232
<div class="panel-body">
33+
<p>{{text_set_webhook}}</p>
34+
<p style="color:red;"><strong>{{webhook_url}}</strong></p>
3335
<form action="{{ action }}" method="post" enctype="multipart/form-data" id="form-pp-std-uk" class="form-horizontal">
3436
<ul class="nav nav-tabs">
3537
<li class="active"><a href="#tab-general" data-toggle="tab">{{ tab_general }}

catalog/controller/extension/payment/paystack.php

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,7 @@ public function index()
6464

6565
$data['currency'] = $order_info['currency_code'];
6666
$data['ref'] = uniqid('' . $this->session->data['order_id'] . '-');
67-
//$data['amount'] = intval($order_info['total'] * 100);
68-
$data['amount'] = intval($this->currency->format($order_info['total']*100, $order_info['currency_code'], $order_info['currency_value'], false));
67+
$data['amount'] = intval($this->currency->format($order_info['total'] * 100, $order_info['currency_code'], $order_info['currency_value'], false));
6968
$data['email'] = $order_info['email'];
7069
$data['callback'] = $this->url->link('extension/payment/paystack/callback', 'trxref=' . rawurlencode($data['ref']), 'SSL');
7170

@@ -154,6 +153,66 @@ public function callback()
154153
$this->model_checkout_order->addOrderHistory($order_id, $order_status_id);
155154
$this->redir_and_die($redir_url);
156155
}
156+
} else if ((strtoupper($_SERVER['REQUEST_METHOD']) == 'POST') && array_key_exists('x-paystack-signature', $_SERVER)) { // WEBHOOK CODE
157+
158+
// Retrieve the request's body
159+
$input = @file_get_contents("php://input");
160+
161+
if ($this->config->get('payment_paystack_live')) {
162+
$secret_key = $this->config->get('payment_paystack_live_secret');
163+
} else {
164+
$secret_key = $this->config->get('payment_paystack_test_secret');
165+
}
166+
167+
// validate event do all at once to avoid timing attack
168+
if ($_SERVER['HTTP_X_PAYSTACK_SIGNATURE'] !== hash_hmac('sha512', $input, $secret_key))
169+
exit();
170+
171+
http_response_code(200);
172+
173+
// parse event (which is json string) as object
174+
// Do something - that will not take long - with $event
175+
$event = json_decode($input);
176+
177+
if ($event['event'] == 'charge.success') {
178+
179+
$trxref = $event['data']['reference'];
180+
181+
// order id is what comes before the first dash in trxref
182+
$order_id = substr($trxref, 0, strpos($trxref, '-'));
183+
// if no dash were in transation reference, we will have an empty order_id
184+
if (!$order_id) {
185+
$order_id = 0;
186+
}
187+
188+
$this->load->model('checkout/order');
189+
190+
$order_info = $this->model_checkout_order->getOrder($order_id);
191+
192+
$order_status_id = $this->config->get('config_order_status_id');
193+
194+
if (array_key_exists('data', $event) && array_key_exists('status', $event['data']) && ($event['data']['status'] === 'success')) {
195+
//PSTK Logger
196+
if ($this->config->get('payment_paystack_live')) {
197+
$pk = $this->config->get('payment_paystack_live_public');
198+
} else {
199+
$pk = $this->config->get('payment_paystack_test_public');
200+
}
201+
202+
$pstk_logger = new open_cart_paystack_plugin_tracker('opencart-3.x', $pk);
203+
$pstk_logger->log_transaction_success($trxref);
204+
205+
//----------------------
206+
$order_status_id = $this->config->get('payment_paystack_order_status_id');
207+
} elseif (array_key_exists('data', $event) && array_key_exists('status', $event['data']) && ($event['data']['status'] === 'failed')) {
208+
$order_status_id = $this->config->get('payment_paystack_declined_status_id');
209+
} else {
210+
$order_status_id = $this->config->get('payment_paystack_canceled_status_id');
211+
}
212+
213+
$this->model_checkout_order->addOrderHistory($order_id, $order_status_id);
214+
}
215+
exit();
157216
}
158217
}
159218
}

0 commit comments

Comments
 (0)