Commit 9b05b7c4 by lmf

增加Payoneer 支付渠道

parent 5e3ec3c3
# These are some examples of commonly ignored file patterns.
# You should customize this list as applicable to your project.
# Learn more about .gitignore:
# https://www.atlassian.com/git/tutorials/saving-changes/gitignore
# Node artifact files
node_modules/
dist/
# Compiled Java class files
*.class
# Compiled Python bytecode
*.py[cod]
# Log files
*.log
# Package files
*.jar
# Maven
target/
dist/
# JetBrains IDE
.idea/
# Unit test reports
TEST*.xml
# Generated by MacOS
.DS_Store
# Generated by Windows
Thumbs.db
# Applications
*.app
*.exe
*.war
# Large media files
*.mp4
*.tiff
*.avi
*.flv
*.mov
*.wmv
<?php
namespace Payoneer\OpenPaymentGateway\Api\Data;
/**
* @api
* @since 100.0.2
*/
interface NotificationInterface
{
const TABLE = 'payoneer_notification';
const ID = 'id';
const TRANSACTION_ID = 'transactionId';
const LONG_ID = 'longId';
const ORDER_ID = 'order_id';
const CONTENT = 'content';
const CRON_STATUS = 'cron_status';
const CREATED_AT = 'created_at';
const UPDATED_AT = 'updated_at';
/**
* Get notification id
*
* @return int
*/
public function getId();
/**
* Set notification id
*
* @param int $id
* @return $this
*/
public function setId($id);
/**
* Get transaction id
*
* @return string
*/
public function getTransactionId();
/**
* Set transaction id
*
* @param string $txnId
* @return $this
*/
public function setTransactionId($txnId);
/**
* Get long id
*
* @return string
*/
public function getLongId();
/**
* Set long id
*
* @param string $longId
* @return $this
*/
public function setLongId($longId);
/**
* Get order id
*
* @return string
*/
public function getOrderId();
/**
* Set order id
*
* @param string $orderId
* @return $this
*/
public function setOrderId($orderId);
/**
* Get response content
*
* @return string
*/
public function getContent();
/**
* Set response content
*
* @param string $response
* @return $this
*/
public function setContent($response);
/**
* Get response processed status
*
* @return bool
*/
public function getCronStatus();
/**
* Set response processed status
*
* @param bool $status
* @return $this
*/
public function setCronStatus($status);
}
<?php
declare(strict_types=1);
namespace Payoneer\OpenPaymentGateway\Api\Data;
interface PayoneerTransactionInterface
{
/**
* Constants for keys of data array. Identical to the name of the getter in snake case.
*/
const TRANSACTION_ID = 'transaction_id';
const CUSTOMER_ID = 'customer_id';
const REGISTRATION_ID = 'registration_id';
/**
* Get TransactionId.
*
* @return int
*/
public function getTransactionId();
/**
* Set TransactionId.
* @param int $transactionId
* @return void
*/
public function setTransactionId($transactionId);
/**
* @return int
*/
public function getCustomerId();
/**
* Set CustomerId.
* @param int $customerId.
* @return void
*/
public function setCustomerId($customerId);
/**
* Get RegistrationId.
*
* @return string
*/
public function getRegistrationId();
/**
* Set RegistrationId.
* @param string $registrationId.
* @return void
*/
public function setRegistrationId($registrationId);
}
<?php
namespace Payoneer\OpenPaymentGateway\Api;
use Payoneer\OpenPaymentGateway\Api\Data\NotificationInterface;
/**
* @api
* @since 100.0.2
*/
interface PayoneerNotificationRepositoryInterface
{
/**
* Save the notification data
*
* @param NotificationInterface $notification
* @return NotificationInterface
* @throws \Magento\Framework\Exception\InputException
* @throws \Magento\Framework\Exception\LocalizedException
* @throws \Magento\Framework\Exception\CouldNotSaveException
*/
public function save(NotificationInterface $notification);
}
<?php
declare(strict_types=1);
namespace Payoneer\OpenPaymentGateway\Api;
use Payoneer\OpenPaymentGateway\Api\Data\PayoneerTransactionInterface;
/**
* Grid CRUD interface.
* @api
*/
interface PayoneerTransactionRepositoryInterface
{
/**
* @param PayoneerTransactionInterface $payoneerTransaction
* @return mixed
*/
public function save(PayoneerTransactionInterface $payoneerTransaction);
/**
* @param int $customerId
* @return mixed
*/
public function getByCustomerId($customerId);
/**
* @return mixed
*/
public function create();
}
<?php
namespace Payoneer\OpenPaymentGateway\Block\Adminhtml\Form\Field;
use Magento\Config\Block\System\Config\Form\Field;
use Magento\Framework\Data\Form\Element\AbstractElement;
/**
* Class ColorPicker
* Creates ColorPicker element
*/
class ColorPicker extends Field
{
/**
* @param AbstractElement $element
* @return string
*/
protected function _getElementHtml(AbstractElement $element)
{
$html = $element->getElementHtml();
$value = $element->getData('value');
$html .= '<script type="text/javascript">
require(["jquery","jquery/colorpicker/js/colorpicker"], function ($) {
$(document).ready(function () {
var $el = $("#' . $element->getHtmlId() . '");
$el.css("backgroundColor", "' . $value . '");
// Attach the color picker
$el.ColorPicker({
color: "' . $value . '",
onChange: function (hsb, hex, rgb) {
$el.css("backgroundColor", "#" + hex).val("#" + hex);
}
});
});
});
</script>';
return $html;
}
}
<?php
namespace Payoneer\OpenPaymentGateway\Block\Adminhtml\Form\Field;
use Magento\Config\Block\System\Config\Form\Field;
use Magento\Framework\Data\Form\Element\AbstractElement;
/**
* Class Disable
* Disables the configuration field
*/
class Disable extends Field
{
/**
* Disables the configuration field
*
* @param AbstractElement $element
* @return string
*/
protected function _getElementHtml(AbstractElement $element)
{
$element->setDisabled('disabled');
return $element->getElementHtml();
}
}
<?php
namespace Payoneer\OpenPaymentGateway\Block\Adminhtml\Form\Field;
use Magento\Config\Block\System\Config\Form\Field;
use Magento\Framework\Data\Form\Element\AbstractElement;
use Magento\Framework\Exception\LocalizedException;
use Magento\Store\Model\Store;
/**
* Class ValidateCredentials
* Creates button for validating the credentials
*/
class ValidateCredentials extends Field
{
/**
* @inheritDoc
*/
protected function _renderScopeLabel(AbstractElement $element): string
{
// Return empty label
return '';
}
/**
* @inheritDoc
* @throws LocalizedException
*/
protected function _getElementHtml(AbstractElement $element): string
{
// Replace field markup with validation button
$title = __('Validate credentials');
$envId = 'select-groups-payoneer-fields-environment-value';
$storeId = 0;
if ($this->getRequest()->getParam('website')) {
$website = $this->_storeManager->getWebsite($this->getRequest()->getParam('website'));
if ($website->getId()) {
/** @var Store $store */
$store = $website->getDefaultStore();/** @phpstan-ignore-line */
$storeId = $store->getStoreId();
}
}
$endpoint = $this->getUrl('payoneer/configuration/validatecredentials', ['storeId' => $storeId]);
// @codingStandardsIgnoreStart
$html = <<<TEXT
<button
type="button"
title="{$title}"
class="button"
onclick="payoneerValidator.call(this, '{$endpoint}', '{$envId}')">
<span>{$title}</span>
</button>
TEXT;
// @codingStandardsIgnoreEnd
return $html;
}
}
<?php
namespace Payoneer\OpenPaymentGateway\Block;
use Magento\Framework\Phrase;
use Magento\Payment\Block\ConfigurableInfo;
/**
* Class Info
*
* Info block for Payoneer payment gateway
*/
class Info extends ConfigurableInfo
{
/**
* Returns label
*
* @param string $field
* @return Phrase
*/
protected function getLabel($field)
{
return __($field);
}
}
<?php
namespace Payoneer\OpenPaymentGateway\Controller\Adminhtml\Configuration;
use Exception;
use Magento\Backend\App\Action;
use Magento\Framework\Controller\Result\JsonFactory;
use Magento\Framework\Controller\ResultFactory;
use Magento\Framework\Controller\ResultInterface;
use Payoneer\OpenPaymentGateway\Gateway\Config\Config;
use Payoneer\OpenPaymentGateway\Model\Api\Request;
/**
* Class ValidateCredentials
* Validate the API Credentials
*/
class ValidateCredentials extends Action
{
const ADMIN_RESOURCE = 'Magento_Config::config';
/**
* @var Config
*/
private $config;
/**
* @var Request
*/
private $request;
/**
* Json Factory
*
* @var JsonFactory
*/
private $jsonResultFactory;
/**
* ValidateCredentials constructor.
* @param Action\Context $context
* @param Config $config
* @param Request $request
* @param JsonFactory $jsonResultFactory
*/
public function __construct(
Action\Context $context,
Config $config,
Request $request,
JsonFactory $jsonResultFactory
) {
parent::__construct($context);
$this->config = $config;
$this->request = $request;
$this->jsonResultFactory = $jsonResultFactory;
}
/**
* Validates the field values
*
* @return ResultInterface
*/
public function execute(): ResultInterface
{
$gatewayResponse = [];
$endPoint = Config::LIST_END_POINT;
$data = $this->config->getMockData();
$storeCode = $this->getRequest()->getParam('storeCode');
$credentials['merchantCode'] = $this->getRequest()->getParam('merchantCode');
$credentials['apiKey'] = $this->getRequest()->getParam('apiKey');
$hostName = $this->getRequest()->getParam('hostName');
if ($hostName) {
$credentials['hostName'] = $hostName;
} else {
$credentials['hostName'] = $this->config->getCredentials($this->config::HOST_NAME);
}
if ($storeCode) {
$data['division'] = $storeCode;
}
$response = $this->resultFactory->create(ResultFactory::TYPE_JSON);
try {
$gatewayResponse = $this->request->send(
Config::METHOD_POST,
$endPoint,
$credentials,
$data
);
$response->setHttpResponseCode($gatewayResponse['status']);
} catch (Exception $e) {
$response->setHttpResponseCode(400);
}
$result = $this->jsonResultFactory->create();
$responseData = isset($gatewayResponse['response'])
? $gatewayResponse['response'] : [];
return $result->setData(['data' => $responseData]);
}
}
<?php
namespace Payoneer\OpenPaymentGateway\Controller\Adminhtml\Gateway;
use Magento\Backend\App\Action;
use Magento\Framework\App\ResponseInterface;
use Magento\Framework\Controller\Result\Redirect;
use Magento\Framework\Controller\ResultInterface;
use Magento\Sales\Model\Order;
use Payoneer\OpenPaymentGateway\Gateway\Config\Config;
use Payoneer\OpenPaymentGateway\Model\Adminhtml\Helper;
use Payoneer\OpenPaymentGateway\Model\Adminhtml\TransactionService as AdminTransactionService;
/**
* Class Capture
*
* Process Payoneer capture request
*/
class Capture extends Action
{
/**
* @var AdminTransactionService
*/
protected $listCapture;
/**
* @var Helper
*/
protected $helper;
/**
* Capture constructor.
*
* @param Action\Context $context
* @param AdminTransactionService $listCapture
* @param Helper $helper
*/
public function __construct(
Action\Context $context,
AdminTransactionService $listCapture,
Helper $helper
) {
parent::__construct($context);
$this->listCapture = $listCapture;
$this->helper = $helper;
}
/**
* Process Payoneer capture
*
* @return ResponseInterface|Redirect|ResultInterface
*/
public function execute()
{
$resultRedirect = $this->resultRedirectFactory->create();
$orderId = (int)$this->getRequest()->getParam('order_id');
if ($orderId) {
try {
/** @var Order $order */
$order = $this->helper->getOrder($orderId);
/** @var string[] $result */
$result = $this->listCapture->process($order, Config::LIST_CAPTURE);
if ($result) {
$this->helper->processCaptureResponse($result, $order);
}
} catch (\Exception $e) {
$this->helper
->showErrorMessage(__('Transaction failed') . ' ' . $e->getMessage());
}
}
return $resultRedirect->setPath('sales/order/view', ['order_id' => $orderId]);
}
}
<?php
namespace Payoneer\OpenPaymentGateway\Controller\Adminhtml\Gateway;
use Magento\Backend\App\Action;
use Magento\Framework\App\ResponseInterface;
use Magento\Framework\Controller\Result\Redirect;
use Magento\Framework\Controller\ResultInterface;
use Magento\Sales\Model\Order;
use Payoneer\OpenPaymentGateway\Model\Adminhtml\Helper;
use Payoneer\OpenPaymentGateway\Model\Adminhtml\TransactionService as AdminTransactionService;
use Payoneer\OpenPaymentGateway\Gateway\Config\Config;
use Payoneer\OpenPaymentGateway\Model\TransactionOrderUpdater;
/**
* Class Fetch
* Process Payoneer fetch request
*/
class Fetch extends Action
{
/**
* @var AdminTransactionService
*/
protected $transactionService;
/**
* @var Helper
*/
protected $helper;
/**
* @var TransactionOrderUpdater
*/
protected $transactionOrderUpdater;
/**
* Fetch constructor.
*
* @param Action\Context $context
* @param AdminTransactionService $transactionService
* @param TransactionOrderUpdater $transactionOrderUpdater
* @param Helper $helper
* @return void
*/
public function __construct(
Action\Context $context,
AdminTransactionService $transactionService,
TransactionOrderUpdater $transactionOrderUpdater,
Helper $helper
) {
parent::__construct($context);
$this->transactionService = $transactionService;
$this->helper=$helper;
$this->transactionOrderUpdater=$transactionOrderUpdater;
}
/**
* Process Payoneer fetch
*
* @return ResponseInterface|Redirect|ResultInterface
*/
public function execute()
{
$resultRedirect = $this->resultRedirectFactory->create();
$orderId = (int)$this->getRequest()->getParam('order_id');
if ($orderId) {
try {
/** @var Order $order */
$order = $this->helper->getOrder($orderId);
/** @var mixed $result */
$result = $this->transactionService->process($order, Config::LIST_FETCH);
if ($result && $result['status'] == 200) {
$this->transactionOrderUpdater->processFetchUpdateResponse(
$order,
$result
);
$this->helper->showSuccessMessage(
__('Data successfully synced')
);
} else {
$this->helper
->showErrorMessage(
__('Error response with the %1 code received from Payoneer. Check the payoneer.log file for details.', $result['status'])
);
}
} catch (\Exception $e) {
$this->helper
->showErrorMessage(__('Transaction failed') . ' ' . $e->getMessage());
}
}
return $resultRedirect->setPath('sales/order/view', ['order_id' => $orderId]);
}
}
<?php
namespace Payoneer\OpenPaymentGateway\Controller\Embedded;
use Magento\Framework\App\Action\HttpGetActionInterface;
use Magento\Framework\App\ResponseInterface;
use Magento\Framework\Controller\Result\Raw;
use Magento\Framework\Controller\Result\RawFactory;
use Magento\Framework\Controller\ResultInterface;
use Payoneer\OpenPaymentGateway\Gateway\Config\Config;
/**
* Class Style
* Process Style data for embedded integration
*/
class Style implements HttpGetActionInterface
{
/**
* @var RawFactory
*/
protected $resultRawFactory;
/**
* @var Config
*/
protected $config;
/**
* Style constructor.
* @param RawFactory $resultRawFactory
* @param Config $config
*/
public function __construct(
RawFactory $resultRawFactory,
Config $config
) {
$this->resultRawFactory = $resultRawFactory;
$this->config = $config;
}
/**
* Creates raw css file based on configuration
* @return ResponseInterface|Raw|ResultInterface
*/
public function execute()
{
$styleConfig = $this->config->getStyleConfig();
$containerCSS = $this->getContainerStyle($styleConfig);
$containerPlaceholderCSS = $this->getContainerPlaceholderStyle();
$checkoutCssConfig = $this->config->getValue('widget_appearance/checkout_css');
$widgetCSS = $containerCSS . $containerPlaceholderCSS;
if ($checkoutCssConfig) {
$widgetCSS = $widgetCSS . $checkoutCssConfig;
}
$resultRaw = $this->resultRawFactory->create();
$resultRaw->setHeader('Content-type', 'text/css');
$resultRaw->setContents($widgetCSS);
return $resultRaw;
}
/**
* Get formatted css for the container
* @param array <mixed> $styleConfig
* @return string
*/
public function getContainerStyle($styleConfig)
{
$content = '#networkForm, .op-payment-widget-container {';
foreach ($styleConfig as $key => $value) {
$content = $content . $key . ':' . $value . ';';
}
return $content . '}';
}
/**
* Get placeholder css
* @return string
*/
public function getContainerPlaceholderStyle()
{
$inputStyle = '';
$selectStyle = '';
$placeholderValue = $this->config->getValue('widget_appearance/placeholders_color');
$phContentClass = '#networkForm ::placeholder, .op-payment-widget-container ::placeholder {';
$phContent = $phContentClass . 'opacity: 1;';
if ($placeholderValue) {
$phColor = 'color:' . $placeholderValue . ';';
$phContent = $phContent . $phColor;
$inputStyle = '#networkForm ::-ms-input-placeholder, .op-payment-widget-container ::-ms-input-placeholder{'
. $phColor . '}';
$selectStyle = '#networkForm select {' . $phColor . '}';
}
$phContent = $phContent . '}';
if ($inputStyle) {
$phContent = $phContent . $inputStyle . $selectStyle;
}
return $phContent;
}
}
<?php
namespace Payoneer\OpenPaymentGateway\Controller\Integration;
use Exception;
use Magento\Checkout\Model\Session;
use Magento\Framework\App\ActionInterface;
use Magento\Framework\App\RequestInterface as Request;
use Magento\Framework\Controller\Result\Json;
use Magento\Framework\Controller\Result\JsonFactory;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\Message\ManagerInterface;
use Magento\Payment\Gateway\Command\ResultInterface;
use Payoneer\OpenPaymentGateway\Gateway\Config\Config;
use Payoneer\OpenPaymentGateway\Model\ListUpdateTransactionService;
use Payoneer\OpenPaymentGateway\Model\TransactionService;
/**
* Class ProcessPayment
* Process List request for hosted payment
*/
class ProcessPayment implements ActionInterface
{
const LIST_EXPIRED = 'list_expired';
const HOSTED = 'hosted';
/**
* @var Session
*/
private $checkoutSession;
/**
* @var TransactionService
*/
private $transactionService;
/**
* @var ListUpdateTransactionService
*/
private $updateTransactionService;
/**
* @var ManagerInterface
*/
protected $messageManager;
/**
* @var Request
*/
protected $request;
/**
* @var JsonFactory
*/
protected $resultJsonFactory;
/**
* ProcessPayment constructor.
* @param Session $checkoutSession
* @param TransactionService $transactionService
* @param ListUpdateTransactionService $updateTransactionService
* @param ManagerInterface $messageManager
* @param Request $request
* @param JsonFactory $resultJsonFactory
*/
public function __construct(
Session $checkoutSession,
TransactionService $transactionService,
ListUpdateTransactionService $updateTransactionService,
ManagerInterface $messageManager,
Request $request,
JsonFactory $resultJsonFactory
) {
$this->checkoutSession = $checkoutSession;
$this->transactionService = $transactionService;
$this->updateTransactionService = $updateTransactionService;
$this->messageManager = $messageManager;
$this->request = $request;
$this->resultJsonFactory = $resultJsonFactory;
}
/**
* @return Json | array <mixed>
* @throws LocalizedException
* @throws NoSuchEntityException
* @throws \Exception
*/
public function execute()
{
$quote = $this->checkoutSession->getQuote();
$payment = $quote->getPayment();
$additionalInformation = $payment->getAdditionalInformation();
/** @phpstan-ignore-next-line */
$listId = isset($additionalInformation[Config::LIST_ID]) ?? $additionalInformation[Config::LIST_ID];
try {
if (!$listId) {
$response = $this->transactionService->process($quote);
} else {
/** @var array <mixed> $response */
$response = $this->updateTransactionService->process($quote->getPayment(), Config::LIST_UPDATE);
//if list session gave an update error, create a new one
if ($this->updateError($response)) {
$response = $this->transactionService->process($quote);
}
}
if ($this->isHostedIntegration()) {
$jsonData = $this->processHostedResponse($response);
} else {
$jsonData = $this->processEmbeddedResponse($response);
}
return $this->resultJsonFactory->create()->setData($jsonData);
} catch (Exception $e) {
return $this->resultJsonFactory->create()->setHttpResponseCode(400)->setData([
'error' => $e->getMessage()
]);
}
}
/**
* @param array <mixed> $result
* @return bool
*/
public function isListExpired($result)
{
if (isset($result['reason']) && str_contains($result['reason'], self::LIST_EXPIRED)) {
return true;
}
return false;
}
/**
* @param array <mixed> $result
* @return bool
*/
public function updateError($result)
{
if (isset($result['status']) && ($result['status'] == 422 || $result['status'] == 409)) {
return true;
} else {
return false;
}
}
/**
* Process response of hosted integration
* @param ResultInterface|null|bool|array <mixed> $result
* @return array <mixed>
* @throws LocalizedException
* @throws NoSuchEntityException
*/
public function processHostedResponse($result)
{
if ($result && isset($result['response']['redirect'])) {
$redirectURL = $result['response']['redirect']['url'];
} else {
$quote = $this->checkoutSession->getQuote();
$payment = $quote->getPayment();
$additionalInformation = $payment->getAdditionalInformation();
if (isset($additionalInformation[Config::REDIRECT_URL])) {
$redirectURL = $additionalInformation[Config::REDIRECT_URL];
} else {
$this->messageManager->addErrorMessage(__('We couldn\'t process the payment'));
}
}
return (isset($redirectURL)? ['redirectURL' => $redirectURL]: []);
}
/**
* Process response of embedded integration
* @param ResultInterface|null|bool|array <mixed> $result
* @return array <mixed>
*/
public function processEmbeddedResponse($result)
{
$jsonData = [];
if ($result && isset($result['response']['links'])) {
$jsonData = [
'links' => $result['response']['links']
];
} else {
$this->messageManager->addErrorMessage(__('We couldn\'t process the payment'));
}
return $jsonData;
}
/**
* @return bool
*/
public function isHostedIntegration()
{
return $this->request->getParam(Config::INTEGRATION) == Config::INTEGRATION_HOSTED;
}
}
<?php
namespace Payoneer\OpenPaymentGateway\Controller\Redirect;
use Magento\Framework\App\Action\Context;
use Magento\Framework\App\Action\HttpGetActionInterface;
use Magento\Framework\App\ResponseInterface;
use Magento\Framework\Controller\ResultInterface;
use Magento\Framework\Exception\CouldNotSaveException;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\View\Result\Page;
use Magento\Quote\Api\CartRepositoryInterface;
use Magento\Quote\Model\Quote;
use Magento\Sales\Api\TransactionRepositoryInterface;
use Magento\Sales\Model\Order\Payment\Transaction;
use Magento\Sales\Model\ResourceModel\Order\Payment\Transaction\CollectionFactory as OrderTransactionCollectionFactory;
use Payoneer\OpenPaymentGateway\Model\Helper;
use Payoneer\OpenPaymentGateway\Logger\NotificationLogger;
use Magento\Checkout\Model\Session as CheckoutSession;
/**
* Class Cancel
* Process CANCEL request
*/
class Cancel implements HttpGetActionInterface
{
/**
* @var Context
*/
private $context;
/**
* @var CartRepositoryInterface
*/
private $cartRepository;
/**
* @var Helper
*/
private $helper;
/**
* @var TransactionRepositoryInterface
*/
private $transactionRepository;
/**
* @var OrderTransactionCollectionFactory
*/
protected $orderTransactionCollectionFactory;
/**
* @var NotificationLogger
*/
protected $notificationLogger;
/**
* @var CheckoutSession
*/
protected $checkoutSession;
/**
* Helper constructor.
* @param Context $context
* @param CartRepositoryInterface $cartRepository
* @param Helper $helper
* @param TransactionRepositoryInterface $transactionRepository
* @param OrderTransactionCollectionFactory $orderTransactionCollectionFactory
* @param NotificationLogger $notificationLogger
* @param CheckoutSession $checkoutSession
*/
public function __construct(
Context $context,
CartRepositoryInterface $cartRepository,
Helper $helper,
TransactionRepositoryInterface $transactionRepository,
OrderTransactionCollectionFactory $orderTransactionCollectionFactory,
NotificationLogger $notificationLogger,
CheckoutSession $checkoutSession
) {
$this->context = $context;
$this->cartRepository = $cartRepository;
$this->helper = $helper;
$this->transactionRepository = $transactionRepository;
$this->orderTransactionCollectionFactory = $orderTransactionCollectionFactory;
$this->notificationLogger = $notificationLogger;
$this->checkoutSession = $checkoutSession;
}
/**
* @return ResponseInterface|ResultInterface|Page
*/
public function execute()
{
$reqParams = $this->context->getRequest()->getParams();
try {
// Session to skip order confirmation email sending
$this->checkoutSession->setIsPayoneerCancelledOrder(true);
$this->checkoutSession->setPayoneerSkipInvoiceCreation(true);
$this->helper->setPayoneerInvalidTxnSession();
// Place order with invalid transaction details
$this->saveCartAndPlaceOrder($reqParams);
// Restore quote
$this->checkoutSession->restoreQuote();
// Update the invalid order transaction type to void
$this->updateTransactionType();
//Add comment to the order
$this->helper->addCommentToOrder();
} catch (\Exception $e) {
$this->notificationLogger->addError(
'CancelError - ' . $e->getMessage()
);
}
return $this->helper->redirectToCart(
__('We couldn\'t process the payment')
);
}
/**
* @param array <mixed> $reqParams
* @throws CouldNotSaveException
* @throws LocalizedException
* @throws NoSuchEntityException
* @return void
*/
public function saveCartAndPlaceOrder($reqParams)
{
$cartId = $reqParams['cart_id'];
if ($cartId) {
/** @var Quote $quote */
$quote = $this->cartRepository->getActive($reqParams['cart_id']);
$payment = $quote->getPayment();
foreach ($reqParams as $key => $value) {
$payment->setAdditionalInformation($key, $value);
}
$quote->setPayment($payment);
if (!$quote->getCustomerId()) {
$quote = $this->helper->setGuestCustomerEmail($quote);
}
$this->cartRepository->save($quote);
$this->helper->placeOrder($reqParams['cart_id']);
}
}
/**
* Updates transaction type to 'void'
*
* @return void
*/
public function updateTransactionType()
{
$orderId = $this->helper->getLastOrderId();
$collection = $this->orderTransactionCollectionFactory->create();
$collection->addOrderIdFilter($orderId);
if ($collection->getSize()) {
/** @var Transaction $transaction */
$transaction = $collection->getFirstItem();
$transaction->setTxnType('void');
$transaction->setIsClosed(1);
$this->transactionRepository->save($transaction);
}
}
}
<?php
namespace Payoneer\OpenPaymentGateway\Controller\Redirect;
use Exception;
use Magento\Framework\App\CsrfAwareActionInterface;
use Magento\Framework\App\Request\Http;
use Magento\Framework\App\Request\InvalidRequestException;
use Magento\Framework\App\RequestInterface;
use Magento\Framework\App\ResponseInterface;
use Magento\Framework\Controller\ResultInterface;
use Payoneer\OpenPaymentGateway\Api\Data\NotificationInterfaceFactory;
use Payoneer\OpenPaymentGateway\Api\PayoneerNotificationRepositoryInterface;
use Payoneer\OpenPaymentGateway\Gateway\Config\Config;
use Payoneer\OpenPaymentGateway\Model\PayoneerNotification;
use Payoneer\OpenPaymentGateway\Model\PayoneerNotificationFactory;
use Magento\Sales\Model\ResourceModel\Order\CollectionFactory as OrderCollectionFactory;
use Payoneer\OpenPaymentGateway\Logger\NotificationLogger;
use Payoneer\OpenPaymentGateway\Model\Adminhtml\Helper;
use Payoneer\OpenPaymentGateway\Model\TransactionOrderUpdater;
/**
* Class Notification
*
* Process Notification request
*/
class Notification implements CsrfAwareActionInterface
{
/**
* @var PayoneerNotificationFactory
*/
protected $payoneerNotification;
/**
* @var Http
*/
protected $request;
/**
* @var PayoneerNotificationRepositoryInterface
*/
protected $notificationRepository;
/**
* @var NotificationInterfaceFactory
*/
protected $notificationFactory;
/**
* @var OrderCollectionFactory
*/
protected $orderCollectionFactory;
/**
* @var NotificationLogger
*/
protected $notificationLogger;
/**
* @var TransactionOrderUpdater
*/
protected $transactionOrderUpdater;
/**
* Notification constructor.
*
* @param PayoneerNotificationFactory $payoneerNotification
* @param PayoneerNotificationRepositoryInterface $notificationRepository
* @param NotificationInterfaceFactory $notificationFactory
* @param OrderCollectionFactory $orderCollectionFactory
* @param NotificationLogger $notificationLogger
* @param Http $request
* @param TransactionOrderUpdater $transactionOrderUpdater
*/
public function __construct(
PayoneerNotificationFactory $payoneerNotification,
PayoneerNotificationRepositoryInterface $notificationRepository,
NotificationInterfaceFactory $notificationFactory,
OrderCollectionFactory $orderCollectionFactory,
NotificationLogger $notificationLogger,
Http $request,
TransactionOrderUpdater $transactionOrderUpdater
) {
$this->payoneerNotification = $payoneerNotification;
$this->notificationRepository = $notificationRepository;
$this->notificationFactory = $notificationFactory;
$this->request = $request;
$this->orderCollectionFactory = $orderCollectionFactory;
$this->notificationLogger = $notificationLogger;
$this->transactionOrderUpdater = $transactionOrderUpdater;
}
/**
* Listen notification from payoneer side and save to db.
*
* @return ResponseInterface|ResultInterface|void|null
* @throws Exception
*/
public function execute()
{
try {
$urlParams = $this->request->getParams();
$post = $this->request->getContent();
$postArray = \Safe\json_decode($post, true);
if ($postArray['entity'] == Config::ENTITY_PAYMENT) {
/** @var PayoneerNotification $notification */
$notification = $this->notificationFactory->create();
$notification->addData([
'transactionId' => $postArray['transactionId'],
'longId' => $postArray['longId'],
'content' => $post,
'order_id' => $urlParams['order_id'],
'cron_status' => 0
]);
$this->notificationRepository->save($notification);
if (isset($postArray['statusCode']) &&
isset($postArray['interactionReason']) &&
$postArray['interactionReason'] != Helper::SYSTEM_FAILURE
) {
$this->transactionOrderUpdater->processNotificationResponse(
$notification->getOrderId(),
$postArray
);
$notification->setCronStatus(true);
$this->notificationRepository->save($notification);
}
}
} catch (Exception $e) {
$this->notificationLogger->addError(
__(
'ErrorMessage = %1, OrderId = %2, NotificationResponse = %3.',
$e->getMessage(),
$urlParams['order_id'],
$post
)
);
}
exit; // @codingStandardsIgnoreLine
}
/**
* Get the token from the order payment additional info.
*
* @param string $orderId
* @return string|null
*/
private function getTokenFromOrder($orderId)
{
$collection = $this->orderCollectionFactory->create();
$collection->addFieldToFilter('increment_id', ['eq' => $orderId]);
if ($collection->getSize()) {
$order = $collection->getFirstItem();
$payment = $order->getPayment();
return $payment->getAdditionalInformation(Config::TOKEN_NOTIFICATION);
}
return null;
}
/**
* @param RequestInterface $request
* @return InvalidRequestException|null
*/
public function createCsrfValidationException(RequestInterface $request): ?InvalidRequestException
{
return null;
}
/**
* @param RequestInterface $request
* @return bool|null
*/
public function validateForCsrf(RequestInterface $request): ?bool
{
$orderId = $request->getParam('order_id');
$notificationToken = $request->getParam('token');
$orderToken = $this->getTokenFromOrder($orderId);
if ($notificationToken == '' || $notificationToken == null || $notificationToken != $orderToken) {
$this->notificationLogger->addError(
__(
'Invalid token for order #%1, order token = %2, received token = %3',
$orderId,
$orderToken,
$notificationToken
)
);
return false;
}
return true;
}
}
<?php
namespace Payoneer\OpenPaymentGateway\Controller\Redirect;
use Magento\Checkout\Model\Session;
use Magento\Framework\App\Action\Context;
use Magento\Framework\App\Action\HttpGetActionInterface;
use Magento\Framework\App\ResponseInterface;
use Magento\Framework\Controller\Result\Redirect;
use Magento\Framework\Controller\ResultInterface;
use Magento\Framework\View\Result\Page;
use Magento\Framework\View\Result\PageFactory;
use Magento\Quote\Api\CartManagementInterface;
use Magento\Quote\Api\CartRepositoryInterface;
use Magento\Quote\Model\Quote;
use Payoneer\OpenPaymentGateway\Gateway\Config\Config;
use Payoneer\OpenPaymentGateway\Model\Adminhtml\Source\Fields as AdminFields;
use Payoneer\OpenPaymentGateway\Model\Helper;
/**
* Class Success
* Process SUCCESS request
*/
class Success implements HttpGetActionInterface
{
const INTERACTION_CODE_PROCEED = 'PROCEED';
/**
* @var Context
*/
private $context;
/**
* @var CartRepositoryInterface
*/
private $cartRepository;
/**
* @var PageFactory
*/
private $resultPageFactory;
/**
* @var Helper
*/
protected $helper;
/**
* @var Session
*/
private $checkoutSession;
/**
* @var Config
*/
private $config;
/**
* Success constructor.
* @param Context $context
* @param CartRepositoryInterface $cartRepository
* @param PageFactory $resultPageFactory
* @param Helper $helper
* @param Session $checkoutSession
* @param Config $config
*/
public function __construct(
Context $context,
CartRepositoryInterface $cartRepository,
PageFactory $resultPageFactory,
Helper $helper,
Session $checkoutSession,
Config $config
) {
$this->context = $context;
$this->cartRepository = $cartRepository;
$this->resultPageFactory = $resultPageFactory;
$this->helper = $helper;
$this->checkoutSession = $checkoutSession;
$this->config = $config;
}
/**
* Dispatch request
* @return ResponseInterface|Redirect|ResultInterface|Page
*/
public function execute()
{
$reqParams = $this->context->getRequest()->getParams();
try {
if (isset($reqParams['listUrl']) &&
isset($reqParams['interactionCode']) &&
$reqParams['interactionCode'] == self::INTERACTION_CODE_PROCEED
) {
$cartId = $reqParams['cart_id'];
/** @var Quote $quote */
$quote = $this->cartRepository->getActive($cartId);
$quoteData = $quote->getData();
$payment = $quote->getPayment();
if (!isset($reqParams['token'])
|| $reqParams['token'] == ''
|| $reqParams['token'] == null
|| $payment->getAdditionalInformation('token') != $reqParams['token']
) {
return $this->redirectToCart();
} else {
foreach ($reqParams as $key => $value) {
$payment->setAdditionalInformation($key, $value);
}
if ($this->config->getValue('payment_action') == AdminFields::CAPTURE) {
$payment->setAdditionalInformation('payoneerCapture', 'Success');
}
$quote->setPayment($payment);
}
if ($quote->getCustomerId() && isset($reqParams['customerRegistrationId'])) {
$this->helper->saveRegistrationId($reqParams['customerRegistrationId'], $quote->getCustomerId());
}
if (!$quote->getCustomerId()) {
$quote = $this->helper->setGuestCustomerEmail($quote);
} else {
$this->helper->unsetPayoneerCustomerEmailSession();
}
$this->cartRepository->save($quote);
if ($quoteData['grand_total'] != $reqParams['amount']) {
$this->checkoutSession->setUpdateOrderStatus(true);
}
//Place order in magento
$this->helper->placeOrder($cartId);
//Unset custom Payoneer sessions
$this->helper->unsetPayoneerCountryIdSession();
return $this->resultPageFactory->create();
} else {
return $this->redirectToCart();
}
} catch (\Exception $e) {
return $this->redirectToCart($e->getMessage());
}
}
/**
* @param string|null $message
* @return Redirect
*/
public function redirectToCart($message = null)
{
if (!$message) {
$message = 'We couldn\'t process the payment. Invalid response from Payoneer.';
}
return $this->helper->redirectToCart(__($message));
}
}
<?php
namespace Payoneer\OpenPaymentGateway\Cron;
use Magento\Framework\Stdlib\DateTime\TimezoneInterface;
use Payoneer\OpenPaymentGateway\Model\ResourceModel\PayoneerNotification\CollectionFactory;
use Payoneer\OpenPaymentGateway\Model\TransactionOrderUpdater;
use Payoneer\OpenPaymentGateway\Model\ResourceModel\PayoneerNotification\Collection;
use Payoneer\OpenPaymentGateway\Logger\NotificationLogger;
use Payoneer\OpenPaymentGateway\Gateway\Config\Config;
use Payoneer\OpenPaymentGateway\Model\NotificationEmailSender;
use Payoneer\OpenPaymentGateway\Api\PayoneerNotificationRepositoryInterface;
/**
* Update order on running cron with notification data
*/
class OrderUpdate
{
/**
* @var CollectionFactory
*/
private $notificationCollectionFactory;
/**
* @var TransactionOrderUpdater
*/
protected $transactionOrderUpdater;
/**
* @var NotificationLogger
*/
protected $notificationLogger;
/**
* @var Config
*/
protected $config;
/**
* @var TimezoneInterface
*/
protected $timezone;
/**
* @var NotificationEmailSender
*/
protected $emailSender;
/**
* @var PayoneerNotificationRepositoryInterface
*/
protected $notificationRepository;
/**
* OrderUpdate construct function
*
* @param CollectionFactory $notificationCollectionFactory
* @param TransactionOrderUpdater $transactionOrderUpdater
* @param NotificationLogger $notificationLogger
* @param Config $config
* @param TimezoneInterface $timezone
* @param NotificationEmailSender $emailSender
* @param PayoneerNotificationRepositoryInterface $notificationRepository
* @return void
*/
public function __construct(
CollectionFactory $notificationCollectionFactory,
TransactionOrderUpdater $transactionOrderUpdater,
NotificationLogger $notificationLogger,
Config $config,
TimezoneInterface $timezone,
NotificationEmailSender $emailSender,
PayoneerNotificationRepositoryInterface $notificationRepository
) {
$this->notificationCollectionFactory = $notificationCollectionFactory;
$this->transactionOrderUpdater = $transactionOrderUpdater;
$this->notificationLogger = $notificationLogger;
$this->config = $config;
$this->timezone = $timezone;
$this->emailSender = $emailSender;
$this->notificationRepository = $notificationRepository;
}
/**
* Get the non-processed notification and process it.
*
* @return bool|void
*/
public function execute()
{
try {
$notificationCollection = $this->getNotificationsToCleanUp();
if ($notificationCollection != null) {
/** @phpstan-ignore-next-line */
$notificationCollection->walk('delete');
}
} catch (\Exception $e) {
$this->notificationLogger->addError(
__('NotificationCleanupError: %1', $e->getMessage())
);
}
try {
$notificationCollection = $this->getNotificationsToSendEmail();
if ($notificationCollection != null) {
foreach ($notificationCollection as $notification) {
$response = \Safe\json_decode($notification->getContent(), true);
$this->emailSender->send($response);
$notification->setSendEmail(true);
$this->notificationRepository->save($notification);
}
}
} catch (\Exception $e) {
$this->notificationLogger->addError(
__('NotificationEmailSendError: %1', $e->getMessage())
);
}
}
/**
* Get all the notifications to cleanup
*
* @return Collection|null
*/
private function getNotificationsToCleanUp()
{
$cleanupDays = $this->config->getValue(Config::NOTIFICATION_CLEANUP_DAYS_PATH);
if (empty($cleanupDays)) {
return null;
}
$collection = $this->notificationCollectionFactory->create();
$collection->addFieldToFilter('cron_status', ['eq' => 1]);
$collection->addFieldToFilter(
'created_at',
['lteq' => $this->getUtcDateXDaysBefore($cleanupDays)]
);
return $collection;
}
/**
* Get all the notifications to which the email should be send
*
* @return Collection|null
*/
private function getNotificationsToSendEmail()
{
$emailSendDays = $this->config->getValue(Config::EMAIL_NOTIFICATION_DAYS_PATH);
if (empty($emailSendDays)) {
return null;
}
$collection = $this->notificationCollectionFactory->create();
$collection->addFieldToFilter('cron_status', ['eq' => 0]);
$collection->addFieldToFilter('send_email', ['eq' => 0]);
$collection->addFieldToFilter(
'created_at',
['lteq' => $this->getUtcDateXDaysBefore($emailSendDays)]
);
return $collection;
}
/**
* Get the date in UTC timezone
*
* @param int $noOfDays
* @return string
*/
private function getUtcDateXDaysBefore($noOfDays)
{
return $this->timezone->date()->setTimezone(new \DateTimeZone('UTC'))
->modify('-' . $noOfDays . ' day')
->format('Y-m-d 23:59:59');
}
}
<?php
namespace Payoneer\OpenPaymentGateway\Gateway\Command;
use Magento\Checkout\Model\Session;
use Magento\Payment\Gateway\Command\CommandException;
use Magento\Payment\Gateway\Command\ResultInterface as CommandResultInterface;
use Magento\Payment\Gateway\CommandInterface;
use Magento\Payment\Gateway\ErrorMapper\ErrorMessageMapperInterface;
use Magento\Payment\Gateway\Helper\SubjectReader;
use Magento\Payment\Gateway\Http\ClientException;
use Magento\Payment\Gateway\Http\ClientInterface;
use Magento\Payment\Gateway\Http\ConverterException;
use Magento\Payment\Gateway\Request\BuilderInterface;
use Magento\Payment\Gateway\Response\HandlerInterface;
use Magento\Payment\Gateway\Validator\ResultInterface;
use Magento\Payment\Gateway\Validator\ValidatorInterface;
use Payoneer\OpenPaymentGateway\Gateway\Http\TransferFactoryInterface;
use Psr\Log\LoggerInterface;
/**
* Class GatewayCommand
*
* GatewayCommand for Payoneer payment
*/
class GatewayCommand implements CommandInterface
{
/**
* @var BuilderInterface
*/
protected $requestBuilder;
/**
* @var TransferFactoryInterface
*/
protected $transferFactory;
/**
* @var ClientInterface
*/
protected $client;
/**
* @var LoggerInterface
*/
protected $logger;
/**
* @var HandlerInterface|null
*/
protected $handler;
/**
* @var ValidatorInterface|null
*/
protected $validator;
/**
* @var ErrorMessageMapperInterface|null
*/
private $errorMessageMapper;
/**
* @var Session
*/
private $session;
/**
* Gateway command constructor
*
* @param BuilderInterface $requestBuilder
* @param TransferFactoryInterface $transferFactory
* @param ClientInterface $client
* @param LoggerInterface $logger
* @param Session $checkoutSession
* @param HandlerInterface $handler
* @param ValidatorInterface $validator
* @param ErrorMessageMapperInterface|null $errorMessageMapper
*
*/
public function __construct(
BuilderInterface $requestBuilder,
TransferFactoryInterface $transferFactory,
ClientInterface $client,
LoggerInterface $logger,
Session $checkoutSession,
HandlerInterface $handler = null,
ValidatorInterface $validator = null,
ErrorMessageMapperInterface $errorMessageMapper = null
) {
$this->requestBuilder = $requestBuilder;
$this->transferFactory = $transferFactory;
$this->client = $client;
$this->logger = $logger;
$this->session = $checkoutSession;
$this->handler = $handler;
$this->validator = $validator;
$this->errorMessageMapper = $errorMessageMapper;
}
/**
* Executes command basing on business object
*
* @param array <mixed> $commandSubject
* @return CommandResultInterface | array <mixed>
* @throws CommandException
* @throws ClientException
* @throws ConverterException
*/
public function execute(array $commandSubject)
{
$response = [];
$payment = SubjectReader::readPayment($commandSubject);
$transferO = $this->transferFactory->create(
$this->requestBuilder->build($commandSubject),
$payment
);
//process payoneer request only if it is not via fetch or notification
if ($this->session->getFetchNotificationResponse()) {
$response = $this->session->getFetchNotificationResponse();
} else {
$response = $this->client->placeRequest($transferO);
if ($this->validator !== null) {
$result = $this->validator->validate(
array_merge($commandSubject, ['response' => $response])
);
if (!$result->isValid()) {
$this->processErrors($result);
}
}
}
if ($this->handler) {
$this->handler->handle(
$commandSubject,
$response
);
}
if ($this->session->getFetchNotificationResponse()) {
$this->session->unsFetchNotificationResponse();
}
return $response;
}
/**
* Tries to map error messages from validation result and logs processed message.
* Throws an exception with mapped message or default error.
*
* @param ResultInterface $result
* @return void
* @throws CommandException
*/
private function processErrors(ResultInterface $result)
{
$messages = [];
$errorCodeOrMessage = null;
$errorsSource = array_merge($result->getErrorCodes(), $result->getFailsDescription());
foreach ($errorsSource as $errorCodeOrMessage) {
$errorCodeOrMessage = (string) $errorCodeOrMessage;
// error messages mapper can be not configured if payment method doesn't have custom error messages.
if ($this->errorMessageMapper !== null) {
$mapped = (string) $this->errorMessageMapper->getMessage($errorCodeOrMessage);
if (!empty($mapped)) {
$messages[] = $mapped;
$errorCodeOrMessage = $mapped;
}
}
$this->logger->critical('Payment Error: ' . $errorCodeOrMessage);
}
$exceptionMessage = $errorCodeOrMessage ?: 'Transaction declined. Try again later.';
throw new CommandException(
!empty($messages)
? __(implode(PHP_EOL, $messages))
: __($exceptionMessage)
);
}
}
<?php
namespace Payoneer\OpenPaymentGateway\Gateway\Http\Authorization;
use Payoneer\OpenPaymentGateway\Gateway\Config\Config;
use Magento\Payment\Gateway\Data\PaymentDataObjectInterface;
use Payoneer\OpenPaymentGateway\Gateway\Http\TransferFactory;
/**
* Class CancellationTransferFactory
*
* Builds authorization cancellation transfer object
*/
class CancellationTransferFactory extends TransferFactory
{
/**
* @inheritDoc
*/
protected function getApiUri(PaymentDataObjectInterface $payment)
{
$longId = $payment->getPayment()->getAdditionalInformation('longId');
return sprintf(
Config::AUTHORIZATION_CANCEL_END_POINT,
$longId
);
}
/**
* @inheritDoc
*/
protected function getMethod()
{
return Config::METHOD_DELETE;
}
}
<?php
namespace Payoneer\OpenPaymentGateway\Gateway\Http\Client;
use Magento\Framework\DataObject;
use Magento\Payment\Gateway\Http\ClientInterface;
use Magento\Payment\Gateway\Http\TransferInterface;
use Payoneer\OpenPaymentGateway\Gateway\Config\Config;
use Payoneer\OpenPaymentGateway\Model\Api\Request;
use Payoneer\OpenPaymentGateway\Model\Method\Logger;
/**
* Class Client
* Payoneer client for transactions
*/
class Client implements ClientInterface
{
const AUTHORIZE = 'authorize';
const LIST = 'list';
const CAPTURE = 'authorize_capture';
const AUTHORIZATION_CANCEL = 'authorize_cancel';
const REFUND = 'refund';
const VOID = 'void';
const LIST_FETCH = 'list_fetch';
const LIST_CAPTURE = 'list_capture';
const LIST_UPDATE = 'list_update';
const LIST_DELETE = 'list_delete';
const PREAUTH_CANCEL = 'preauth_cancel';
/**
* @var Logger
*/
protected $logger;
/**
* @var Request
*/
protected $request;
/**
* @var Config
*/
protected $config;
/**
* @var string
*/
protected $operation;
/**
* Mandatory request fields
* @var string[]
*/
protected $mandatoryFields = [
'transactionId',
'country',
'customer',
'payment',
'callback'
];
/**
* Mandatory request fields for 'payment' object
* @var string[]
*/
protected $mandatoryFieldsPayment = [
'amount',
'currency',
'reference',
'invoiceId'
];
/**
* Mandatory request fields for 'customer' object
* @var string[]
*/
protected $mandatoryFieldsCustomer = [
'number'
];
/**
* @var array <mixed> | string
*/
protected $requestData;
/**
* Client construct
*
* @param Logger $logger
* @param Request $request
* @param Config $config
* @param string $operation
* @return void
*/
public function __construct(
Logger $logger,
Request $request,
Config $config,
$operation
) {
$this->logger = $logger;
$this->request = $request;
$this->config = $config;
$this->operation = $operation;
}
/**
* @param TransferInterface $transferObject
* @return array|DataObject
* @return array <mixed>
*/
public function placeRequest(TransferInterface $transferObject)
{
$response = [];
$responseObj = null;
$this->requestData = $transferObject->getBody();
$this->logData(['operation' => $this->operation]);
switch ($this->operation) {
case self::LIST:
case self::LIST_UPDATE:
$isRequestValid = $this->validateRequest();
if ($isRequestValid) {
$responseObj = $this->processRequest($transferObject);
} else {
$this->logData(['request' => $this->requestData]);
}
break;
case self::AUTHORIZE:
case self::CAPTURE:
$responseObj = $this->processAuthRequest($transferObject);
break;
case self::REFUND:
case self::AUTHORIZATION_CANCEL:
case self::LIST_CAPTURE:
case self::LIST_FETCH:
case self::LIST_DELETE:
$responseObj = $this->processRequest($transferObject);
break;
default:
throw new \InvalidArgumentException(sprintf('Unknown operation [%s]', $this->operation));
}
if ($responseObj instanceof DataObject) {
$response['response'] = $responseObj->getData('response') ?: '';
$response['status'] = $responseObj->getData('status') ?: '';
$response['reason'] = $responseObj->getData('reason') ?: '';
}
$this->logData($response);
return $response;
}
/**
* @param TransferInterface $transferObject
* @return DataObject
*/
protected function processAuthRequest($transferObject)
{
$responseObject = new \Magento\Framework\DataObject();
$responseObject->setData('response', $this->getResponseData($transferObject));
return $responseObject;
}
/**
* @param TransferInterface $transfer
* @return array|mixed
*/
private function getResponseData(TransferInterface $transfer)
{
$headers = $transfer->getHeaders();
if (isset($headers[Config::TXN_ID])) {
return [Config::TXN_ID => $headers[Config::TXN_ID]];
}
return [];
}
/**
* Validate payoneer request data
*
* @return bool
*/
public function validateRequest()
{
$isValid = true;
foreach ($this->mandatoryFields as $mandatoryField) {
switch ($mandatoryField) {
case 'payment':
$isValid = $this->mandatoryFieldsExists($this->mandatoryFieldsPayment, 'payment');
break;
case 'customer':
$isValid = $this->mandatoryFieldsExists($this->mandatoryFieldsCustomer, 'customer');
break;
default:
if (is_array($this->requestData) && !isset($this->requestData[$mandatoryField]) ||
(is_array($this->requestData)
&& isset($this->requestData[$mandatoryField])
&& $this->requestData[$mandatoryField] == '')) {
$this->logData([$mandatoryField . ' must not be empty']);
return false;
}
}
if (!$isValid) {
return false;
}
}
return $isValid;
}
/**
* Check if mandatory fields exists
*
* @param array <mixed> $mandatoryFields
* @param string $objectName
* @return bool
*/
public function mandatoryFieldsExists($mandatoryFields, $objectName)
{
foreach ($mandatoryFields as $mandatoryField) {
if (is_array($this->requestData) && !isset($this->requestData[$objectName][$mandatoryField])) {
$this->logData([$objectName . '.' . $mandatoryField . ' must not be empty']);
return false;
}
}
return true;
}
/**
* Log data to payoneer.log
* @param array <mixed> $result
* @return void
*/
public function logData($result)
{
if ((bool)$this->config->getValue('debug') == true) {
$this->logger->debug([$result]);
}
}
/**
* Process the api request.
*
* @param TransferInterface $transferObject
* @return DataObject <mixed> | DataObject
*/
public function processRequest($transferObject)
{
$credentials = [];
$credentials['merchantCode'] = $transferObject->getAuthUsername();
$credentials['apiKey'] = $transferObject->getAuthPassword();
$clientConfigs = $transferObject->getClientConfig();
$credentials['hostName'] = $clientConfigs['host_name'];
$data = $transferObject->getBody();
if ((bool)$this->config->getValue('debug') == true) {
$this->logger->debug(['request' => $data]);
}
return $this->request->send(
$transferObject->getMethod(),
$transferObject->getUri(),
$credentials,
$data
);
}
}
<?php
namespace Payoneer\OpenPaymentGateway\Gateway\Http;
use Magento\Payment\Gateway\Data\PaymentDataObjectInterface;
use Payoneer\OpenPaymentGateway\Gateway\Config\Config;
/**
* Class ListCaptureTransferFactory
*
* Builds gateway transfer object
*/
class ListCaptureTransferFactory extends TransferFactory
{
/**
* @inheritDoc
*/
protected function getApiUri(PaymentDataObjectInterface $payment)
{
$additionalInformation = $payment->getPayment()->getAdditionalInformation();
$longId = $additionalInformation['longId'];
return sprintf(
Config::CAPTURE_END_POINT,
$longId
);
}
}
<?php
namespace Payoneer\OpenPaymentGateway\Gateway\Http;
use Magento\Payment\Gateway\Data\PaymentDataObjectInterface;
use Payoneer\OpenPaymentGateway\Gateway\Config\Config;
/**
* Class ListFetchTransferFactory
*
* Builds gateway transfer object
*/
class ListFetchTransferFactory extends TransferFactory
{
/**
* @inheritDoc
*/
protected function getApiUri(PaymentDataObjectInterface $payment)
{
$additionalInformation = $payment->getPayment()->getAdditionalInformation();
$longId = $additionalInformation['longId'];
return 'api/charges/' . $longId;
}
/**
* Return the method
*
* @return string
*/
protected function getMethod()
{
return Config::METHOD_GET;
}
}
<?php
namespace Payoneer\OpenPaymentGateway\Gateway\Http;
use Magento\Payment\Gateway\Http\TransferBuilder;
use Magento\Payment\Gateway\Http\TransferFactoryInterface;
use Magento\Payment\Gateway\Http\TransferInterface;
use Payoneer\OpenPaymentGateway\Gateway\Config\Config;
/**
* Class MagentoTransferFactory
*
* Builds gateway transfer object
*/
class MagentoTransferFactory implements TransferFactoryInterface
{
/**
* @var TransferBuilder
*/
protected $transferBuilder;
/**
* @var Config
*/
protected $config;
/**
* @param TransferBuilder $transferBuilder
* @param Config $config
*/
public function __construct(
TransferBuilder $transferBuilder,
Config $config
) {
$this->transferBuilder = $transferBuilder;
$this->config = $config;
}
/**
* Builds gateway transfer object
*
* @param array <mixed> $request
* @return TransferInterface
*/
public function create(array $request)
{
return $this->transferBuilder
->setBody($request)
->setMethod(Config::METHOD_POST)
->setHeaders(
[
Config::TXN_ID => $request[Config::TXN_ID]
]
)
->build();
}
}
<?php
namespace Payoneer\OpenPaymentGateway\Gateway\Http;
use Magento\Payment\Gateway\Data\PaymentDataObjectInterface;
use Payoneer\OpenPaymentGateway\Gateway\Config\Config;
/**
* Class RefundTransferFactory
*
* Builds refund transfer object
*/
class RefundTransferFactory extends TransferFactory
{
/**
* @inheritDoc
*/
protected function getApiUri(PaymentDataObjectInterface $payment)
{
$payment = $payment->getPayment();
$captureResponse = $payment->getAdditionalInformation('capture_response');
if ($captureResponse) {
$longId = isset($captureResponse['longId']) ? $captureResponse['longId'] : null;
} else {
$longId = $payment->getAdditionalInformation('longId');
}
return sprintf(
Config::REFUND_END_POINT,
$longId
);
}
}
<?php
namespace Payoneer\OpenPaymentGateway\Gateway\Http;
use Magento\Payment\Gateway\Data\PaymentDataObjectInterface;
use Magento\Payment\Gateway\Http\TransferBuilder;
use Magento\Payment\Gateway\Http\TransferInterface;
use Payoneer\OpenPaymentGateway\Gateway\Config\Config;
/**
* Class TransferFactory
*
* Builds gateway transfer object
*/
class TransferFactory implements TransferFactoryInterface
{
/**
* @var TransferBuilder
*/
protected $transferBuilder;
/**
* @var Config
*/
protected $config;
/**
* @var string
*/
protected $method;
/**
* @param TransferBuilder $transferBuilder
* @param Config $config
* @param string $method
*/
public function __construct(
TransferBuilder $transferBuilder,
Config $config,
$method
) {
$this->transferBuilder = $transferBuilder;
$this->config = $config;
$this->method = $method;
}
/**
* Builds gateway transfer object
*
* @param array <mixed> $request
* @param PaymentDataObjectInterface $payment
* @return TransferInterface
*/
public function create(array $request, PaymentDataObjectInterface $payment)
{
$merchantCode = $this->config->getValue('merchant_gateway_key');
$apiKey = $this->config->getCredentials('api_key');
$hostName = $this->config->getCredentials('host_name');
return $this->transferBuilder
->setBody($request)
->setAuthUsername($merchantCode)
->setAuthPassword($apiKey)
->setMethod($this->getMethod())
->setUri($this->getApiUri($payment))
->setHeaders(
$this->config->prepareHeaders($merchantCode, $apiKey)
)->setClientConfig(['host_name' => $hostName])
->build();
}
/**
* Return the api uri
*
* @param PaymentDataObjectInterface $payment
* @return string
*/
protected function getApiUri(PaymentDataObjectInterface $payment)
{
if ($this->method == Config::METHOD_POST) {
return Config::LIST_END_POINT;
} else {
$additionalInformation = $payment->getPayment()->getAdditionalInformation();
$listId = isset($additionalInformation['listId']) ? $additionalInformation['listId'] : null;
return sprintf(
Config::LIST_UPDATE_END_POINT,
$listId
);
}
}
/**
* Return the method
*
* @return string
*/
protected function getMethod()
{
return $this->method;
}
}
<?php
namespace Payoneer\OpenPaymentGateway\Gateway\Http;
use Magento\Payment\Gateway\Data\PaymentDataObjectInterface;
use Magento\Payment\Gateway\Http\TransferInterface;
interface TransferFactoryInterface
{
/**
* Build gateway transfer object
*
* @param array <mixed> $request
* @param PaymentDataObjectInterface $payment
*
* @return TransferInterface
*/
public function create(array $request, PaymentDataObjectInterface $payment);
}
<?php
namespace Payoneer\OpenPaymentGateway\Gateway;
use Magento\Payment\Gateway\Data\Quote\AddressAdapterFactory;
use Magento\Quote\Api\Data\CartInterface;
use Magento\Quote\Api\Data\CartItemInterface;
use Magento\Quote\Model\Quote;
use Magento\Quote\Model\Quote\Address;
use Magento\Payment\Gateway\Data\Quote\QuoteAdapter as MagentoQuoteAdapter;
/**
* Class QuoteAdapter
* Gets the details from quote
*/
class QuoteAdapter extends MagentoQuoteAdapter
{
/** @var Quote */
protected $quote;
/**
* QuoteAdapter constructor.
* @param CartInterface $quote
* @param AddressAdapterFactory $addressAdapterFactory
*/
public function __construct(CartInterface $quote, AddressAdapterFactory $addressAdapterFactory)
{
parent::__construct($quote, $addressAdapterFactory);
$this->quote = $quote;/** @phpstan-ignore-line */
}
/**
* Get remote ip
* @return string|null
*/
public function getRemoteIp()
{
return $this->quote->getRemoteIp();
}
/**
* Get shipping amount
* @return float
*/
public function getShippingAmount()
{
return $this->getAddressModel()->getBaseShippingAmount();
}
/**
* Get tax amount
* @return float
*/
public function getTaxAmount()
{
return $this->getAddressModel()->getTaxAmount();
}
/**
* Get shipping amount inclusive tax
* @return float
*/
public function getShippingAmountInclTax()
{
return $this->getAddressModel()->getBaseShippingInclTax();
}
/**
* Get discount amount
* @return float
*/
public function getDiscountAmount()
{
return $this->getAddressModel()->getBaseDiscountAmount();
}
/**
* @return Address
*/
protected function getAddressModel()
{
return $this->quote->isVirtual() ? $this->quote->getBillingAddress() : $this->quote->getShippingAddress();
}
/**
* Get quote items
* @return array|CartItemInterface[]|null
*/
public function getItems()
{
$items = parent::getItems();
if (!$items) {
$items = $this->quote->getAllItems();
}
return $items;
}
}
<?php
namespace Payoneer\OpenPaymentGateway\Gateway\Request;
use Magento\Checkout\Model\Session;
use Magento\Payment\Gateway\Data\AddressAdapterInterface;
use Magento\Payment\Gateway\Helper\SubjectReader;
use Magento\Payment\Gateway\Request\BuilderInterface;
use Payoneer\OpenPaymentGateway\Gateway\Config\Config;
/**
* Class AddressDataBuilder
* Class to build address data
*/
class AddressDataBuilder implements BuilderInterface
{
/**
* Billing address data constants
*/
const FIRST_NAME = 'firstname';
const LAST_NAME = 'lastname';
const MIDDLE_NAME = 'middlename';
const EMPTY_STRING = '';
const SHIPPING = 'shipping';
const BILLING = 'billing';
/**
* @var Session
*/
private $checkoutSession;
/**
* @var Config
*/
private $config;
/**
* @param Session $checkoutSession
* @param Config $config
*/
public function __construct(
Session $checkoutSession,
Config $config
) {
$this->checkoutSession = $checkoutSession;
$this->config = $config;
}
/**
* Builds address data
*
* @param array <mixed> $buildSubject
* @return array <mixed>
*/
public function build(array $buildSubject)
{
$payment = SubjectReader::readPayment($buildSubject);
$order = $payment->getOrder();
$billingAddress = $order->getBillingAddress();
$shippingAddress = $order->getShippingAddress();
$billingAddressChanged = false;
$address = isset($buildSubject['address']) ? $buildSubject['address'] : null;
if ($address) {
$billingAddress = $address;
$billingAddressChanged = true;
}
$shippingAddressCountryId = $shippingAddress ? $shippingAddress->getCountryId() : null;
if ($shippingAddressCountryId) {
$this->checkoutSession->setShippingCountryId($shippingAddressCountryId);
}
return [
Config::CUSTOMER => [
Config::ADDRESSES => [
Config::SHIPPING => $shippingAddress ? $this->getAddressData($shippingAddress, self::SHIPPING) : [],
Config::BILLING => $billingAddressChanged ?
$this->getNewBillingAddress($billingAddress) :
$this->getAddressData($billingAddress, self::BILLING)
]
]
];
}
/**
* Gets address details
*
* @param AddressAdapterInterface $address
* @param string $type
* @return array <mixed>
*/
public function getAddressData($address, $type)
{
return [
Config::STREET => $address->getStreetLine1() ?: null,
Config::HOUSE_NUMBER => $address->getStreetLine2(),
Config::ZIP => $address->getPostcode(),
Config::CITY => $address->getCity(),
Config::STATE => $address->getRegionCode(),
Config::COUNTRY => $this->getCountryId($address, $type),
Config::NAME => [
Config::FIRST_NAME => $address->getFirstname(),
Config::MIDDLE_NAME => $address->getMiddlename(),
Config::LAST_NAME => $address->getLastname()
]
];
}
/**
* @param AddressAdapterInterface $address
* @param string $type
* @return string
*/
public function getCountryId($address, $type)
{
$countryId = $address->getCountryId();
if (!$countryId) {
switch ($type) {
case self::SHIPPING:
$countryId = $this->checkoutSession->getShippingCountryId() ?: $this->config->getCountryByStore();
break;
case self::BILLING:
$countryId = $this->checkoutSession->getBillingCountryId() ?: $this->config->getCountryByStore();
break;
}
}
return $countryId;
}
/**
* Build new billing address data
* @param array <mixed> $billingAddress
* @return array <mixed>
*/
public function getNewBillingAddress($billingAddress)
{
$billingAddressCountryId = isset($billingAddress[Config::COUNTRY_ID]) ?
$billingAddress[Config::COUNTRY_ID] : $this->checkoutSession->getBillingCountryId();
return [
Config::STREET => isset($billingAddress[Config::STREET][0]) ?
$billingAddress[Config::STREET][0] : self::EMPTY_STRING,
Config::HOUSE_NUMBER => isset($billingAddress[Config::STREET][1]) ?
$billingAddress[Config::STREET][1] : self::EMPTY_STRING,
Config::ZIP => isset($billingAddress[Config::POSTCODE]) ?
$billingAddress[Config::POSTCODE] : self::EMPTY_STRING,
Config::CITY => isset($billingAddress[Config::CITY]) ?
$billingAddress[Config::CITY] : self::EMPTY_STRING,
Config::STATE => isset($billingAddress[Config::REGION]) ?
$billingAddress[Config::REGION] : self::EMPTY_STRING,
Config::COUNTRY => $billingAddressCountryId ?: $this->config->getCountryByStore(),
Config::NAME => [
Config::FIRST_NAME => isset($billingAddress[self::FIRST_NAME]) ?
$billingAddress[self::FIRST_NAME] : self::EMPTY_STRING,
Config::MIDDLE_NAME => isset($billingAddress[self::MIDDLE_NAME]) ?
$billingAddress[self::MIDDLE_NAME] : self::EMPTY_STRING,
Config::LAST_NAME => isset($billingAddress[self::LAST_NAME]) ?
$billingAddress[self::LAST_NAME] : self::EMPTY_STRING
]
];
}
}
<?php
namespace Payoneer\OpenPaymentGateway\Gateway\Request;
use Magento\Payment\Gateway\Helper\SubjectReader;
use Magento\Payment\Gateway\Request\BuilderInterface;
use Payoneer\OpenPaymentGateway\Gateway\Config\Config;
/**
* Class AdminTransactionIDDataBuilder
* Builds transaction request
*/
class AdminTransactionIDDataBuilder implements BuilderInterface
{
/**
* Builds transaction id
*
* @param array <mixed> $buildSubject
* @return array <mixed>
*/
public function build(array $buildSubject)
{
$payment = SubjectReader::readPayment($buildSubject);
return [
Config::TRANSACTION_ID => $payment->getOrder()->getId() . strtotime('now')
];
}
}
<?php
namespace Payoneer\OpenPaymentGateway\Gateway\Request;
use Magento\Framework\App\RequestInterface as Request;
use Magento\Framework\Module\ModuleListInterface;
use Magento\Payment\Gateway\Data\PaymentDataObjectInterface;
use Magento\Payment\Gateway\Helper\SubjectReader;
use Magento\Payment\Gateway\Request\BuilderInterface;
use Payoneer\OpenPaymentGateway\Gateway\Config\Config;
use Payoneer\OpenPaymentGateway\Model\Adminhtml\Source\Fields;
/**
* Class BaseRequestDataBuilder
* Builds base request data
*/
class BaseRequestDataBuilder implements BuilderInterface
{
/**
* @var Config
*/
private $config;
/**
* @var Request
*/
private $request;
/**
* @var ModuleListInterface
*/
private $moduleList;
/**
* @param Config $config
* @param Request $request
*/
public function __construct(
Config $config,
Request $request,
ModuleListInterface $moduleList
) {
$this->config = $config;
$this->request = $request;
$this->moduleList = $moduleList;
}
/**
* Builds base request data
*
* @param array <mixed> $buildSubject
* @return array <mixed>
*/
public function build(array $buildSubject)
{
$payment = SubjectReader::readPayment($buildSubject);
return [
Config::TRANSACTION_ID => $payment->getPayment()->getAdditionalInformation(Config::TXN_ID),
Config::COUNTRY => $this->getCountryId($payment),
Config::INTEGRATION => $this->getPaymentFlow(),
Config::DIVISION => $this->config->getValue('environment') == Fields::ENVIRONMENT_SANDBOX_VALUE
? $this->config->getValue('sandbox_store_code')
: $this->config->getValue('live_store_code'),
Config::ALLOW_DELETE => true,
//system attributes
"system" => [
"type" => "SHOP_PLATFORM",
"code" => "MAGENTO",
"version" => $this->moduleList->getOne('Payoneer_OpenPaymentGateway')['setup_version']
]
];
}
/**
* @param PaymentDataObjectInterface $payment
* @return string
*/
private function getCountryId($payment)
{
$order = $payment->getOrder();
//use country of shipping address if it exists, else billing address or store country
$shippingAddress = $order->getShippingAddress();
if (isset($shippingAddress) && $shippingAddress->getCountryId()) {
$countryId = $shippingAddress->getCountryId();
} else {
$billingAddress = $order->getBillingAddress();
if (isset($billingAddress) && $billingAddress->getCountryId()) {
$countryId = $billingAddress->getCountryId();
} else {
$countryId = $this->config->getCountryByStore();
}
}
return $countryId;
}
/**
* Build payment flow from request
*
* @return string
*/
private function getPaymentFlow()
{
$integration = $this->request->getParam(Config::INTEGRATION);
if ($integration == Config::INTEGRATION_HOSTED) {
return Config::HOSTED;
}
if ($integration == Config::INTEGRATION_EMBEDDED) {
return Config::SELECT_NATIVE;
}
return $this->config->getValue(Config::PAYMENT_FLOW);
}
}
<?php
namespace Payoneer\OpenPaymentGateway\Gateway\Request;
use Magento\Checkout\Model\Session;
use Magento\Framework\UrlInterface;
use Magento\Payment\Gateway\Helper\SubjectReader;
use Magento\Payment\Gateway\Request\BuilderInterface;
use Payoneer\OpenPaymentGateway\Gateway\Config\Config;
/**
* Class CallBackBuilder
* Builds Callback array
*/
class CallBackDataBuilder implements BuilderInterface
{
/**
* @var UrlInterface
*/
private $urlBuilder;
/**
* @var Session
*/
private $checkoutSession;
/**
* @var Config
*/
protected $config;
/**
* CallBackBuilder constructor.
* @param UrlInterface $urlBuilder
* @param Session $checkoutSession
* @param Config $config
*/
public function __construct(
UrlInterface $urlBuilder,
Session $checkoutSession,
Config $config
) {
$this->urlBuilder = $urlBuilder;
$this->checkoutSession = $checkoutSession;
$this->config = $config;
}
/**
* Builds callback data
*
* @param array <mixed> $buildSubject
* @return array <mixed>
*/
public function build(array $buildSubject)
{
$payment = SubjectReader::readPayment($buildSubject);
$token = $payment->getPayment()->getAdditionalInformation(Config::TOKEN);
$notificationToken = $payment->getPayment()->getAdditionalInformation(Config::TOKEN_NOTIFICATION);
$orderId = $payment->getOrder()->getOrderIncrementId();
$cartId = $this->getQuoteIdFromSession();
$successParams = ['cart_id' => $cartId, 'token' => $token];
$cancelParams = ['cart_id' => $cartId, 'error' => true];
return [
Config::CALLBACK => [
Config::RETURN_URL => $this->urlBuilder->getUrl(Config::RETURN_URL_PATH, $successParams),
Config::CANCEL_URL => $this->urlBuilder->getUrl(Config::CANCEL_URL_PATH, $cancelParams),
Config::NOTIFICATION_URL => $this->getNotificationUrl($orderId, $notificationToken)
]
];
}
/**
* @param string $orderId
* @param mixed $token
* @return string
*/
public function getNotificationUrl($orderId, $token)
{
$configUrl = $this->config->getValue('notification_url');
if ($configUrl) {
$configUrl = $configUrl . '/order_id/' . $orderId . '/token/' . $token;
} else {
$configUrl = $this->urlBuilder->getUrl(
Config::NOTIFICATION_URL_PATH,
['order_id' => $orderId, 'token' => $token]
);
}
return $configUrl;
}
/**
* Gets quote id from the checkout session
* @return int|null
*/
public function getQuoteIdFromSession()
{
$quoteId = null;
if ($this->checkoutSession->hasQuote()) {
$quoteId = $this->checkoutSession->getQuoteId();
}
return $quoteId;
}
}
<?php
namespace Payoneer\OpenPaymentGateway\Gateway\Request;
use Magento\Checkout\Model\Session;
use Magento\Payment\Gateway\Helper\SubjectReader;
use Magento\Payment\Gateway\Request\BuilderInterface;
use Payoneer\OpenPaymentGateway\Gateway\Config\Config;
use Payoneer\OpenPaymentGateway\Model\Helper;
/**
* Class CustomerDataBuilder
* Builds customer data
*/
class CustomerDataBuilder implements BuilderInterface
{
/**
* @var Helper
*/
private $helper;
/**
* @var Session
*/
private $checkoutSession;
/**
* @param Helper $helper
* @param Session $checkoutSession
*/
public function __construct(
Helper $helper,
Session $checkoutSession
) {
$this->helper = $helper;
$this->checkoutSession = $checkoutSession;
}
/**
* Builds customer data
*
* @param array <mixed> $buildSubject
* @return array <mixed>
*/
public function build(array $buildSubject)
{
$payment = SubjectReader::readPayment($buildSubject);
$order = $payment->getOrder();
$billingAddress = $order->getBillingAddress();
$registrationId = null;
$number = null;
$customerId = $order->getCustomerId();
if ($customerId) {
$registrationId = $this->helper->getRegistrationId($customerId);
$number = $customerId;
} else {
$number = $billingAddress ? $billingAddress->getTelephone() : null;
}
$customerEmail = $billingAddress ? $billingAddress->getEmail() : null;
if (!$customerEmail) {
$customerEmail = $this->checkoutSession->getPayoneerCustomerEmail();
}
$customerData = [
Config::CUSTOMER => [
Config::NUMBER => $number,
Config::EMAIL => $customerEmail,
Config::COMPANY => [
Config::NAME => $billingAddress ? $billingAddress->getCompany() : null,
],
Config::NAME => [
Config::FIRST_NAME => $billingAddress ? $billingAddress->getFirstname() : null,
Config::MIDDLE_NAME => $billingAddress ? $billingAddress->getMiddlename() : null,
Config::LAST_NAME => $billingAddress ? $billingAddress->getLastname() : null
]
]
];
if ($registrationId) {
$customerData[Config::CUSTOMER][Config::REGISTRATION] = [
Config::ID => $registrationId
];
}
return $customerData;
}
}
<?php
namespace Payoneer\OpenPaymentGateway\Gateway\Request;
use Magento\Payment\Gateway\Data\OrderAdapterInterface;
use Magento\Payment\Gateway\Helper\SubjectReader;
use Magento\Payment\Gateway\Request\BuilderInterface;
use Magento\Sales\Model\Order\Item;
use Payoneer\OpenPaymentGateway\Gateway\Config\Config;
use Payoneer\OpenPaymentGateway\Gateway\QuoteAdapter as PayoneerQuoteAdapter;
use Payoneer\OpenPaymentGateway\Model\Helper;
/**
* Class ItemsDataBuilder
* Build Item Data
*/
class ItemsDataBuilder implements BuilderInterface
{
const ADJUSTMENTS = 'Total Adjustments';
/**
* @var Helper
*/
private $helper;
/**
* @param Helper $helper
*/
public function __construct(
Helper $helper
) {
$this->helper = $helper;
}
/**
* Builds items data
*
* @param array <mixed> $buildSubject
* @return array <mixed>
*/
public function build(array $buildSubject)
{
$payment = SubjectReader::readPayment($buildSubject);
$order = $payment->getOrder();
$totalItemsCount = isset($buildSubject['totalItemsCount'])
? $buildSubject['totalItemsCount'] : 0;
if ($order->getItems() && $totalItemsCount > 0) {
$items = $this->buildItems($order);
return [
Config::PRODUCTS => $items
];
} else {
return [];
}
}
/**
* Build items
*
* @param OrderAdapterInterface $order
* @return array <mixed>
*/
protected function buildItems($order)
{
$result = [];
/** @var Item[] $items */
$items = $order->getItems();
foreach ($items as $item) {
$result[] = [
Config::SKU => $item->getSku(),
Config::NAME => $item->getName(),
Config::QUANTITY => $item->getData('qty'),
Config::CURRENCY => $order->getCurrencyCode(),
Config::AMOUNT => $this->helper->formatNumber($item->getBaseRowTotal()),
Config::NET_AMOUNT => $this->helper->formatNumber($item->getBaseRowTotal()),
Config::TAX_AMOUNT => $this->helper->formatNumber($item->getBaseTaxAmount()),
Config::TAX_PERCENT => $this->helper->formatNumber($item->getBaseRowTotalInclTax())
];
}
if ($order instanceof PayoneerQuoteAdapter) {
$totalAdjustments = 0.00;
if ($order->getShippingAmountInclTax() > 0) {
$totalAdjustments += $order->getShippingAmountInclTax();
}
if ($order->getDiscountAmount() < 0) {
$totalAdjustments += $order->getDiscountAmount();
}
if ($order->getTaxAmount() > 0) {
$totalAdjustments += $order->getTaxAmount();
}
$result[] = [
Config::NAME => self::ADJUSTMENTS,
Config::AMOUNT => number_format($totalAdjustments, 2)
];
}
return $result;
}
}
<?php
namespace Payoneer\OpenPaymentGateway\Gateway\Request;
use Magento\Payment\Gateway\Request\BuilderInterface;
use Magento\Payment\Gateway\Helper\SubjectReader;
use Payoneer\OpenPaymentGateway\Gateway\Config\Config;
/**
* Class PaymentDataBuilder
* Builds payment data
*/
class PaymentDataBuilder implements BuilderInterface
{
/**
* @var Config
*/
protected $config;
/**
* @param Config $config
*/
public function __construct(
Config $config
) {
$this->config = $config;
}
/**
* Builds payment data
*
* @param array <mixed> $buildSubject
* @return array <mixed>
*/
public function build(array $buildSubject)
{
$payment = SubjectReader::readPayment($buildSubject);
$order = $payment->getOrder();
return [
Config::PAYMENT => [
Config::AMOUNT => number_format($buildSubject[Config::AMOUNT], 2),
Config::CURRENCY => $order->getCurrencyCode(),
Config::REFERENCE => $this->config->getValue('order_reference_message'),
Config::INVOICE_ID => $order->getId()
]
];
}
}
<?php
namespace Payoneer\OpenPaymentGateway\Gateway\Request;
use Magento\Payment\Gateway\Request\BuilderInterface;
use Payoneer\OpenPaymentGateway\Gateway\Config\Config;
use Payoneer\OpenPaymentGateway\Model\Adminhtml\Source\Fields;
/**
* Class PreselectionBuilder
* Builds 'preselection' array
*/
class PreselectionBuilder implements BuilderInterface
{
/**
* Preference array constants
*/
const DEFERRED = 'DEFERRED';
const NON_DEFERRED = 'NON_DEFERRED';
/**
* @var Config
*/
protected $config;
/**
* PreselectionBuilder constructor.
* @param Config $config
*/
public function __construct(
Config $config
) {
$this->config = $config;
}
/**
* Builds preselection data
*
* @param array <mixed> $buildSubject
* @return array <mixed>
*/
public function build(array $buildSubject)
{
return [
Config::PRESELECTION => [
Config::DEFERRAL => $this->config->getValue('payment_action') == Fields::AUTHORIZE
? self::DEFERRED
: self::NON_DEFERRED
]
];
}
}
<?php
namespace Payoneer\OpenPaymentGateway\Gateway\Request;
use Magento\Framework\UrlInterface;
use Magento\Payment\Gateway\Helper\SubjectReader;
use Magento\Payment\Gateway\Request\BuilderInterface;
use Payoneer\OpenPaymentGateway\Gateway\Config\Config;
use Magento\Framework\App\RequestInterface as Request;
/**
* Class StyleDataBuilder
* Builds Style data array
*/
class StyleDataBuilder implements BuilderInterface
{
/**
* @var Config
*/
protected $config;
/**
* @var UrlInterface
*/
private $urlBuilder;
/**
* @var Request
*/
private $request;
/**
* @param UrlInterface $urlBuilder
* @param Config $config
* @param Request $request
*/
public function __construct(
UrlInterface $urlBuilder,
Config $config,
Request $request
) {
$this->urlBuilder = $urlBuilder;
$this->config = $config;
$this->request = $request;
}
/**
* Builds style data
*
* @param array <mixed> $buildSubject
* @return array <mixed>
*/
public function build(array $buildSubject)
{
$payment = SubjectReader::readPayment($buildSubject);
$styleData = [
Config::STYLE => [
Config::HOSTED_VERSION => Config::VERSION_V4,
Config::LANGUAGE => $this->config->getStoreLocale()
]
];
if ($this->isHostedIntegration()) {
return $styleData;
} else {
$styleDataValues = $this->config->getStyleConfig();
$styleData[Config::STYLE]['resolution'] = Config::RESOLUTION_1X;
if (isset($styleDataValues['background-color'])) {
$styleData[Config::STYLE]['primaryColor'] = $styleDataValues['background-color'];
}
$styleData[Config::STYLE]['cssOverride'] =
$this->urlBuilder->getUrl(Config::EMBEDDED_STYLE_PATH);
}
return $styleData;
}
/**
* @return bool
*/
private function isHostedIntegration()
{
$integration = $this->request->getParam(Config::INTEGRATION);
if ($integration == Config::INTEGRATION_HOSTED) {
return true;
}
if ($this->config->getValue(Config::PAYMENT_FLOW) == Config::HOSTED) {
return true;
}
return false;
}
}
<?php
namespace Payoneer\OpenPaymentGateway\Gateway\Request;
use Magento\Payment\Gateway\Helper\SubjectReader;
use Magento\Payment\Gateway\Request\BuilderInterface;
use Payoneer\OpenPaymentGateway\Gateway\Config\Config;
/**
* Class TransactionIDDataBuilder
* Builds magento transaction request
*/
class TransactionIDDataBuilder implements BuilderInterface
{
/**
* Builds transaction id
*
* @param array <mixed> $buildSubject
* @return array <mixed>
*/
public function build(array $buildSubject)
{
$payment = SubjectReader::readPayment($buildSubject);
return [
Config::TXN_ID => $payment->getPayment()->getAdditionalInformation(Config::TXN_ID)
];
}
}
<?php
namespace Payoneer\OpenPaymentGateway\Gateway\Response;
use Magento\Checkout\Model\Session;
use Magento\Framework\Exception\LocalizedException;
use Magento\Payment\Gateway\Helper\SubjectReader;
use Magento\Payment\Gateway\Response\HandlerInterface;
use Magento\Sales\Model\Order\Payment;
use Magento\Sales\Model\Order\Payment\Transaction;
/**
* Class PayoneerResponseHandler
*
* Payoneer gateway response handler
*/
class PayoneerResponseHandler implements HandlerInterface
{
const ADDITIONAL_INFO_KEY_REFUND_RESPONSE = 'refund_response';
const ADDITIONAL_INFO_KEY_PARTIAL_REFUND_RESPONSE = 'partial_refund_response';
const ADDITIONAL_INFO_KEY_CAPTURE_RESPONSE = 'capture_response';
const ADDITIONAL_INFO_KEY_AUTH_CANCEL_RESPONSE = 'auth_cancel_response';
const AUTH_CANCEL_STATUS_NODE = 'auth_cancel_status';
const AUTH_CAPTURE_STATUS_NODE = 'capture_status';
const REFUND_TXN_TYPE = 'refund';
/**
* @var SubjectReader
*/
private $subjectReader;
/**
* @var mixed|string
*/
private $additionalInfoKey;
/**
* @var mixed|string
*/
private $actionSuccessResponseKey;
/**
* @var mixed
*/
private $transactionType;
/**
* @var Session
*/
private $session;
/**
* PayoneerResponseHandler constructor.
*
* @param SubjectReader $subjectReader
* @param Session $checkoutSession
* @param string|mixed $additionalInfoKey
* @param string|mixed $actionSuccessResponseKey
* @param string $transactionType
*/
public function __construct(
SubjectReader $subjectReader,
Session $checkoutSession,
$additionalInfoKey = '',
$actionSuccessResponseKey = '',
$transactionType = ''
) {
$this->subjectReader = $subjectReader;
$this->session = $checkoutSession;
$this->additionalInfoKey = $additionalInfoKey;
$this->actionSuccessResponseKey = $actionSuccessResponseKey;
$this->transactionType = $transactionType;
}
/**
* Handle the response.
*
* @param array <mixed> $handlingSubject
* @param array <mixed> $response
* @return void
* @throws LocalizedException
*/
public function handle(array $handlingSubject, array $response)
{
$paymentDO = $this->subjectReader->readPayment($handlingSubject);
/** @var Payment $orderPayment */
$orderPayment = $paymentDO->getPayment();
if ($this->session->getFetchNotificationResponse()) {
$additionalInfo = $this->session->getFetchNotificationResponse();
$longId = $additionalInfo['longId'];
$orderPayment->setTransactionId($longId . '- refund');
} else {
$additionalInfo = $this->buildAdditionalInfoDataFromResponse($response);
if ($this->transactionType == self::REFUND_TXN_TYPE) {
$longId = $response['response']['identification']['longId'];
$orderPayment->setTransactionId($longId . '- refund');
}
}
if ($this->additionalInfoKey == self::ADDITIONAL_INFO_KEY_REFUND_RESPONSE) {
$paymentAdditionalInfo = $orderPayment->getAdditionalInformation();
$refundResponse = isset($paymentAdditionalInfo[$this->additionalInfoKey]) ?
$paymentAdditionalInfo[$this->additionalInfoKey] : [];
$refundResponse[] = $additionalInfo;
$orderPayment->setAdditionalInformation(
$this->additionalInfoKey,
$refundResponse
);
} else {
$paymentAdditionalInfo = $orderPayment->getAdditionalInformation();
$mergedInfo = array_merge($paymentAdditionalInfo, $additionalInfo);
$orderPayment->setAdditionalInformation($mergedInfo);
}
$orderPayment->setTransactionAdditionalInfo(
Transaction::RAW_DETAILS,
$additionalInfo
);
}
/**
* Build the payment additional info data.
*
* @param array <mixed> $response
* @return array <mixed>
*/
public function buildAdditionalInfoDataFromResponse($response)
{
$additionalInfo = [];
if (isset($response['response'])) {
$additionalInfo = [
'resultinfo' => $response['response']['resultInfo'],
'returncode_name' => $response['response']['returnCode']['name'],
'returncode_source' => $response['response']['returnCode']['source'],
'status_code' => $response['response']['status']['code'],
'status_reason' => $response['response']['status']['reason'],
'interaction_code' => $response['response']['interaction']['code'],
'interaction_reason' => $response['response']['interaction']['reason'],
'longId' => $response['response']['identification']['longId'],
'shortId' => $response['response']['identification']['shortId'],
'transactionId' => $response['response']['identification']['transactionId'],
'amount' => $response['response']['payment']['amount']
];
}
if (!empty($this->actionSuccessResponseKey)) {
$additionalInfo[$this->actionSuccessResponseKey] = 'success';
}
return $additionalInfo;
}
}
<?php
namespace Payoneer\OpenPaymentGateway\Gateway\Response;
use Magento\Payment\Gateway\Response\HandlerInterface;
use Magento\Sales\Model\Order\Payment;
use Payoneer\OpenPaymentGateway\Gateway\Config\Config;
use Magento\Payment\Gateway\Helper\SubjectReader;
use Magento\Sales\Model\Order\Payment\Transaction;
/**
* Class ResponseHandler
* Payoneer Response Handler
*/
class ResponseHandler implements HandlerInterface
{
/**
* @var SubjectReader
*/
private $subjectReader;
/**
* ResponseHandler constructor.
* @param SubjectReader $subjectReader
*/
public function __construct(
SubjectReader $subjectReader
) {
$this->subjectReader = $subjectReader;
}
/**
* Handles response
*
* @param array <mixed> $handlingSubject
* @param array <mixed> $response
* @return void
*/
public function handle(array $handlingSubject, array $response)
{
$paymentDO = $this->subjectReader->readPayment($handlingSubject);
/** @var Payment $orderPayment */
$orderPayment = $paymentDO->getPayment();
$orderPayment->setTransactionId($response['response'][Config::TXN_ID]);
$orderPayment->setIsTransactionClosed(false);
$additionalInfo = $orderPayment->getAdditionalInformation();
$orderPayment->setTransactionAdditionalInfo(
Transaction::RAW_DETAILS,
$additionalInfo
);
}
}
<?php
namespace Payoneer\OpenPaymentGateway\Gateway\Validator;
use Magento\Payment\Gateway\Helper\SubjectReader;
use Magento\Payment\Gateway\Validator\AbstractValidator;
use Magento\Payment\Gateway\Validator\ResultInterface;
use Magento\Payment\Gateway\Validator\ResultInterfaceFactory;
/**
* Class ResponseValidator
* Payoneer Response Validator
*/
class ResponseValidator extends AbstractValidator
{
const REFUND_PAID_OUT_STATUS = 'paid_out';
const REFUND_PAID_OUT_PARTIAL = 'paid_out_partial';
const CAPTURE_STATUS = 'charged';
const REFUND_CREDITED = 'refund_credited';
const AUTH_CANCEL_PENDING_STATUS = 'pending';
const CANCELLATION_REQUESTED = 'cancelation_requested';
const AUTH_CANCELLED_STATUS = 'canceled';
const PREAUTHORIZATION_CANCELLED = 'preauthorization_canceled';
/**
* @var bool
*/
private $skipValidation;
/**
* @var mixed
*/
private $successStatusCode;
/**
* @param ResultInterfaceFactory $resultFactory
* @param bool $skipValidation
* @param mixed $successStatusCode
* @return void
*/
public function __construct(
ResultInterfaceFactory $resultFactory,
$skipValidation = false,
$successStatusCode = ''
) {
parent::__construct($resultFactory);
$this->skipValidation = $skipValidation;
$this->successStatusCode = $successStatusCode;
}
/**
* Performs domain-related validation for business object
*
* @param array <mixed> $validationSubject
* @return ResultInterface
*/
public function validate(array $validationSubject): ResultInterface
{
$response = SubjectReader::readResponse($validationSubject);
if ($this->skipValidation == true) {
return $this->createResult(true);
}
if ($response['status'] != 200) {
return $this->createResult(false, [$response['reason']]);
}
if (isset($response['response']['status']['code']) &&
$response['response']['status']['code'] != $this->successStatusCode
) {
return $this->createResult(false, [$response['response']['resultInfo']]);
}
return $this ->createResult(true);
}
}
<?php
namespace Payoneer\OpenPaymentGateway\Http;
use GuzzleHttp\Client;
use GuzzleHttp\ClientFactory;
use GuzzleHttp\Exception\GuzzleException;
use GuzzleHttp\Psr7\Response;
use GuzzleHttp\Psr7\ResponseFactory;
use Magento\Framework\Webapi\Rest\Request;
/**
* Class PayoneerClient to manage API client communication
*/
class PayoneerClient
{
/**
* @var ResponseFactory
*/
protected $responseFactory;
/**
* @var ClientFactory
*/
protected $clientFactory;
/**
* @var array <mixed>
*/
protected $handlers = [];
/**
* PayoneerClient constructor.
* @param ClientFactory $clientFactory
* @param ResponseFactory $responseFactory
*/
public function __construct(
ClientFactory $clientFactory,
ResponseFactory $responseFactory
) {
$this->clientFactory = $clientFactory;
$this->responseFactory = $responseFactory;
}
/**
* @param int|string $method
* @param string $hostname
* @param string $endpoint
* @param array <mixed> $options
* @return mixed
*/
public function send(
$method,
$hostname,
$endpoint,
array $options = []
) {
$response = $this->doRequest($hostname, $endpoint, $options, $method);
$responseBody = $response->getBody();
$responseBody->rewind();
$responseObject = new \Magento\Framework\DataObject();
$responseObject->setData('status', $response->getStatusCode());
$responseObject->setData('reason', $response->getReasonPhrase());
$responseObject->setData('response', json_decode($responseBody->getContents(), true));
return $responseObject;
}
/**
* Do API request with provided params
*
* @param string $hostname
* @param string $endpoint
* @param array <mixed> $options
* @param string|int $requestMethod
* @return mixed
*/
private function doRequest(
$hostname,
$endpoint,
$options = [],
$requestMethod = Request::HTTP_METHOD_GET
) {
try {
$uriEndpoint = $hostname . $endpoint;
$client = $this->clientFactory->create(['config' => [
'base_uri' => $hostname
]]);
$response = $client->request(
(string)$requestMethod,
$uriEndpoint,
$options
);
} catch (GuzzleException $exception) {
$response = $this->responseFactory->create([
'status' => $exception->getCode(),
'reason' => $exception->getMessage()
]);
}
return $response;
}
}
<?php
namespace Payoneer\OpenPaymentGateway\Logger;
use Magento\Framework\Filesystem\DriverInterface;
use Magento\Framework\Logger\Handler\Base as BaseHandler;
/**
* Logger handler class for Payoneer
*/
class Handler extends BaseHandler
{
/**
* @var string
*/
protected $fileName;
/**
* Handler constructor.
* @param DriverInterface $filesystem
* @param string $fileName
* @param null $filePath
* @throws \Exception
*/
public function __construct(
DriverInterface $filesystem,
$fileName,
$filePath = null
) {
$this->fileName = $fileName;
parent::__construct($filesystem, $filePath);
}
}
<?php
namespace Payoneer\OpenPaymentGateway\Logger;
use Payoneer\OpenPaymentGateway\Model\Helper;
use Monolog\Handler\HandlerInterface;
use Monolog\Logger;
use Payoneer\OpenPaymentGateway\Gateway\Config\Config;
/**
* NotificationLogger class
* Log the notification related errors
*/
class NotificationLogger extends Logger
{
/**
* @var array <mixed>
*/
private $generalInfo = [];
/**
* @var Helper
*/
private $helper;
/**
* @var Config
*/
private $config;
/**
* NotificationLogger construct
*
* @param Helper $helper
* @param Config $config
* @param string $name The logging channel
* @param HandlerInterface[] $handlers Optional stack of handlers
* @param callable[] $processors Optional array of processors
* @return void
*/
public function __construct(
Helper $helper,
Config $config,
$name,
array $handlers = [],
array $processors = []
) {
parent::__construct($name, $handlers, $processors);
$this->helper = $helper;
$this->config = $config;
}
/**
* Adds a log record at the ERROR level.
*
* @param string $message The log message
* @param array <mixed> $context The log context
* @return bool Whether the record has been processed
*/
public function addError($message, array $context = [])
{
if (!$this->config->isDebuggingEnabled()) {
return true;
}
$this->prepareGeneralInfo();
$message = $this->addGeneralInfoToMessage($message);
return $this->addRecord(static::ERROR, $message, $context);
}
/**
* Prepare the general info data for logging.
*
* @return void
*/
private function prepareGeneralInfo()
{
if (empty($this->generalInfo)) {
$this->generalInfo = $this->helper->getProductMetaData();
}
}
/**
* Append the general info data before the message.
*
* @param string $message
* @return string
*/
private function addGeneralInfoToMessage($message)
{
$finalMessage = '[';
foreach ($this->generalInfo as $key => $value) {
$finalMessage .= $key . '=' . $value . '|';
}
$finalMessage .= ']' . $message;
return $finalMessage;
}
}
<?php
namespace Payoneer\OpenPaymentGateway\Model\Adminhtml\Source;
use Magento\Framework\Data\OptionSourceInterface;
/**
* Class Fields
* Admin config fields
*/
class Fields implements OptionSourceInterface
{
const ENVIRONMENT_PRODUCTION_LABEL = 'Live';
const ENVIRONMENT_PRODUCTION_VALUE = 'live';
const ENVIRONMENT_SANDBOX_LABEL = 'Test';
const ENVIRONMENT_SANDBOX_VALUE = 'test';
const HOSTED = 'HOSTED';
const SELECTIVE_NATIVE = 'SELECTIVE_NATIVE';
const AUTHORIZE = 'authorize';
const CAPTURE = 'authorize_capture';
const STANDALONE = 'Standalone';
const EMBEDDED = 'Embedded';
const DIRECT_PAYMENT = 'Direct payment';
const DEFERRED = 'Deferred';
const FONT_BOLD = 'bold';
const FONT_LIGHTER = 'lighter';
const FONT_NORMAL = 'normal';
const REGULAR = 'Regular';
const BOLD = 'Bold';
const LIGHTER = 'Lighter';
const LEFT = 'Left';
const RIGHT = 'Right';
const CENTER = 'Center';
const ALIGN_LEFT = 'left';
const ALIGN_RIGHT = 'right';
const ALIGN_CENTER = 'center';
/**
* Possible environment types
*
* @return array <mixed>
*/
public function toOptionArray(): array
{
return [
[
'value' => self::ENVIRONMENT_SANDBOX_VALUE,
'label' => self::ENVIRONMENT_SANDBOX_LABEL
],
[
'value' => self::ENVIRONMENT_PRODUCTION_VALUE,
'label' => self::ENVIRONMENT_PRODUCTION_LABEL
]
];
}
/**
* @return array <mixed>
*/
public function fontWeight(): array
{
return [
[
'value' => self::FONT_LIGHTER,
'label' => self::LIGHTER,
],
[
'value' => self::FONT_NORMAL,
'label' => self::REGULAR
],
[
'value' => self::FONT_BOLD,
'label' => self::BOLD
]
];
}
/**
* @return array <mixed>
*/
public function alignText(): array
{
return [
[
'value' => self::ALIGN_LEFT,
'label' => self::LEFT,
],
[
'value' => self::ALIGN_RIGHT,
'label' => self::RIGHT
],
[
'value' => self::ALIGN_CENTER,
'label' => self::CENTER
]
];
}
/**
* @return array <mixed>
*/
public function paymentAction(): array
{
return [
[
'value' => self::AUTHORIZE,
'label' => self::DEFERRED
],
[
'value' => self::CAPTURE,
'label' => self::DIRECT_PAYMENT
]
];
}
/**
* @return array <mixed>
*/
public function paymentFlow(): array
{
return [
[
'value' => self::HOSTED,
'label' => self::STANDALONE
],
[
'value' => self::SELECTIVE_NATIVE,
'label' => self::EMBEDDED
]
];
}
}
<?php
namespace Payoneer\OpenPaymentGateway\Model\Adminhtml;
use Exception;
use Magento\Payment\Gateway\Command\CommandPoolInterface;
use Magento\Payment\Gateway\Command\ResultInterface;
use Magento\Payment\Gateway\Data\PaymentDataObjectFactory;
use Magento\Sales\Model\Order;
use Magento\Payment\Model\InfoInterface;
/**
* Class TransactionService
*
* Process admin transactions api requests
*/
class TransactionService
{
/**
* @var CommandPoolInterface
*/
protected $commandPool;
/**
* @var PaymentDataObjectFactory
*/
protected $paymentDataObjectFactory;
/**
* TransactionService constructor.
* @param CommandPoolInterface $commandPool
* @param PaymentDataObjectFactory $paymentDataObjectFactory
*/
public function __construct(
CommandPoolInterface $commandPool,
PaymentDataObjectFactory $paymentDataObjectFactory
) {
$this->commandPool = $commandPool;
$this->paymentDataObjectFactory = $paymentDataObjectFactory;
}
/**
* Process Api request
*
* @param Order $order
* @param string $command
* @return ResultInterface|null|bool|array <mixed>
*/
public function process(Order $order, $command)
{
$result = [];
/** @var InfoInterface $payment*/
$payment = $order->getPayment();
try {
$paymentDataObject = $this->paymentDataObjectFactory->create($payment);
/** @var array <mixed> $result */
$result = $this->commandPool->get($command)->execute([
'payment' => $paymentDataObject
]);
return $result;
} catch (Exception $e) {
return $result;
}
}
}
<?php
namespace Payoneer\OpenPaymentGateway\Model\Api;
use Magento\Framework\DataObject;
use Magento\Framework\Webapi\Rest\Request as WebRequest;
use Payoneer\OpenPaymentGateway\Gateway\Config\Config;
use Payoneer\OpenPaymentGateway\Http\PayoneerClient;
/**
* Class Request - Manage Payoneer API requests
*/
class Request
{
/**
* @var Config
*/
protected $config;
/**
* @var PayoneerClient
*/
protected $payoneerHttpClient;
/**
* Request constructor.
* @param Config $config
* @param PayoneerClient $payoneerHttpClient
*/
public function __construct(
Config $config,
PayoneerClient $payoneerHttpClient
) {
$this->config = $config;
$this->payoneerHttpClient = $payoneerHttpClient;
}
/**
* @param int|string $method
* @param string $endPoint
* @param array <mixed> $credentials
* @param array <mixed>|string $data
* @return DataObject
*/
public function send(
$method,
$endPoint,
$credentials,
$data
): DataObject {
$options = [];
if ($method == WebRequest::HTTP_METHOD_GET) {
$options['query'] = $data;
} else {
$options['json'] = $data;
}
$options['headers'] = $this->config->prepareHeaders($credentials['merchantCode'], $credentials['apiKey']);
return $this->payoneerHttpClient->send($method, $credentials['hostName'], $endPoint, $options);
}
}
<?php
namespace Payoneer\OpenPaymentGateway\Model\Api;
/**
* Class Response - Validate API response
*/
class Response
{
/**
* @var array<mixed>
*/
protected $responseCodes = [
'success' => ['200','201','204'],
'invalid_token' => ['401', '403']
];
/**
* @param string $key
* @return array<mixed>
*/
public function getResponseCode(string $key): array
{
return $this->responseCodes[$key];
}
/**
* @param mixed $response
* @return bool|string
*/
public function validateResponse($response)
{
return in_array($response->getStatus(), $this->getResponseCode('success'));
}
}
<?php
namespace Payoneer\OpenPaymentGateway\Model\Config\Source;
use Magento\Framework\Data\OptionSourceInterface;
class PaymentIconType implements OptionSourceInterface
{
const PAYMENT_ICON_STATIC = 'static';
const PAYMENT_ICON_DYNAMIC = 'dynamic';
const PAYMENT_ICON_BOTH = 'both';
/**
* Payment icon types
*
* @return array <mixed>
*/
public function toOptionArray(): array
{
return [
[
'value' => self::PAYMENT_ICON_STATIC,
'label' => __('Static')
],
[
'value' => self::PAYMENT_ICON_DYNAMIC,
'label' => __('Dynamic')
],
[
'value' => self::PAYMENT_ICON_BOTH,
'label' => __('Both')
]
];
}
}
<?php
namespace Payoneer\OpenPaymentGateway\Model\Creditmemo;
use Magento\Framework\Exception\LocalizedException;
use Magento\Sales\Api\InvoiceRepositoryInterface;
use Magento\Sales\Model\Order;
use Magento\Sales\Model\Order\CreditmemoFactory;
use Magento\Sales\Model\Service\CreditmemoService;
class CreditmemoCreator
{
/**
* @var CreditmemoFactory
*/
protected $creditmemoFactory;
/**
* @var CreditmemoService
*/
protected $creditmemoService;
/**
* @var InvoiceRepositoryInterface
*/
protected $invoiceRepository;
/**
* CreditmemoCreator constructor
*
* @param CreditmemoFactory $creditmemoFactory
* @param CreditmemoService $creditmemoService
* @param InvoiceRepositoryInterface $invoiceRepository
* @return void
*/
public function __construct(
CreditmemoFactory $creditmemoFactory,
CreditmemoService $creditmemoService,
InvoiceRepositoryInterface $invoiceRepository
) {
$this->creditmemoFactory = $creditmemoFactory;
$this->creditmemoService = $creditmemoService;
$this->invoiceRepository = $invoiceRepository;
}
/**
* Create creditmemo for full order.
*
* @param Order $order
* @return bool
* @throws LocalizedException
*/
public function create($order)
{
try {
$invoices = $order->getInvoiceCollection();
$invoiceId = 0;
foreach ($invoices as $invoice) {
$invoiceId = $invoice->getId();
}
$invoice = $this->invoiceRepository->get($invoiceId);
$creditmemo = $this->creditmemoFactory->createByOrder($order);
$creditmemo->setData('invoice', $invoice);
$this->creditmemoService->refund($creditmemo, true);
return true;
} catch (\Exception $e) {
throw new LocalizedException(
__(__('We couldn\'t create a credit memo for the %1 order. Try again later.') . $e->getMessage(), $order->getIncrementId())
);
}
}
}
<?php
namespace Payoneer\OpenPaymentGateway\Model;
use Exception;
use Magento\Framework\Exception\LocalizedException;
use Magento\Payment\Gateway\Command\CommandPoolInterface;
use Magento\Payment\Gateway\Command\ResultInterface;
use Magento\Payment\Gateway\Data\PaymentDataObjectFactory;
use Magento\Payment\Model\InfoInterface;
use Magento\Quote\Model\Quote\Payment;
/**
* Class ListUpdateTransactionService
*
* Process transactions api request for list update
*/
class ListUpdateTransactionService
{
/**
* @var CommandPoolInterface
*/
private $commandPool;
/**
* @var PaymentDataObjectFactory
*/
private $paymentDataObjectFactory;
/**
* ListUpdateTransactionService constructor.
*
* @param CommandPoolInterface $commandPool
* @param PaymentDataObjectFactory $paymentDataObjectFactory
*/
public function __construct(
CommandPoolInterface $commandPool,
PaymentDataObjectFactory $paymentDataObjectFactory
) {
$this->commandPool = $commandPool;
$this->paymentDataObjectFactory = $paymentDataObjectFactory;
}
/**
* Process Api request
*
* @param Payment $payment
* @param string $command
* @return ResultInterface|null|bool|array <mixed>
* @throws LocalizedException
*/
public function process(Payment $payment, $command)
{
try {
/** @var InfoInterface $payment*/
$paymentDataObject = $this->paymentDataObjectFactory->create($payment);
return $this->commandPool->get($command)->execute([
'payment' => $paymentDataObject,
'amount' => $payment->getQuote()->getGrandTotal(), /** @phpstan-ignore-line */
'totalItemsCount' => $payment->getQuote()->getItemsCount() /** @phpstan-ignore-line */
]);
} catch (Exception $e) {
throw new LocalizedException(__($e->getMessage()));
}
}
}
<?php
namespace Payoneer\OpenPaymentGateway\Model\Method;
use Magento\Payment\Gateway\ConfigInterface;
use Psr\Log\LoggerInterface;
use Magento\Framework\App\ProductMetadataInterface;
use Magento\Framework\Module\ModuleListInterface;
/**
* Class Logger for payment related information (request, response, etc.) which is used for debug.
*
* @api
* @since 100.0.2
*/
class Logger
{
const MODULE_NAME = 'Payoneer_OpenPaymentGateway';
const DEBUG_KEYS_MASK = '****';
/**
* @var LoggerInterface
*/
protected $logger;
/**
* @var ConfigInterface|null
*/
private $config;
/**
* @var ProductMetadataInterface
*/
protected $productMetadata;
/**
* @var ModuleListInterface
*/
protected $moduleList;
/**
* @param ProductMetadataInterface $productMetadata
* @param ModuleListInterface $moduleList
* @param LoggerInterface $logger
* @param ConfigInterface|null $config
*/
public function __construct(
ProductMetadataInterface $productMetadata,
ModuleListInterface $moduleList,
LoggerInterface $logger,
ConfigInterface $config = null
) {
$this->productMetadata = $productMetadata;
$this->moduleList = $moduleList;
$this->logger = $logger;
$this->config = $config;
}
/**
* Logs payment related information used for debug
*
* @param array <mixed> $data
* @param array <mixed>|null $maskKeys
* @param bool|null $forceDebug
* @return void
*/
public function debug(array $data, array $maskKeys = null, $forceDebug = null)
{
$data = array_merge($data, $this->getProductMetaData());
$maskKeys = $maskKeys !== null ? $maskKeys : $this->getDebugReplaceFields();
$debugOn = $forceDebug !== null ? $forceDebug : $this->isDebugOn();
if ($debugOn === true) {
$data = $this->filterDebugData(
$data,
$maskKeys
);
$this->logger->debug(var_export($data, true));
}
}
/**
* Returns configured keys to be replaced with mask
*
* @return array <mixed>
*/
private function getDebugReplaceFields()
{
if ($this->config && $this->config->getValue('debugReplaceKeys')) {
return explode(',', $this->config->getValue('debugReplaceKeys'));
}
return [];
}
/**
* Whether debug is enabled in configuration
*
* @return bool
*/
private function isDebugOn()
{
return $this->config && (bool)$this->config->getValue('debug');
}
/**
* Recursive filter data by private conventions
*
* @param array <mixed> $debugData
* @param array <mixed> $debugReplacePrivateDataKeys
* @return array <mixed>
*/
protected function filterDebugData(array $debugData, array $debugReplacePrivateDataKeys)
{
$debugReplacePrivateDataKeys = array_map('strtolower', $debugReplacePrivateDataKeys);
foreach (array_keys($debugData) as $key) {
if (in_array(strtolower($key), $debugReplacePrivateDataKeys)) {
$debugData[$key] = self::DEBUG_KEYS_MASK;
} elseif (is_array($debugData[$key])) {
$debugData[$key] = $this->filterDebugData($debugData[$key], $debugReplacePrivateDataKeys);
}
}
return $debugData;
}
/**
* Get Magento application product metadata
* @return array <mixed>
*/
public function getProductMetaData()
{
return [
'magentoVersion' => $this->productMetadata->getVersion(),
'magentoEdition' => $this->productMetadata->getEdition(),
'moduleVersion' => $this->getModuleVersion()
];
}
/**
* Find the installed module version
*
* @return mixed
*/
public function getModuleVersion()
{
$module = $this->moduleList->getOne(self::MODULE_NAME);
return $module ? $module ['setup_version'] : null;
}
}
<?php
namespace Payoneer\OpenPaymentGateway\Model;
use Magento\Framework\Mail\Template\TransportBuilder;
use Magento\Store\Model\StoreManagerInterface;
use Magento\Framework\App\Area;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\Exception\LocalizedException;
use Magento\Store\Model\ScopeInterface;
class NotificationEmailSender
{
const NOTIFICATION_EMAIL_TEMPLATE_ID = "notification_email_template";
/**
* @var TransportBuilder
*/
private $transportBuilder;
/**
* @var StoreManagerInterface
*/
private $storeManager;
/**
* @var ScopeConfigInterface
*/
private $scopeConfig;
/**
* Initialize dependencies.
*
* @param TransportBuilder $transportBuilder
* @param StoreManagerInterface $storeManager
* @param ScopeConfigInterface $scopeConfig
*/
public function __construct(
TransportBuilder $transportBuilder,
StoreManagerInterface $storeManager,
ScopeConfigInterface $scopeConfig
) {
$this->transportBuilder = $transportBuilder;
$this->storeManager = $storeManager;
$this->scopeConfig = $scopeConfig;
}
/**
* Send notification email
*
* @param array <mixed> $notificationResponse
* @return void
*/
public function send($notificationResponse)
{
$emailTemplateVars = $this->prepareEmailTemplateVars($notificationResponse);
$storeId = $this->storeManager->getStore()->getId();
$fromToAddressData = $this->getSenderDetails($storeId);
try {
$transport = $this->transportBuilder
->setTemplateIdentifier(self::NOTIFICATION_EMAIL_TEMPLATE_ID)
->setTemplateOptions(
[
'area' => Area::AREA_FRONTEND,
'store' => $storeId
]
)
->setTemplateVars($emailTemplateVars)
->setFromByScope($fromToAddressData)
->addTo($fromToAddressData['email'], $fromToAddressData['name'])
->getTransport();
$transport->sendMessage();
} catch (\Exception $e) {
throw new LocalizedException(
__('Error sending email = %1', $e->getMessage())
);
}
}
/**
* Prepare the email template variables.
*
* @param array <mixed> $notificationResponse
* @return array <mixed>
*/
private function prepareEmailTemplateVars($notificationResponse)
{
$emailTemplateVars = [];
$emailTemplateVars['resultCode'] = isset($notificationResponse['resultCode'])
? $notificationResponse['resultCode'] : '';
$emailTemplateVars['longId'] = isset($notificationResponse['longId'])
? $notificationResponse['longId'] : '';
$emailTemplateVars['transactionId'] = isset($notificationResponse['transactionId'])
? $notificationResponse['transactionId'] : '';
$emailTemplateVars['interactionCode'] = isset($notificationResponse['interactionCode'])
? $notificationResponse['interactionCode'] : '';
$emailTemplateVars['notificationId'] = isset($notificationResponse['notificationId'])
? $notificationResponse['notificationId'] : '';
$emailTemplateVars['reasonCode'] = isset($notificationResponse['reasonCode'])
? $notificationResponse['reasonCode'] : '';
$emailTemplateVars['statusCode'] = isset($notificationResponse['statusCode'])
? $notificationResponse['statusCode'] : '';
return $emailTemplateVars;
}
/**
* Get the email sender details
*
* @param int $storeId
* @return array <mixed>
*/
private function getSenderDetails($storeId)
{
$senderData = [];
$senderData['name'] = $this->scopeConfig->getValue(
'trans_email/ident_general/name',
ScopeInterface::SCOPE_STORE,
$storeId
);
$senderData['email'] = $this->scopeConfig->getValue(
'trans_email/ident_general/email',
ScopeInterface::SCOPE_STORE,
$storeId
);
return $senderData;
}
}
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment