如何将自定义支付网关添加到社交引擎

How to add a custom payment gateway to Social Engine

我需要将一个基于社交引擎的新支付网关集成到我们的公司网站。这个 CMS 有一个名为 Advanced Payment Gateways 的扩展,它允许集成新的网关。事实上,它获取您的网关名称并生成一个压缩为文件的骨架结构,以便您可以解压缩并上传到您的服务器,从而与应用程序目录合并。

我将解释如何在没有社交引擎的情况下实现我的网关,我希望有人能告诉我如何将其整合到社交引擎中。

  1. 首先我连接到我的 PSP 服务:

    $client = new nusoap_client('https://example.com/pgwchannel/services/pgw?wsdl');
    
  2. 我在数组中准备了以下参数以发送到 bpPayRequest

    $parameters = array(
        'terminalId' => $terminalId,
        'userName' => $userName,
        'userPassword' => $userPassword,
        'orderId' => $orderId,
        'amount' => $amount,
        'localDate' => $localDate,
        'localTime' => $localTime,
        'additionalData' => $additionalData,
        'callBackUrl' => $callBackUrl,
        'payerId' => $payerId);
    
    // Call the SOAP method
    $result = $client->call('bpPayRequest', $parameters, $namespace);
    
  3. 如果支付请求被接受,结果是逗号分隔的字符串,第一个元素是0.
    然后我们可以将第二个元素(参考id)发送到付款 通过 POST 方法如下网关:

    echo "<script language='javascript' type='text/javascript'>postRefId('" . $res[1] . "');</script>";
    
    <script language="javascript" type="text/javascript">    
        function postRefId (refIdValue) {
            var form = document.createElement("form");
            form.setAttribute("method", "POST");
            form.setAttribute("action", "https://example.com/pgwchannel/startpay");         
            form.setAttribute("target", "_self");
            var hiddenField = document.createElement("input");              
            hiddenField.setAttribute("name", "RefId");
            hiddenField.setAttribute("value", refIdValue);
            form.appendChild(hiddenField);
    
            document.body.appendChild(form);         
            form.submit();
            document.body.removeChild(form);
        }
        </script>
    
  4. 网关将return以下参数通过POST方法回调给我们在支付请求中提供的回调URL
    RefId(在前面的步骤中生成的引用 ID)
    ResCode(支付结果:0表示成功)
    saleOrderId(在付款请求期间传递的订单 ID)
    SaleReferenceId(PSP给商家的销售参考码)

  5. 如果上一步中的ResCode0,那么我们需要通过下面的调用bpVerifyRequest参数来验证支付,否则支付将被取消。

     $parameters = array(
        'terminalId' => $terminalId,
        'userName' => $userName,
        'userPassword' => $userPassword,
        'orderId' => $orderId,
        'saleOrderId' => $verifySaleOrderId,
        'saleReferenceId' => $verifySaleReferenceId);
    
    // Call the SOAP method
    $result = $client->call('bpVerifyRequest', $parameters, $namespace);
    
  6. 如果bpVerifyRequest的结果为零,付款是肯定的,商家必须提供购买的商品或服务。但是,有一个可选方法bpSettleRequest,用于请求结算。调用方式如下:

    $parameters = array(
        'terminalId' => $terminalId,
        'userName' => $userName,
        'userPassword' => $userPassword,
        'orderId' => $orderId,
        'saleOrderId' => $settleSaleOrderId,
        'saleReferenceId' => $settleSaleReferenceId);

    // Call the SOAP method
    $result = $client->call('bpSettleRequest', $parameters, $namespace);

我在查看支付网关插件中的默认网关时感到困惑,例如PayPal、Stripe、2Checkout 等。如何将此代码逻辑合并到新创建的网关框架中? (结构如下图):

您可以在这里查看完整的源代码:
default.php
callback.php

我通过在 Engine_Payment_Gateway_MyGateway class 中添加支付代码解决了这个问题:

一旦用户在 SocialEngine 页面上确认他们想要支付,就会调用上述 class 中的方法 processTransaction() 并将用户重定向到 PSP 的支付安全页面。一旦他们完成付款,即支付成功或失败或取消交易,他们的 PSP 页面会将他们重定向到我们之前作为称为 callBackUrl 的参数发送给它的页面。在那里,您将收到特定于 PSP 的参数,这些参数可帮助您确定付款是否成功,并通过另一个 SOAP 调用要求 PSP 确认付款,然后可选择要求它结算(尽快将钱存入卖家的帐户):

添加到 processTransaction():

        $data = array();
        $rawData = $transaction->getRawData();

        //Save order ID for later
        $this->_orderId = $rawData['vendor_order_id'];
        $this->_grandTotal = $rawData['AMT'];


        $client = new nusoap_client('https://example.com/pgwchannel/services/pgw?wsdl');
        $namespace = 'http://interfaces.core.sw.example.com/';


        // Check for an error
        $err = $client->getError();
        if ($err) {
            echo '<h2>Constructor error</h2><pre>' . $err . '</pre>';
            die();
        }


        /* Set variables */

//Get price from SEAO 
//$order_ids = Engine_Api::_()->getDbTable('orders','sitestoreproduct')->getOrderIds($this->parent_id);
//$price = Engine_Api::_()->getDbTable('orders','sitestoreproduct')->getGrandTotal($this->parent_id);


        $terminalId = '1111111';
        $userName = 'username';
        $userPassword = '1111111';
        $orderId = $rawData['vendor_order_id'];

        $amount = $rawData['AMT'];
        $localDate = date("Y") . date("m") . date("d");
        $localTime = date("h") . date("i") . date("s");
        $additionalData = $rawData['return_url'];
        $callBackUrl = 'https://example.com/pgateway/pay/callback';
        $payerId = '0';







        /* Define parameters array   */

        $parameters = array(
            'terminalId' => $terminalId,
            'userName' => $userName,
            'userPassword' => $userPassword,
            'orderId' => $orderId,
            'amount' => $amount,
            'localDate' => $localDate,
            'localTime' => $localTime,
            'additionalData' => $additionalData,
            'callBackUrl' => $callBackUrl,
            'payerId' => $payerId
        );



        $result = $client->call('bpPayRequest', $parameters, $namespace);



        if ($client->fault) {
            echo '<h2>Fault</h2><pre>';
            print_r($result);
            echo '</pre>';
            die();
        } else { //Check for errors
            $error = $client->getError();
            if ($error) {
                echo "An error occurred: ";
                print_r($error);
                die();
            } else {
                //break the code
                $resultSegmts = explode(',', $result);
                $ResCode = $resultSegmts [0];


                if ($ResCode == "0") {
                    //Notify admin of the order                    
                    echo '<h3>Redirecting you to the payment page. Please wait...</h3><br/>';
                    echo '<script language="javascript" type="text/javascript">
                      postRefId("' . $resultSegmts[1] . '");
                    </script>';
                } elseif ($ResCode == "25") {
                    echo "<h3>Purchase successful</h3>";
                } else {
                    echo "<h3>PSP response is: $ResCode</h3>";
                } 
            }
        }

添加到您的回调操作:

    $this->view->message = 'This is callback action for PayController';
    $RefId = $_POST['RefId'];
    $ResCode = $_POST['ResCode'];
    $saleOrderId = $_POST['SaleOrderId'];
    $saleReferenceId = $_POST['SaleReferenceId'];

    $this->_orderId = $saleOrderId;

        $this->view->RefId = $RefId;
        $this->view->saleOlderId = $saleOrderId;
        $this->view->saleReferenceId = $saleReferenceId;
    }
    if ($ResCode == "0") {
        try {
            $client = new nusoap_client('https://example.com/pgwchannel/services/pgw?wsdl');
        } catch (Exception $e) {
            die($e->getMessage());
        }

        $namespace = 'http://interfaces.core.sw.example.com/';
        $terminalId = "111111";
        $userName = "username";
        $userPassword = "11111111";


        $parameters = array(
            'terminalId' => $terminalId,
            'userName' => $userName,
            'userPassword' => $userPassword,
            'orderId' => $saleOrderId,
            'saleOrderId' => $saleOrderId,
            'saleReferenceId' => $saleReferenceId
        );
        $resVerify = $client->call('bpVerifyRequest', $parameters, $namespace);



        if ($resVerify->fault) { //Check for fault 
            echo "<h1>Fault: </h1>";
            print_r($result);
            die();
        } else { //No fault: check for errors now 
            $err = $client->getError();
            if ($err) {
                echo "<h1>Error: " . $err . " </h1>";
            } else {
                if ($resVerify == "0") {//Check verification response: if 0, then purchase was successful. 
                    echo "<div class='center content green'>Payment successful. Thank you for your order.</div>";
                    $this->view->message = $this->_translate('Thanks for your purchase.');
                    $this->dbSave(); //update database table
                } else
                    echo "<script language='javascript' type='text/javascript'>alert(    'Verification Response: " . $resVerify . "');</script>";
            }
        }

        //Note that we need to send bpSettleRequest to PSP service to request settlement once we have verified the payment 
        if ($resVerify == "0") {
            // Update table, Save RefId
            //Create parameters array for settle
            $this->sendEmail();
            $this->sendSms();

            $resSettle = $client->call('bpSettleRequest', $parameters, $namespace);
            //Check for fault 
            if ($resSettle->fault) {
                echo "<h1>Fault: </h1><br/><pre>";
                print_r($resSettle);
                echo "</pre>";
                die();
            } else { //No fault in bpSettleRequest result 
                $err = $client->getError();
                if ($err) {
                    echo "<h1>Error: </h1><pre>" . $err . "</pre>";
                    die();
                } else {
                    if ($resSettle == "0" || $resSettle == "45") {//Settle request successful 
                        // echo "<script language='javascript' type='text/javascript'>alert('Payment successful');</script>";
                    }
                }
            }
        }
    } else {
        echo "<div class='center content error'>Payment failed. Please try again later.</div> ";
        // log error in app
        // Update table, log the error
        // Show proper message to user
    }
    $returnUrl = 'https://example.com/stores/products'; //Go to store home for now. Later I'll set this to the last page 
    echo "<div class='center'>";
    echo "<form action=$returnUrl method='POST'>";
    echo "<input class='center' id='returnstore' type='submit' value='Return to store'/>";
    echo "</form>";
    echo "</div>";