You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

421 lines
14 KiB

<?php
defined('BASE_PATH') OR exit('No direct script access allowed');
class unionpay{
public function __construct(){
defined('SDK_SIGN_CERT_PATH') or define('SDK_SIGN_CERT_PATH', DATA_PATH . '/cer/' . 'PM_700000000000001_acp.pfx');
defined('SDK_SIGN_CERT_PWD') or define('SDK_SIGN_CERT_PWD', '000000');
defined('SDK_VERIFY_CERT_DIR') or define('SDK_VERIFY_CERT_DIR', DATA_PATH . '/cer/');
defined('SDK_FRONT_TRANS_URL') or define('SDK_FRONT_TRANS_URL', 'https://101.231.204.80:5000/gateway/api/frontTransReq.do');
defined('SDK_BACK_TRANS_URL') or define('SDK_BACK_TRANS_URL', 'https://101.231.204.80:5000/gateway/api/backTransReq.do');
defined('SDK_SINGLE_QUERY_URL') or define('SDK_SINGLE_QUERY_URL', 'https://101.231.204.80:5000/gateway/api/queryTrans.do');
include_once(BASE_PATH.'helpers/order_helper.php');
include_once(BASE_PATH.'helpers/payment_helper.php');
}
/**
* 生成支付代码
*
* @param array $order
* 订单信息
* @param array $payment
* 支付方式信息
*/
function get_code($order, $payment) {
if (!defined('EC_CHARSET')) {
$charset = 'UTF-8';
} else {
$charset = EC_CHARSET;
}
if(!$order['add_time']){
$order['add_time'] = gmtime();
}
if(!isset($order['order_sn']{10})){
$order['order_sn'] = get_order_sn();
}
$parameter = array(
'version' => '5.0.0', // 接口版本号
'encoding' => $charset,
'certId' => $this->getSignCertId(), //证书ID
'txnType' => '01', //交易类型
'txnSubType' => '01', //交易子类
'bizType' => '000000', //业务类型
'frontUrl' => return_url(basename(__FILE__, '.php')), //前台通知地址
'backUrl' => notify_url(basename(__FILE__, '.php')), //后台通知地址
'signMethod' => '01', //签名方法
'channelType' => '08', //渠道类型
'accessType' => '0', //接入类型
'merId' => $payment['mer_id'], //商户代码
'orderId' => $order['order_sn'] . '0' . $order['log_id'], // 请求号,唯一
'txnTime' => date('YmdHis', $order['add_time']), //订单发送时间
'txnAmt' => $order['order_amount'] * 100, //交易金额 单位分
'currencyCode' => '156', //交易币种
'defaultPayType' => '0001', //默认支付方式
'reqReserved' =>' 透传信息', //请求方保留域,透传字段,查询、通知、对账文件中均会原样出现
);
$this->sign($parameter);
$front_uri = 'https://101.231.204.80:5000/gateway/api/frontTransReq.do';
// 构造 自动提交的表单
$html_form = $this->create_html($parameter, $front_uri);
return $html_form;
}
/**
* 查询交易
*/
public function verify_query($order, $payment) {
if (!defined('EC_CHARSET')) {
$charset = 'UTF-8';
} else {
$charset = EC_CHARSET;
}
$params = array(
'version' => '5.0.0', //版本号
'encoding' => $charset, //编码方式
'certId' => $this->getSignCertId(), //证书ID
'signMethod' => '01', //签名方法
'txnType' => '00', //交易类型
'txnSubType' => '00', //交易子类
'bizType' => '000000', //业务类型
'accessType' => '0', //接入类型
'channelType' => '07', //渠道类型
'orderId' => $order['order_sn'] . '0' . $order['log_id'], //请修改被查询的交易的订单号
'merId' => $payment['mer_id'], //商户代码,请修改为自己的商户号
'txnTime' => date('YmdHis', $order['add_time']), //请修改被查询的交易的订单发送时间
);
$this->sign($params);
$result = $this->sendHttpRequest($params, SDK_SINGLE_QUERY_URL);
//返回结果展示
$result_arr = $this->coverStringToArray($result);
if ($this->verify($result_arr)) {
if ($result_arr['respCode'] == '00') {
print_r($result_arr );
echo "ee";
//改变订单支付方式
$log_id = substr($result_arr['orderId'], 14);
order_paid($log_id, 2);
return true;
}
}
//echo $this->verify($result_arr) ? '验签成功' : '验签失败';
}
/**
* 银联同步响应操作
*
* @return boolean
*/
public function callback($data) {
if (isset($_POST ['signature'])) {
if ($this->verify($_POST)) {
if ($_POST['respCode'] == '00') {
// 获取支付订单号log_id
$log_id = substr($_POST['orderId'], 14);
order_paid($log_id, 2);
return true;
}
} else {
return false;
}
} else {
echo '签名为空';
}
}
/**
* 银联异步通知
*
* @return string
*/
public function notify($data) {
if (!empty($_POST)) {
if (isset($_POST ['signature'])) {
if ($this->verify($_POST)) {
if ($_POST['respCode'] == '00') {
// 获取支付订单号log_id
$log_id = substr($_POST['orderId'], 14);
order_paid($log_id, 2);
return true;
}
} else {
return false;
}
} else {
echo '签名为空';
}
} else {
exit("fail");
}
}
/**
* 签名证书ID
*
* @return unknown
*/
function getSignCertId() {
// 签名证书路径
return $this->getCertId(SDK_SIGN_CERT_PATH);
}
/**
* 取证书ID(.pfx)
*
* @return unknown
*/
function getCertId($cert_path) {
$pkcs12certdata = file_get_contents($cert_path);
openssl_pkcs12_read($pkcs12certdata, $certs, SDK_SIGN_CERT_PWD);
$x509data = $certs ['cert'];
openssl_x509_read($x509data);
$certdata = openssl_x509_parse($x509data);
$cert_id = $certdata ['serialNumber'];
return $cert_id;
}
/**
* 签名
*
* @param String $params_str
*/
function sign(&$params) {
//global $log;
//$log->LogInfo('=====签名报文开始======');
if (isset($params['transTempUrl'])) {
unset($params['transTempUrl']);
}
// 转换成key=val&串
$params_str = $this->coverParamsToString($params);
//$log->LogInfo("签名key=val&...串 >" . $params_str);
$params_sha1x16 = sha1($params_str, FALSE);
//$log->LogInfo("摘要sha1x16 >" . $params_sha1x16);
// 签名证书路径
$cert_path = SDK_SIGN_CERT_PATH;
$private_key = $this->getPrivateKey($cert_path);
// 签名
$sign_falg = openssl_sign($params_sha1x16, $signature, $private_key, OPENSSL_ALGO_SHA1);
if ($sign_falg) {
$signature_base64 = base64_encode($signature);
// $log->LogInfo("签名串为 >" . $signature_base64);
$params ['signature'] = $signature_base64;
} else {
echo "签名失败";
exit;
//$log->LogInfo(">>>>>签名失败<<<<<<<");
}
//$log->LogInfo('=====签名报文结束======');
}
/**
* 返回(签名)证书私钥 -
*
* @return unknown
*/
function getPrivateKey($cert_path) {
$pkcs12 = file_get_contents($cert_path);
openssl_pkcs12_read($pkcs12, $certs, SDK_SIGN_CERT_PWD);
return $certs ['pkey'];
}
/**
* 数组 排序后转化为字体串
*
* @param array $params
* @return string
*/
function coverParamsToString($params) {
$sign_str = '';
// 排序
ksort($params);
foreach ($params as $key => $val) {
if ($key == 'signature') {
continue;
}
$sign_str .= sprintf("%s=%s&", $key, $val);
// $sign_str .= $key . '=' . $val . '&';
}
return substr($sign_str, 0, strlen($sign_str) - 1);
}
/**
* 构造自动提交表单
*
* @param unknown_type $params
* @param unknown_type $action
* @return string
*/
function create_html($params, $action) {
$encodeType = isset($params ['encoding']) ? $params ['encoding'] : 'UTF-8';
$html = <<<eot
<form id="pay_form" name="pay_form" action="{$action}" method="post" target="_blank">
eot;
foreach ($params as $key => $value) {
$html .= " <input type=\"hidden\" name=\"{$key}\" id=\"{$key}\" value=\"{$value}\" />\n";
}
$html .= <<<eot
<input type="submit" type="hidden" value="立即支付" class="btn btn-info ect-btn-info ect-colorf ect-bg c-btn3">
</form>
eot;
return $html;
}
/**
* 验签
*
* @param String $params_str
* @param String $signature_str
*/
function verify($params) {
global $log;
// 公钥
$public_key = $this->getPulbicKeyByCertId($params ['certId']);
// echo $public_key . '<br/>';
// 签名串
$signature_str = $params ['signature'];
unset($params ['signature']);
$params_str = $this->coverParamsToString($params);
// $log->LogInfo('报文去[signature] key=val&串>' . $params_str);
$signature = base64_decode($signature_str);
//echo date('Y-m-d', time());
$params_sha1x16 = sha1($params_str, FALSE);
//$log->LogInfo('摘要shax16>' . $params_sha1x16);
$isSuccess = openssl_verify($params_sha1x16, $signature, $public_key, OPENSSL_ALGO_SHA1);
//$log->LogInfo($isSuccess ? '验签成功' : '验签失败' );
return $isSuccess;
}
/**
* 根据证书ID 加载 证书
*
* @param unknown_type $certId
* @return string NULL
*/
function getPulbicKeyByCertId($certId) {
global $log;
//$log->LogInfo ( '报文返回的证书ID>' . $certId );
// 证书目录
$cert_dir = SDK_VERIFY_CERT_DIR;
//$log->LogInfo ( '验证签名证书目录 :>' . $cert_dir );
$handle = opendir($cert_dir);
if ($handle) {
while ($file = readdir($handle)) {
clearstatcache();
$filePath = $cert_dir . '/' . $file;
if (is_file($filePath)) {
if (pathinfo($file, PATHINFO_EXTENSION) == 'cer') {
if ($this->getCertIdByCerPath($filePath) == $certId) {
closedir($handle);
//$log->LogInfo ( '加载验签证书成功' );
return $this->getPublicKey($filePath);
}
}
}
}
//$log->LogInfo ( '没有找到证书ID为[' . $certId . ']的证书' );
} else {
//$log->LogInfo ( '证书目录 ' . $cert_dir . '不正确' );
}
closedir($handle);
return null;
}
/**
* 取证书ID(.cer)
*
* @param unknown_type $cert_path
*/
function getCertIdByCerPath($cert_path) {
$x509data = file_get_contents($cert_path);
openssl_x509_read($x509data);
$certdata = openssl_x509_parse($x509data);
$cert_id = $certdata ['serialNumber'];
return $cert_id;
}
/**
* 取证书公钥 -验签
*
* @return string
*/
function getPublicKey($cert_path) {
return file_get_contents($cert_path);
}
/**
* 后台交易 HttpClient通信
* @param unknown_type $params
* @param unknown_type $url
* @return mixed
*/
function sendHttpRequest($params, $url) {
$opts = $this->getRequestParamString($params);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //不验证证书
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); //不验证HOST
curl_setopt($ch, CURLOPT_SSLVERSION, 3);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-type:application/x-www-form-urlencoded;charset=UTF-8'
));
curl_setopt($ch, CURLOPT_POSTFIELDS, $opts);
/**
* 设置cURL 参数,要求结果保存到字符串中还是输出到屏幕上。
*/
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// 运行cURL,请求网页
$html = curl_exec($ch);
// close cURL resource, and free up system resources
curl_close($ch);
return $html;
}
/**
* 字符串转换为 数组
*
* @param unknown_type $str
* @return multitype:unknown
*/
function coverStringToArray($str) {
$result = array();
if (!empty($str)) {
$temp = preg_split('/&/', $str);
if (!empty($temp)) {
foreach ($temp as $key => $val) {
$arr = preg_split('/=/', $val, 2);
if (!empty($arr)) {
$k = $arr ['0'];
$v = $arr ['1'];
$result [$k] = $v;
}
}
}
}
return $result;
}
/**
* 组装报文
*
* @param unknown_type $params
* @return string
*/
function getRequestParamString($params) {
$params_str = '';
foreach ($params as $key => $value) {
$params_str .= ($key . '=' . (!isset($value) ? '' : urlencode($value)) . '&');
}
return substr($params_str, 0, strlen($params_str) - 1);
}
}
?>