Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Exclude development files from Composer exports (composer install / git archive)
/dev export-ignore
/.github export-ignore
/.gitattributes export-ignore
/.gitignore export-ignore
/CONTRIBUTING.md export-ignore

# Force LF line endings for shell scripts (prevents CRLF issues in Docker)
*.sh text eol=lf
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,6 @@ composer.phar
\#*
/nbproject/

# Environment
.env
dev/.env
42 changes: 17 additions & 25 deletions Controller/Payment/AbstractPaystackStandard.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,19 @@
namespace Pstk\Paystack\Controller\Payment;

use Magento\Payment\Helper\Data as PaymentHelper;
use Pstk\Paystack\Gateway\PaystackApiClient;


abstract class AbstractPaystackStandard extends \Magento\Framework\App\Action\Action {

protected $resultPageFactory;

/**
*
* @var \Magento\Sales\Api\OrderRepositoryInterface
* @var \Magento\Sales\Api\OrderRepositoryInterface
*/
protected $orderRepository;

/**
*
* @var \Magento\Sales\Api\Data\OrderInterface
Expand All @@ -43,33 +44,33 @@ abstract class AbstractPaystackStandard extends \Magento\Framework\App\Action\Ac
protected $checkoutSession;
protected $method;
protected $messageManager;

/**
*
* @var \Pstk\Paystack\Model\Ui\ConfigProvider
* @var \Pstk\Paystack\Model\Ui\ConfigProvider
*/
protected $configProvider;

/**
*
* @var \Yabacon\Paystack
* @var PaystackApiClient
*/
protected $paystack;
protected $paystackClient;

/**
* @var \Magento\Framework\Event\Manager
*/
protected $eventManager;

/**
*
* @var \Psr\Log\LoggerInterface
*/
protected $logger;

/**
*
* @var \Magento\Framework\App\Request\Http
* @var \Magento\Framework\App\Request\Http
*/
protected $request;

Expand All @@ -90,7 +91,8 @@ public function __construct(
\Pstk\Paystack\Model\Ui\ConfigProvider $configProvider,
\Magento\Framework\Event\Manager $eventManager,
\Magento\Framework\App\Request\Http $request,
\Psr\Log\LoggerInterface $logger
\Psr\Log\LoggerInterface $logger,
PaystackApiClient $paystackClient
) {
$this->resultPageFactory = $resultPageFactory;
$this->orderRepository = $orderRepository;
Expand All @@ -102,21 +104,11 @@ public function __construct(
$this->eventManager = $eventManager;
$this->request = $request;
$this->logger = $logger;

$this->paystack = $this->initPaystackPHP();


$this->paystackClient = $paystackClient;

parent::__construct($context);
}

protected function initPaystackPHP() {
$secretKey = $this->method->getConfigData('live_secret_key');
if ($this->method->getConfigData('test_mode')) {
$secretKey = $this->method->getConfigData('test_secret_key');
}
return new \Yabacon\Paystack($secretKey);
}

protected function redirectToFinal($successFul = true, $message="") {
if($successFul){
if($message) $this->messageManager->addSuccessMessage(__($message));
Expand Down
6 changes: 2 additions & 4 deletions Controller/Payment/Callback.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,7 @@ public function execute() {
}

try {
$transactionDetails = $this->paystack->transaction->verify([
'reference' => $reference
]);
$transactionDetails = $this->paystackClient->verifyTransaction($reference);

$reference = explode('_', $transactionDetails->data->reference, 2);
$reference = ($reference[0])?: 0;
Expand All @@ -60,7 +58,7 @@ public function execute() {

$message = "Invalid reference or order number";

} catch (\Yabacon\Paystack\Exception\ApiException $e) {
} catch (\Pstk\Paystack\Gateway\Exception\ApiException $e) {
$message = $e->getMessage();

} catch (Exception $e) {
Expand Down
4 changes: 2 additions & 2 deletions Controller/Payment/Setup.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public function execute() {

try {
return $this->processAuthorization($order);
} catch (\Yabacon\Paystack\Exception\ApiException $e) {
} catch (\Pstk\Paystack\Gateway\Exception\ApiException $e) {
$message = $e->getMessage();
$order->addStatusToHistory($order->getStatus(), $message);
$this->orderRepository->save($order);
Expand All @@ -48,7 +48,7 @@ public function execute() {
}

protected function processAuthorization(\Magento\Sales\Model\Order $order) {
$tranx = $this->paystack->transaction->initialize([
$tranx = $this->paystackClient->initializeTransaction([
'first_name' => $order->getCustomerFirstname(),
'last_name' => $order->getCustomerLastname(),
'amount' => $order->getGrandTotal() * 100, // in kobo
Expand Down
126 changes: 46 additions & 80 deletions Controller/Payment/Webhook.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,94 +3,87 @@
/**
* Paystack Magento2 Module using \Magento\Payment\Model\Method\AbstractMethod
* Copyright (C) 2019 Paystack.com
*
*
* This file is part of Pstk/Paystack.
*
*
* Pstk/Paystack is free software => you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http =>//www.gnu.org/licenses/>.
*/

namespace Pstk\Paystack\Controller\Payment;


use Magento\Sales\Model\Order;

class Webhook extends AbstractPaystackStandard
{

public function execute() {
$finalMessage = "failed";

$resultFactory = $this->resultFactory->create(\Magento\Framework\Controller\ResultFactory::TYPE_RAW);
try {

// Retrieve the request's body and parse it as JSON
$event = \Yabacon\Paystack\Event::capture();
$rawBody = $this->request->getContent();
http_response_code(200);

/* It is a important to log all events received. Add code *
* here to log the signature and body to db or file */
$this->logger->debug("PAYSTACK_LOG: {$event->raw}");

/* Verify that the signature matches one of your keys */
$secretKey = $this->configProvider->getSecretKeyArray();
$owner = $event->discoverOwner($secretKey);
$this->logger->info("Paystack Webhook: received request");

if (!$owner) {
// None of the keys matched the event's signature
// Validate webhook signature
$signature = $this->request->getHeader('X-Paystack-Signature') ?: '';
if (!$signature || !$this->paystackClient->validateWebhookSignature($rawBody, $signature)) {
$this->logger->warning("Paystack Webhook: signature validation failed");
$resultFactory->setContents("auth failed");
return $resultFactory;
}

// Do something with $event->obj
// Give value to your customer but don't give any output
// Remember that this is a call from Paystack's servers and
// Your customer is not seeing the response here at all
switch ($event->obj->event) {
// charge.success
case 'charge.success':
if ('success' === $event->obj->data->status) {
$transactionDetails = $this->paystack->transaction->verify([
'reference' => $event->obj->data->reference
]);
$this->logger->info("Paystack Webhook: signature valid");

$reference = $transactionDetails->data->reference;
$event = json_decode($rawBody);
if (!$event) {
$resultFactory->setContents("invalid payload");
return $resultFactory;
}

$order = $this->orderInterface->loadByIncrementId($reference);
$this->logger->info("Paystack Webhook: event type = " . ($event->event ?? 'unknown'));

switch ($event->event) {
case 'charge.success':
if ('success' === $event->data->status) {
$transactionDetails = $this->paystackClient->verifyTransaction($event->data->reference);

//if is popup mode, reference is generated by Paystack and we provided quoteId instead
if((!$order || !$order->getId()) && isset($event->obj->data->metadata->quoteId)){
$reference = $transactionDetails->data->reference;
$this->logger->info("Paystack Webhook: verified transaction", ['reference' => $reference]);

$this->paystackClient->logTransactionSuccess($reference, $this->configProvider->getPublicKey());

$reference = $transactionDetails->data->reference;
//PSTK_LOGGER HERE
log_transaction_success($reference);
//------------------------
$order = $this->orderInterface->loadByIncrementId($reference);

//if is popup mode, reference is generated by Paystack and we provided quoteId instead
if((!$order || !$order->getId()) && isset($event->obj->data->metadata->quoteId)){

$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$searchCriteriaBuilder = $objectManager->create('Magento\Framework\Api\SearchCriteriaBuilder');
$searchCriteria = $searchCriteriaBuilder->addFilter('quote_id', $event->obj->data->metadata->quoteId, 'eq')->create();
$items = $this->orderRepository->getList($searchCriteria);
if($items->getTotalCount() == 1){
$order = $items->getFirstItem();
$order = $this->orderInterface->loadByIncrementId($reference);

}
// In popup mode, reference is generated by Paystack and we provided quoteId instead
if ((!$order || !$order->getId()) && isset($event->data->metadata->quoteId)) {
$this->logger->info("Paystack Webhook: order not found by reference, searching by quoteId", ['quoteId' => $event->data->metadata->quoteId]);
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$searchCriteriaBuilder = $objectManager->create('Magento\Framework\Api\SearchCriteriaBuilder');
$searchCriteria = $searchCriteriaBuilder->addFilter('quote_id', $event->data->metadata->quoteId, 'eq')->create();
$items = $this->orderRepository->getList($searchCriteria);
if ($items->getTotalCount() == 1) {
$order = $items->getFirstItem();
}
}

if ($order && $order->getId()) {
$this->logger->info("Paystack Webhook: order found, dispatching verify event", [
'order_id' => $order->getIncrementId(),
'current_status' => $order->getStatus(),
]);
// dispatch the `payment_verify_after` event to update the order status
$this->eventManager->dispatch('paystack_payment_verify_after', [
"paystack_order" => $order,
Expand All @@ -99,43 +92,16 @@ public function execute() {
$resultFactory->setContents("success");
return $resultFactory;
}
$this->logger->warning("Paystack Webhook: order not found for reference " . $reference);
}
}
break;
}
}
} catch (Exception $exc) {
} catch (\Exception $exc) {
$this->logger->error("Paystack Webhook: exception", ['error' => $exc->getMessage()]);
$finalMessage = $exc->getMessage();
}

$resultFactory->setContents($finalMessage);
return $resultFactory;
}

function log_transaction_success($trx_ref){
//send reference to logger along with plugin name and public key
$url = "https://plugin-tracker.paystackintegrations.com/log/charge_success";
$plugin_name = 'magento-2';
$public_key = $this->configProvider->getPublicKey();

$fields = [
'plugin_name' => $plugin_name,
'transaction_reference' => $trx_ref,
'public_key' => $public_key
];

$fields_string = http_build_query($fields);

$ch = curl_init();

curl_setopt($ch,CURLOPT_URL, $url);
curl_setopt($ch,CURLOPT_POST, true);
curl_setopt($ch,CURLOPT_POSTFIELDS, $fields_string);

curl_setopt($ch,CURLOPT_RETURNTRANSFER, true);

//execute post
$result = curl_exec($ch);
// echo $result;
}
}
28 changes: 0 additions & 28 deletions Dockerfile

This file was deleted.

7 changes: 7 additions & 0 deletions Gateway/Exception/ApiException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

namespace Pstk\Paystack\Gateway\Exception;

class ApiException extends \Exception
{
}
Loading