本文实例讲述了php银联网页支付实现方法。分享给大家供大家参考。具体分析如下:
这里介绍的银联WAP支付功能,仅限消费功能。
1. PHP代码如下:
代码如下:
namespace common\services;
class UnionPay
{
/**
* 支付配置
* @var array
*/
public $config = [];
/**
* 支付参数,提交到银联对应接口的所有参数
* @var array
*/
public $params = [];
/**
* 自动提交表单模板
* @var string
*/
private $formTemplate =
HTML;
/**
* 构建自动提交HTML表单
* @return string
*/
public function createPostForm()
{
$this->params['signature'] = $this->sign();
$input = '';
foreach($this->params as $key => $item) {
$input .= "\t\t\n";
}
return sprintf($this->formTemplate, $this->config['frontUrl'], $input);
}
/**
* 验证签名
* 验签规则:
* 除signature域之外的所有项目都必须参加验签
* 根据key值按照字典排序,然后用&拼接key=value形式待验签字符串;
* 然后对待验签字符串使用sha1算法做摘要;
* 用银联公钥对摘要和签名信息做验签操作
*
* @throws \Exception
* @return bool
*/
public function verifySign()
{
$publicKey = $this->getVerifyPublicKey();
$verifyArr = $this->filterBeforSign();
ksort($verifyArr);
$verifyStr = $this->arrayToString($verifyArr);
$verifySha1 = sha1($verifyStr);
$signature = base64_decode($this->params['signature']);
$result = openssl_verify($verifySha1, $signature, $publicKey);
if($result === -1) {
throw new \Exception('Verify Error:'.openssl_error_string());
}
return $result === 1 ? true : false;
}
/**
* 取签名证书ID(SN)
* @return string
*/
public function getSignCertId()
{
return $this->getCertIdPfx($this->config['signCertPath']);
}
/**
* 签名数据
* 签名规则:
* 除signature域之外的所有项目都必须参加签名
* 根据key值按照字典排序,然后用&拼接key=value形式待签名字符串;
* 然后对待签名字符串使用sha1算法做摘要;
* 用银联颁发的私钥对摘要做RSA签名操作
* 签名结果用base64编码后放在signature域
*
* @throws \InvalidArgumentException
* @return multitype|string
*/
private function sign() {
$signData = $this->filterBeforSign();
ksort($signData);
$signQueryString = $this->arrayToString($signData);
if($this->params['signMethod'] == 01) {
//签名之前先用sha1处理
//echo $signQueryString;exit;
$datasha1 = sha1($signQueryString);
$signed = $this->rsaSign($datasha1);
} else {
throw new \InvalidArgumentException('Nonsupport Sign Method');
}
return $signed;
}
/**
* 数组转换成字符串
* @param array $arr
* @return string
*/
private function arrayToString($arr)
{
$str = '';
foreach($arr as $key => $value) {
$str .= $key.'='.$value.'&';
}
return substr($str, 0, strlen($str) - 1);
}
/**
* 过滤待签名数据
* signature域不参加签名
*
* @return array
*/
private function filterBeforSign()
{
$tmp = $this->params;
unset($tmp['signature']);
return $tmp;
}
/**
* RSA签名数据,并base64编码
* @param string $data 待签名数据
* @return mixed
*/
private function rsaSign($data)
{
$privatekey = $this->getSignPrivateKey();
$result = openssl_sign($data, $signature, $privatekey);
if($result) {
return base64_encode($signature);
}
return false;
}
/**
* 取.pfx格式证书ID(SN)
* @return string
*/
private function getCertIdPfx($path)
{
$pkcs12certdata = file_get_contents($path);
openssl_pkcs12_read($pkcs12certdata, $certs, $this->config['signCertPwd']);
$x509data = $certs['cert'];
openssl_x509_read($x509data);
$certdata = openssl_x509_parse($x509data);
return $certdata['serialNumber'];
}
/**
* 取.cer格式证书ID(SN)
* @return string
*/
private function getCertIdCer($path)
{
$x509data = file_get_contents($path);
openssl_x509_read($x509data);
$certdata = openssl_x509_parse($x509data);
return $certdata['serialNumber'];
}
/**
* 取签名证书私钥
* @return resource
*/
private function getSignPrivateKey()
{
$pkcs12 = file_get_contents($this->config['signCertPath']);
openssl_pkcs12_read($pkcs12, $certs, $this->config['signCertPwd']);
return $certs['pkey'];
}
/**
* 取验证签名证书
* @throws \InvalidArgumentException
* @return string
*/
private function getVerifyPublicKey()
{
//先判断配置的验签证书是否银联返回指定的证书是否一致
if($this->getCertIdCer($this->config['verifyCertPath']) != $this->params['certId']) {
throw new \InvalidArgumentException('Verify sign cert is incorrect');
}
return file_get_contents($this->config['verifyCertPath']);
}
}
2. 配置示例
代码如下:
//银联支付设置
'unionpay' => [
//测试环境参数
'frontUrl' => 'https://101.231.204.80:5000/gateway/api/frontTransReq.do', //前台交易请求地址
//'singleQueryUrl' => 'https://101.231.204.80:5000/gateway/api/queryTrans.do', //单笔查询请求地址
'signCertPath' => __DIR__.'/../keys/unionpay/test/sign/700000000000001_acp.pfx', //签名证书路径
'signCertPwd' => '000000', //签名证书密码
'verifyCertPath' => __DIR__.'/../keys/unionpay/test/verify/verify_sign_acp.cer', //验签证书路径
'merId' => 'xxxxxxx',
//正式环境参数
//'frontUrl' => 'https://101.231.204.80:5000/gateway/api/frontTransReq.do', //前台交易请求地址
//'singleQueryUrl' => 'https://101.231.204.80:5000/gateway/api/queryTrans.do', //单笔查询请求地址
//'signCertPath' => __DIR__.'/../keys/unionpay/test/sign/PM_700000000000001_acp.pfx', //签名证书路径
//'signCertPwd' => '000000', //签名证书密码
//'verifyCertPath' => __DIR__.'/../keys/unionpay/test/verify/verify_sign_acp.cer', //验签证书路径
//'merId' => 'xxxxxxxxx', //商户代码
],
3. 支付示例
代码如下:
$unionPay = new UnionPay();
$unionPay->config = Yii::$app->params['unionpay'];//上面的配置
$unionPay->params = [
'version' => '5.0.0', //版本号
'encoding' => 'UTF-8', //编码方式
'certId' => $unionPay->getSignCertId(), //证书ID
'signature' => '', //签名
'signMethod' => '01', //签名方式
'txnType' => '01', //交易类型
'txnSubType' => '01', //交易子类
'bizType' => '000201', //产品类型
'channelType' => '08',//渠道类型
'frontUrl' => Url::toRoute(['payment/unionpayreturn'], true), //前台通知地址
'backUrl' => Url::toRoute(['payment/unionpaynotify'], true), //后台通知地址
//'frontFailUrl' => Url::toRoute(['payment/unionpayfail'], true), //失败交易前台跳转地址
'accessType' => '0', //接入类型
'merId' => Yii::$app->params['unionpay']['merId'], //商户代码
'orderId' => $orderNo, //商户订单号
'txnTime' => date('YmdHis'), //订单发送时间
'txnAmt' => $sum * 100, //交易金额,单位分
'currencyCode' => '156', //交易币种
];
$html = $unionPay->createPostForm();
4. 异步通知示例
代码如下:
$unionPay = new UnionPay();
$unionPay->config = Yii::$app->params['unionpay'];
$unionPay->params = Yii::$app->request->post(); //银联提交的参数
if(empty($unionPay->params)) {
return 'fail!';
}
if($unionPay->verifySign() && $unionPay->params['respCode'] == '00') {
//.......
}
希望本文所述对大家的php程序设计有所帮助。

PHP類型提示提升代碼質量和可讀性。 1)標量類型提示:自PHP7.0起,允許在函數參數中指定基本數據類型,如int、float等。 2)返回類型提示:確保函數返回值類型的一致性。 3)聯合類型提示:自PHP8.0起,允許在函數參數或返回值中指定多個類型。 4)可空類型提示:允許包含null值,處理可能返回空值的函數。

PHP中使用clone關鍵字創建對象副本,並通過\_\_clone魔法方法定制克隆行為。 1.使用clone關鍵字進行淺拷貝,克隆對象的屬性但不克隆對象屬性內的對象。 2.通過\_\_clone方法可以深拷貝嵌套對象,避免淺拷貝問題。 3.注意避免克隆中的循環引用和性能問題,優化克隆操作以提高效率。

PHP適用於Web開發和內容管理系統,Python適合數據科學、機器學習和自動化腳本。 1.PHP在構建快速、可擴展的網站和應用程序方面表現出色,常用於WordPress等CMS。 2.Python在數據科學和機器學習領域表現卓越,擁有豐富的庫如NumPy和TensorFlow。

HTTP緩存頭的關鍵玩家包括Cache-Control、ETag和Last-Modified。 1.Cache-Control用於控制緩存策略,示例:Cache-Control:max-age=3600,public。 2.ETag通過唯一標識符驗證資源變化,示例:ETag:"686897696a7c876b7e"。 3.Last-Modified指示資源最後修改時間,示例:Last-Modified:Wed,21Oct201507:28:00GMT。

在PHP中,應使用password_hash和password_verify函數實現安全的密碼哈希處理,不應使用MD5或SHA1。1)password_hash生成包含鹽值的哈希,增強安全性。 2)password_verify驗證密碼,通過比較哈希值確保安全。 3)MD5和SHA1易受攻擊且缺乏鹽值,不適合現代密碼安全。

PHP是一種服務器端腳本語言,用於動態網頁開發和服務器端應用程序。 1.PHP是一種解釋型語言,無需編譯,適合快速開發。 2.PHP代碼嵌入HTML中,易於網頁開發。 3.PHP處理服務器端邏輯,生成HTML輸出,支持用戶交互和數據處理。 4.PHP可與數據庫交互,處理表單提交,執行服務器端任務。

PHP在過去幾十年中塑造了網絡,並將繼續在Web開發中扮演重要角色。 1)PHP起源於1994年,因其易用性和與MySQL的無縫集成成為開發者首選。 2)其核心功能包括生成動態內容和與數據庫的集成,使得網站能夠實時更新和個性化展示。 3)PHP的廣泛應用和生態系統推動了其長期影響,但也面臨版本更新和安全性挑戰。 4)近年來的性能改進,如PHP7的發布,使其能與現代語言競爭。 5)未來,PHP需應對容器化、微服務等新挑戰,但其靈活性和活躍社區使其具備適應能力。

PHP的核心優勢包括易於學習、強大的web開發支持、豐富的庫和框架、高性能和可擴展性、跨平台兼容性以及成本效益高。 1)易於學習和使用,適合初學者;2)與web服務器集成好,支持多種數據庫;3)擁有如Laravel等強大框架;4)通過優化可實現高性能;5)支持多種操作系統;6)開源,降低開發成本。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

Atom編輯器mac版下載
最受歡迎的的開源編輯器

SAP NetWeaver Server Adapter for Eclipse
將Eclipse與SAP NetWeaver應用伺服器整合。

SecLists
SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

VSCode Windows 64位元 下載
微軟推出的免費、功能強大的一款IDE編輯器