如何将自定义支付网关添加到社交引擎
How to add a custom payment gateway to Social Engine
我需要将一个基于社交引擎的新支付网关集成到我们的公司网站。这个 CMS
有一个名为 Advanced Payment Gateways 的扩展,它允许集成新的网关。事实上,它获取您的网关名称并生成一个压缩为文件的骨架结构,以便您可以解压缩并上传到您的服务器,从而与应用程序目录合并。
我将解释如何在没有社交引擎的情况下实现我的网关,我希望有人能告诉我如何将其整合到社交引擎中。
首先我连接到我的 PSP
服务:
$client = new nusoap_client('https://example.com/pgwchannel/services/pgw?wsdl');
我在数组中准备了以下参数以发送到 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);
如果支付请求被接受,结果是逗号分隔的字符串,第一个元素是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>
网关将return以下参数通过POST
方法回调给我们在支付请求中提供的回调URL
:
RefId
(在前面的步骤中生成的引用 ID)
ResCode
(支付结果:0表示成功)
saleOrderId
(在付款请求期间传递的订单 ID)
SaleReferenceId
(PSP给商家的销售参考码)
如果上一步中的ResCode
是0,那么我们需要通过下面的调用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);
如果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>";
我需要将一个基于社交引擎的新支付网关集成到我们的公司网站。这个 CMS
有一个名为 Advanced Payment Gateways 的扩展,它允许集成新的网关。事实上,它获取您的网关名称并生成一个压缩为文件的骨架结构,以便您可以解压缩并上传到您的服务器,从而与应用程序目录合并。
我将解释如何在没有社交引擎的情况下实现我的网关,我希望有人能告诉我如何将其整合到社交引擎中。
首先我连接到我的
PSP
服务:$client = new nusoap_client('https://example.com/pgwchannel/services/pgw?wsdl');
我在数组中准备了以下参数以发送到
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);
如果支付请求被接受,结果是逗号分隔的字符串,第一个元素是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>
网关将return以下参数通过
POST
方法回调给我们在支付请求中提供的回调URL
:
RefId
(在前面的步骤中生成的引用 ID)
ResCode
(支付结果:0表示成功)
saleOrderId
(在付款请求期间传递的订单 ID)
SaleReferenceId
(PSP给商家的销售参考码)如果上一步中的
ResCode
是0,那么我们需要通过下面的调用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);
如果
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>";