Как создать новый метод оплаты для minishop2?

Можете поделиться статьями как добавить свой метод оплаты, суть в оплате такая, получаем объект авторизации передав нужные поля, а так же номер заказа и сумму, и потом передать весь ответ от запроса на фронт, где с помощью js, будет создан объект оплаты, а так же уникальная ссылка, и перенаправит тоже через js. Сам метод оплаты вот epayment.kz/ru/docs/platezhnaya-stranica

Как можно это интегрировать с минишопом?

Сам код вроде есть, но можно ли его отправлять на сам сайт, не будут ли уязвимости.
Пока что код идёт через core, хотя это нигде прикреплено к минишопу, да и получается 403 ошибка, так как пытается подключить к core.

<?php
define('MODX_API_MODE', true);
require $_SERVER['DOCUMENT_ROOT'].'/index.php';

$params = [
    'grant_type' => 'client_credentials',
    'scope' => 'webapi usermanagement email_send verification statement statistics payment',
    'client_id' => $modx->getOption('epay_client_id'),
    'client_secret' => $modx->getOption('epay_client_secret'),
    'invoiceID' => $_POST['invoiceId'],
    'amount' => $_POST['amount'],
    'currency' => 'KZT',
    'terminal' => $modx->getOption('epay_terminal_id'),
    'postLink' => 'https://'.$_SERVER['HTTP_HOST'].'/core/components/epay/succsess.php',
    'failurePostLink' => 'https://'.$_SERVER['HTTP_HOST'].'/core/components/epay/error.php'
];


$debug = $modx->getOption('epay_debug');

$myCurl = curl_init();
curl_setopt_array($myCurl, array(
    CURLOPT_URL => $debug == 1 ? 'https://testoauth.homebank.kz/epay2/oauth2/token' : 'https://epay-oauth.homebank.kz/oauth2/token',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => http_build_query($params)
));
$response = curl_exec($myCurl);
curl_close($myCurl);

header('Content-type: application/json');
echo $response;
Как вариант этот код запихнуть в плагин и поставить обработчик и проверку, но это ведь тоже не правильно. Что лучше сделать в данной ситуации?
Vladimir
09 января 2023, 15:14
modx.pro
1
561
0

Комментарии: 10

Vladimir
09 января 2023, 15:16
0
Сам обработчик пытался сделать, и пытался регистрировать как показано в доках минишопа, но он даже не появляется.
<?php

if (!class_exists('msPaymentInterface')) {
    require_once dirname(__FILE__, 3) . '/minishop2/mspaymenthandler.class.php';
}

class mspEpayHalykBank extends msPaymentHandler implements msPaymentInterface
{

    /**
    * mspEpayHalykBank constructor.
    *
    * @param xPDOObject $object
    * @param array $config
    */
    function __construct(xPDOObject $object, $config = array())
    {
        parent::__construct($object, $config);

        $siteUrl = $this->modx->getOption('site_url');
        $assetsUrl = $this->modx->getOption('assets_url') . 'components/minishop2/';
        $paymentUrl = $siteUrl . substr($assetsUrl, 1) . 'custom/payment/mspepayhalykbank.php';

        $this->config = array_merge(array(
            'grant_type' => 'client_credentials',
            'debug' => $modx->getOption('epay_debug'),
            'paymentEpayUrl' => $this->config['debug'] == 1 ? 'https://testoauth.homebank.kz/epay2/oauth2/token' : 'https://epay-oauth.homebank.kz/oauth2/token',
            'scope' => 'webapi usermanagement email_send verification statement statistics payment',
            'client_id' => $modx->getOption('epay_client_id'),
            'client_secret' => $modx->getOption('epay_client_secret'),
            'currency' => 'KZT',
            'terminal' => $modx->getOption('epay_terminal_id'),
            'postLink' => $siteUrl.'/core/components/epay/succsess.php',
            'failurePostLink' => $siteUrl.'/core/components/epay/error.php'
        ), $config);
    }


    /**
    * @param msOrder $order
    *
    * @return array|string
    */
    public function send(msOrder $order)
    {
        if ($order->get('status') > 1) {
            return $this->error('ms2_err_status_wrong');
        }
        $params = array_merge(
            $this->config,
            array(
                'invoiceID' => $_POST['invoiceId'],
                'amount' => $_POST['amount'],                
            )
        );


        $response = $this->request($params, $this->getPaymentLink($order));
        if (is_array($response) && !empty($response['access_token'])) {

            return $this->success('', array('redirect' => $this->config['checkoutUrl'] . urlencode($token)));
        } else {
            $this->modx->log(
                modX::LOG_LEVEL_ERROR,
                '[miniShop2] Payment error while request. Request: ' . print_r(
                    $params,
                    1
                ) . ', response: ' . print_r(
                    $response,
                    1
                )
            );

            return $this->success('', array('msorder' => $order->get('id')));
        }
    }



    /**
    * Building query
    *
    * @param array $params Query params
    *
    * @return array/boolean
    */
    public function request($params = array(), $paymentEpayUrlFull)
    {
        $myCurl = curl_init();
        curl_setopt_array($myCurl, array(
            CURLOPT_URL => $paymentEpayUrlFull,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => http_build_query($params)
        ));


        $response = curl_exec($myCurl);
        if (curl_errno($myCurl)) {
            $result = curl_error($myCurl);
        }


        header('Content-type: application/json');

        curl_close($myCurl);

        return $response;
    }


    /**
    * Returns a direct link for continue payment process of existing order
    *
    * @param msOrder $order
    *
    * @return string
    */
    public function getPaymentLink(msOrder $order)
    {
        return $this->config['paymentEpayUrl'] . '?' .
        http_build_query(array(
            'action' => 'continue',
            'msorder' => $order->get('id'),
            'mscode' => $this->getOrderHash($order),
        ));
    }
}
    Артур Шевченко
    09 января 2023, 15:23
    0
    В minishop2 предусмотрена возможность добавлять собственные сервисы. Вот пример. В документации к вашему платёжному сервису есть раздел Платёж по API думаю вам стоит использовать именно этот способ проведения платежа, а не JS.
      Vladimir
      09 января 2023, 15:26
      0
      Нужно чтобы именно был редирект на страницу оплаты, а не чтобы заполнение данных происходило через сайт.
        Артур Шевченко
        09 января 2023, 15:31
        0
        В minishop2 оплата на сайте не происходит. Во всяком случае не знаю ни одного модуля, который бы позволял произвести оплату не покидая сайт. В методе оплаты же есть метод getPaymentLink и именно он должен возвращать ссылку на страницу оплаты вашего мерчанта, после чего в обработчике заказа будет выполнен редирект.
          Vladimir
          10 января 2023, 09:17
          0
          Вот сделал новый метод.
          <?php
          
          if (!class_exists('msPaymentInterface')) {
              require_once dirname(__FILE__, 3) . '/handlers/mspaymenthandler.class.php';
          }
          
          class EpayHalykBank extends msPaymentHandler implements msPaymentInterface
          {
          
              /**
              * EpayHalykBank constructor.
              *
              * @param xPDOObject $object
              * @param array $config
              */
              function __construct(xPDOObject $object, $config = array())
              {
                  parent::__construct($object, $config);
          
                  $siteUrl = $this->modx->getOption('site_url');
                  $assetsUrl = $this->modx->getOption('assets_url') . 'components/minishop2/';
                  $paymentUrl = $siteUrl . substr($assetsUrl, 1) . 'payment/mspepayhalykbank.php';
          
                  $this->config = array_merge(array(
                      'grant_type' => 'client_credentials',
                      'debug' => $modx->getOption('epay_debug'),
                      'epayTokenAuthUrl' => $this->config['debug'] == 1 ? $modx->getOption('epay_test_auth_url') : $modx->getOption('epay_prod_auth_url'),
                      'payPageUrl' => $this->config['debug'] == 1 ? $modx->getOption('epay_test_pay_page_url') : $modx->getOption('epay_pay_page_url'),
                      'scope' => 'webapi usermanagement email_send verification statement statistics payment',
                      'client_id' => $modx->getOption('epay_client_id'),
                      'client_secret' => $modx->getOption('epay_client_secret'),
                      'currency' => $modx->getOption('epay_payment_currency'),
                      'terminal_id' => $modx->getOption('epay_terminal_id'),
                      'postLink' => $modx->makeUrl($modx->getOption('epay_post_success_page_id')),
                      'failurePostLink' => $modx->makeUrl($modx->getOption('epay_post_error_page_id'))
                  ), $config);
              }
          
          
          
              /**
              * Create Auth Token
              *
              * @param 
              *
              * @return string
              */
              public function paymentAuth(msOrder $order)
              {
                  $authUrl = $this->config['epayTokenAuthUrl'];
          
                  $params = array(
                      'grant_type' => $this->config['grant_type'],
                      'scope' => $this->config['scope'],
                      'client_id' => $this->config['client_id'],
                      'client_secret' => $this->config['client_secret'],
                      'invoiceID' => $this->getOrderHash($order),
                      'amount' => $order->get('cost'),
                      'currency' => $this->config['currency'],
                      'terminal' => $this->config['terminal_id'],
                      'postLink' => $this->config['postLink'],
                      'failurePostLink' => $this->config['failurePostLink']
                  );
          
                  $myCurl = curl_init();
                  curl_setopt_array($myCurl, array(
                      CURLOPT_URL => $authUrl,
                      CURLOPT_RETURNTRANSFER => true,
                      CURLOPT_POST => true,
                      CURLOPT_POSTFIELDS => http_build_query($params)
                  ));
          
                  $response = curl_exec($myCurl);
                  curl_close($myCurl);
          
                  return json_decode($response, true);
          
              }
          
          
              /**
              * Returns a direct link for continue payment process of existing order
              *
              * @param msOrder $order
              *
              * @return string
              */
              public function getPaymentLink(msOrder $order)
              {
          
                  $authResponse = $this->paymentAuth($order);
          
                  $msAddress = $order->getOne('Address');
                  $orderPhone = $msAddress->get('phone');
                  $orderEmail = $msAddress->get('email');
                  $orderReceiver = $msAddress->get('receiver');
                  $orderComment = $msAddress->get('comment');
          
                  if(substr($orderPhone, 0, 1) == '7'){
                      $orderPhone = '+' . $orderPhone;
                  }
                  // if($authResponse['access_token'])
                  // 'data' => "{\"statement\":{\"name\":\"Arman      Ali\",\"invoiceID\":\"80000016\"}}",
          
                  return $this->config['payPageUrl'] . '?' .
                  http_build_query(array(
                      'action' => 'continue',
                      'msorder' => $order->get('id'),
                      'mscode' => $this->getOrderHash($order),
                      'invoiceId' => $this->getOrderHash($order),
                      'backLink' => $this->config['postLink'].'?action=success',
                      'failureBackLink' => $this->config['failurePostLink'].'?action=error',
                      'postLink' => $this->$siteUrl,
                      'failurePostLink' => $this->config['failurePostLink'].'?action=error',
                      'language' => 'rus',
                      'description' => 'Оплата в интернет магазине',
                      'accountId' => $this->config['client_id'],
                      'terminal' => $this->config['terminal_id'],
                      'amount' => $order->get('cost'),
                      'data' => array(
                          'name' => $orderReceiver,
                          'orderId' => $order->get('id'),
                          'invoiceId' => $this->getOrderHash($order),
                          'phone' => $orderPhone,
                          'email' => $orderEmail,                
                          'comment' => $orderComment
                      ),
                      'currency' => $this->config['currency'],
                      'phone' => $orderPhone,
                      'email' => $orderEmail,
                      'cardSave' => true,
                      'auth' => $authResponse
          
                  ));
              }
          }
          Пытаюсь зарегестрировать, так как в доках, через консоль
          if ($miniShop2 = $modx->getService('miniShop2')) {
              $miniShop2->addService('payment', 'EpayHalykBank',
                  '{core_path}components/minishop2/custom/payment/epayhalykbank.class.php'
              );
          }
          Где EpayHalykBank это имя класса оплаты. Но когда хочу добавить этот обработчик, он просто не появляется. Пути проверял, имя файла тоже проверил, он содержит class

          Можете пожалуйста подсказать, как исправить?
            Vladimir
            10 января 2023, 11:07
            0
            Проблема регистрации была в том что я использовал
            $modx
            а тут нужно было
            $this->modx
              Giant Dad
              20 июня 2023, 16:22
              0
              копирую Ваш код, регистрирую через $this->modx, но при создании оплаты, класс-обработчик всё равно не появляется disk.yandex.ru/d/xq_rjkOVRfquHQ только стандартный PayPal. Подскажите, пожалуйста, в чём может быть проблема
                Николай Савин
                20 июня 2023, 17:39
                0
                Класс оплаты, мало просто положить в нужный каталог. Его нужно зарегистрировать в системе. Подробнее читайте в документации
                  Giant Dad
                  21 июня 2023, 11:23
                  0
                  а видели я пишу выше «регистрирую через $this->modx»? это я как раз про регистрацию в системе через консоль. делаю как раз по документации, на которую вы ссылаетесь.
                  Создаю класс, подключаю его через консоль, в ms2_services сервис прописывается,
                  {«cart»:[],«order»:[],«payment»:{«epayhalykbank»:"{core_path}components\/minishop2\/custom\/payment\/epayhalykbank.class.php"},«delivery»:[]}
                  но класс-обработчик не появляется в выпадашке при создании нового способа оплаты
                  Vladimir
                  20 июня 2023, 18:07
                  0
                  Вам метод оплаты нужно зарегистрировать в системе, код ниже, код регистрации нужно запускать в консоли, Console это пакет для запуска php кода в админке (https://extras.modx.com/package/console), только моё название оплаты «EpayHalykBank» замените на ваше, а так же название файла «epayhalykbank.class.php» только в конце должно быть ".class.php" обязательно
                  if ($miniShop2 = $modx->getService('miniShop2')) {
                      $miniShop2->addService('payment', 'EpayHalykBank',
                          '{core_path}components/minishop2/custom/payment/epayhalykbank.class.php'
                      );
                  }
                  В целом можете написать в тг @invictusmaneobart
        Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
        10