本文主要和大家分享PHP银联在线支付接口的开发实例,希望能帮助到大家。

1、 登录银联自助化测试平台(登陆地址:open.unionpay.com),登录后,点击我的产品,如下:点击右方需要测试的接口,本例以 手机网页支付(WAP支付)为例。

2、 点击左侧菜单 测试参数,即可看到测试过程所需要的参数,如下图:点击测试证书,下载两个证书,一个是以后缀 .pfx 的私钥证书,一个是后缀 .cer 的公钥证书,将其下载后,私钥证书文件名称修改为 acp_test_sign.pfx 。或者你不下载的话,直接用本例子的也可以。TP3.2例子 里面 Public/cer 里面已有所有证书文件。

3、 TP3.2例子里面已有相关代码可以用来测试,测试的时候请使用测试环境的参数,代码中均有注释。在开始之前要确保你的环境PHP版本基于5.3,需开启curl、openssl功能,还有测试要放在线上测试,本地的虚拟域名是不行的。如遇到什么问题,可以参考官方的说明,本文件夹里面有个 PHP Version SDK 是官方的文档,参考里面的说明就好了,他们那个例子我测试的时候也跑不起来,不知道什么鬼原因。

4、 切换到生产环境,注意以下问题:

4.1 首先根据你收到的商户开通邮件里面的指示,访问网站 http://cs.cfca.com.cn/

下载生产证书文件:

点击下载后,完成下载操作后,页面会出现下载成功的提示。下载的证书自动存放在IE中,下一步就要进行证书的导出。

4.2 导出证书文件:打开IE浏览器,点击右上角的齿轮,打开工具=》Internet选项=》内容=》证书,如图:

点击证书后,找到刚刚下载的那个证书,你可以根据名称去辨别,商户邮件中有标注:

上图中红色标注的名称应该跟你下载的那个名称一样。

找到它,然后点击导出:一路的下一步,在以下几步需要注意

以上密码就是 config.php 里面生产环境要设置的那个密码,请设置为六位数字(仅限数字,请勿设置字母及符号)

指定导出证书的文件名,名称就设置为:acp_prod_sign,并选择目录存放证书,点击下一步,设置导出到桌面,完成后将在桌面看到一个 acp_prod_sign.pfx 的文件。这个就是生产环境要用到的私钥文件,将它复制一份到证书目录 /Public/cer 。下一步就要上传这个证书到商户服务网站。

4.2 上传证书到商户服务网站。登录 https://merchant.unionpay.com/portal/login.jsp

上传刚刚导出的那个 acp_prod_sign.pfx 文件,点击上传。

下一步,启用证书,点击安全证书管理,启用即可。

下一步,下载银联公钥

解压文件,把里面的两个证书同样放到 /Public/cer 里面。然后就去 config.php 里面根据文件注释切换到生产环境即可。

以下是TP3.2的代码资料:

/App/Home/Conf/config.php<?phpreturn array( //'配置项'=>'配置值'

'UNIONPAY' => array(// 银联配置

//测试环境参数

'frontUrl' => 'https://101.231.204.80:5000/gateway/api/frontTransReq.do', //测试环境前台交易请求地址

//'frontUrl' => 'https://gateway.95516.com/gateway/api/frontTransReq.do', //生产环境前台交易请求地址

'singleQueryUrl' => 'https://101.231.204.80:5000/gateway/api/backTransReq.do', //测试环境单笔查询请求地址

//'singleQueryUrl' => 'https://gateway.95516.com/gateway/api/queryTrans.do', //生产环境单笔查询请求地址

'signCertPath' =>getcwd().'/Public/cer/acp_test_sign.pfx', //签名证书路径 这个证书就是你在https://open.unionpay.com/ajweb/account/testPara 上面下载的那个商户私钥证书 供你测试使用

//'signCertPath' =>getcwd().'/Public/cer/acp_prod_sign.pfx', //签名证书路径 这个证书就是你在 商户开通邮件里面叫你去 http://cs.cfca.com.cn/ 下载并把私钥上传至商户服务网站并启用的那个私钥文件

'signCertPwd' => '000000', //测试环境签名证书密码

//'signCertPwd' => '135246', //生产环境证书签名证书密码 这个密码是你在IE导出上述私钥文件时候你自己定义的6位数字密码

//'verifyCertPath' => getcwd().'/Public/cer/verify_sign_acp.cer', //测试环境验签证书路径

'verifyCertPath' => getcwd().'/Public/cer/acp_prod_verify_sign.cer', //验签证书路径

'merId' => '777290058138754', //测试商户代码

//'merId' => '8024400481****', //生产环境商户代码 从你的商户开通邮件里面有

), 'UNIONPAY_CONFIG'=>array(// 银联配置

'version' => '5.0.0', //版本号

'encoding' => 'GBK', //编码方式

'signMethod' => '01', //签名方式

'txnType' => '01', //交易类型

'txnSubType' => '01', //交易子类

'bizType' => '000201', //产品类型

'channelType' => '07',//渠道类型

'frontUrl' => "http://win2.qbt8.com/ase_admin/index.php/Home/ypay/pay_success", //前台通知地址

'backUrl' => "http://win2.qbt8.com/ase_admin/index.php/Home/ypay/notify", //后台通知地址

'frontFailUrl' => "http://win2.qbt8.com/ase_admin/index.php/Home/ypay/pay_fail", //失败交易前台跳转地址

'accessType' => '0', //接入类型

'merId' => '777290058138754', //测试商户代码

//'merId' => '8024400481*****', //生产环境商户代码

'txnTime' => date('YmdHis'), //订单发送时间

'currencyCode' => '156', //交易币种

),

);?>

控制器代码如下:<?php

/*

|-------------------------------------------------------------|

| 银联在线支付控制器

|author:shuguang date:2016-11-16 |-------------------------------------------------------------|

*/

namespace Home\Controller;

use Think\Controller;

class YpayController extends Controller

{

/**

* 支付配置

* @var array

*/

public $config = array();

/**

* 支付参数,提交到银联对应接口的所有参数

* @var array

*/

public $params = array();

/**

* 自动提交表单模板

* @var string

*/

private $formTemplate = <<

支付

跳转中...

%s

document.onreadystatechange = function(){ if(document.readyState == "complete") {

document.pay_form.submit();

}

};

HTML;

public function index(){

//前台表单 $this->display();

}

/*支付成功后 前台通知地址*/

public function pay_success(){ echo "

支付成功!

";

}

/*失败交易前台跳转地址*/

public function pay_fail(){ echo "

支付失败!

";

}

/*生产支付参数 提交支付 */

function usespay(){ $this->config = C('UNIONPAY');//从配置里读取

$config = C('UNIONPAY_CONFIG'); $config['certId'] = $this->getSignCertId(); //证书ID $config['orderId'] = mt_rand(111111111,999999999);//订单号 自定义

$config['txnAmt'] = I("post.money")*100; //交易金额,单位分 $this->params = $config;

// $_SESSION['ceshi']=$config;

/* 以下是自己的业务逻辑操作 生产支付记录到本地数据库

$money = I("post.money");; $user_id = $this->user_id; $OrderId = $config['orderId'];//生成随机订单号 $pay_type = "银联";//支付方式 1余额 2支付宝 $pay_fee = M('handfee')->find(2); if ($pay_fee['type'] == 1){ $fee=$pay_fee['rate']*$money;

}else { $fee=$pay_fee['fee'];

}

//订单表数据 $order = array( "order_id"=>$OrderId, "uid"=>$user_id, "pay_mode"=>1, "pay_channels"=>2, "fee"=>$fee, "status"=>0,//待审核 "beizhu"=>"银联在线充值", "ent_money"=>$money-$fee, "time"=>time(), "sub_time"=>time(), "pay_money"=>$money, "pay_type"=>$pay_type,//1余额支付 2支付宝支付

//"type"=>2

);*/

//$Ord=M('pay');

//$Ord->add($order); $html = $this->createPostForm();//构建自动提交HTML表单 echo $html;

}

function ceshi(){

dump($_SESSION);

}

function usernotify(){// 付款后返回商家

}

function notify(){//后台通知路径

/*付款后业务逻辑代码 */ $orderId = $_POST ['orderId']; //其他字段也可用类似方式获取 $respCode = $_POST ['respCode']; //判断respCode=00或A6即可认为交易成功 if ($respCode=='00'||$respCode=='A6'){

/*通过写入文件的方式记录返回的订单号等 */ $str = "--------- ".date('Y-m-d H:i:s')." ---------"; $str .= "orderId:".$orderId."\r\n"; $str .= "respCode:".$respCode."\r\n"; $str .= "--------- END -----------"."\r\n";

file_put_contents('unionpay_notify_log.log', $str);

/* 以下是支付成功后的数据库操作 请根据需要自行操作

$order['status']=1; $order['check_time']=time();

M('pay')->where(array('order_id'=>$orderId))->save($order);

$order_info = M('pay')->where(array('order_id'=>$orderId))->find();

$log['user_id']=$order_info['uid']; $log['user_money']=$order_info['pay_money']; $log['change_time']=time(); $log['desc']="银联在线充值";

M('account_log')->add($log);

M('users')->where('user_id='.$order_info['uid'])->setInc('user_money',$order_info['ent_money']);

*/

}

}

function unionpayfail(){

}

/* function orderPay($orderinfo,$state){ $filename = 'Log/yapy';

file_put_contents($filename.'/'.$orderinfo['orderId'].'.txt', json_encode($_POST), FILE_APPEND);

//$order = D('order');

//$payment = D('payment');

//$where['order_sn'] = array('in', array($orderinfo['orderId']));

//$orinfo = $order->where($where)->find(); $rs = $payment->where($where)->find(); if (empty($rs) && $orinfo['order_state'] < 2 ) { $where1['udb_user.user_id'] = array('eq', session('id')); $userinfo1 = json_decode(req_api("api_key", C("API_KEY"), C('USER_API') ."user/api/GetSomeuser/", array('where' => json_encode($where1))), true); $data1['order_state'] = (int) $state;

//$orderwhere['order_sn'] = array('in', array($orderinfo['orderId']));

//$order->where($orderwhere)->save($data1); if($orinfo['balance'] >0 && $orinfo['isblance'] == 1){ if($userinfo1[0]['balance']-$orinfo['balance']>=0){ $total1 = $total1-$data['balance']; $istrue = req_api("api_key", C("API_KEY"), C('USER_API') . "user/api/removeBalance/", array('user' =>session('id'),'count'=>$orinfo['balance'],'type'=>'d'));

//$this->BanlanceRecord(2,$orinfo['balance'],'购物消费',session('id'));

}

} if ($orinfo['jindou'] >0 && $orinfo['isjindou'] == 1) { if($userinfo1[0]['user_wealth']-$orinfo['jindou']>=0){ $istrue = req_api("api_key", C("API_KEY"), C('USER_API') . "user/api/AddJindou/", array('user' =>session('id'),'count'=>$orinfo['jindou'],'type'=>'d')); $this->ChangeRecord(2,$orinfo['jindou'],'购物抵消',session('id')); $total1 = $total1-($orinfo['jindou']/100);

}

} $data['order_sn'] = $orderinfo['orderId']; $data['buyer_id'] = $orderinfo['certId']; $data['buyer_user'] = '银联支付'; $data['is_success'] = 'T'; $data['notify_time'] = substr($orderinfo['txnTime'],0,4)."-".substr($orderinfo['txnTime'],4,2).'-'.substr($orderinfo['txnTime'],6,2).' '.substr($orderinfo['txnTime'],8,2).':'.substr($orderinfo['txnTime'],10,2).':'.substr($orderinfo['txnTime'],12,2); $data['trade_no'] = $orderinfo['queryId']; $data['seller_id'] = $orderinfo['merId']; $data['total_fee'] = $orderinfo['txnAmt']*100; $data['sign'] = $orderinfo['signature']; $data['user_id'] = $orinfo['user_id']; $data['order_state'] = (int) $state; $data['status'] = 0; $payment->data($data)->filter('strip_tags')->add();

} $record = A('Shop/Orderrecord'); $shuju['order_state'] = (string) $state; $shuju['action_user_id'] = session('id'); $shuju['action_descrption'] = $type.'支付宝付款' . $orinfo['payable_total']; $record->ChangeOrderRecords($orinfo['_id'], $shuju); $orderrecord = A('Shop/Order'); $orderrecord->CashMoneyRecord(2, $orinfo['payable_total'], '购物消费--订单(' . $orderinfo['out_trade_no'] . ')', session('id'));

layout(false); $this->assign('orderinfo', $orinfo); $this->display('Order:PaySuccess6');

} */

/**

* 构建自动提交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()); echo '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'); echo '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)

{ $data = fopen($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'); echo 'Verify sign cert is incorrect';

} return file_get_contents($this->config['verifyCertPath']);

}

}

视图文件内容如下:

银联支付测试

银联支付测试

支付金额:

证书文件这里上传不了,放个截图好了,都可以自己去下载的:

相关推荐:

php 银行支付通道_PHP银联在线支付接口的开发实例相关推荐

  1. 第三方支付平台:银联在线支付

    前言 现将银联在线支付所需相关资料整理如下,前期资料仅涉及相关支付接口内容初步了解,不涉及具体技术实现环节. 银联商户注册所需信息 1.填写两方合作协议并打印二份盖章,一式二份(法定代表人签字盖公章并 ...

  2. Firefox全面兼容中国银联“在线支付”

    http://www.linuxdiyf.com/viewarticle.php?id=202865 来源: 驱动之家 昨日下午,中国银联正式推出了"在线支付"和"互联网 ...

  3. 银联在线支付对接流程以及签名算法

    银联在线支付 简介 银联在线支付支持PC网关.手机SDK.WAP网关.云闪付等多种支付场景,其中云闪付产品可以完美支持ApplePay.Samsung Pay.Huawei Pay等市面上常见的手机厂 ...

  4. 关于银联在线支付和短彩信接口的开发——总结

    9月份开始做用二维码做闭环的一个在线订购景区门票的项目,其中这样做是很好的,用二维码连接了线上与线下的交易和兑券.银联在线支付接口(asp.net cs)做的很好,方便调用开发.就是处理回值的时候得找 ...

  5. 银联在线php支付接口,ecshop银联在线支付接口插件(官方版)

    分享一个银联在线支付(UPOP)ecshop支付接口的插件,亲自用过.你只需放到ec对应的目录,然后进到后台"支付方式"页面安装就能调用了.希望能对你有用!! 此插件在ecshop ...

  6. java银联在线支付开发_银联在线支付案例代码

    [实例简介] 银联在线支付的测试案例代码 [实例截图] [核心代码] PayOnLine └── PayOnLine ├── src │   ├── acp_sdk.properties │   └─ ...

  7. “银联在线支付”签约无需任何条件,个人也可以完成签约

    申请条件:"银联在线支付"签约无需任何条件,个人也可以完成签约,只需要您购买我们开通好的企业支付宝,账户您自己管理,资金您自己操作(QQ3.0.5.7.1.0.4.3.9),或您也 ...

  8. html跳转qq浏览器,javascript,_银联在线支付接口,qq浏览器不能跳转,javascript - phpStudy...

    银联在线支付接口,qq浏览器不能跳转 银联在线支付接口,qq浏览器不能跳转,其他浏览器可以跳转 //html代码 提交 确认充值 //js代码 function topupmoney() { //充值 ...

  9. ECSHOP 银联在线支付 PHP 银联商务

    <?php/*** ECSHOP 银联在线支付* ======================================================================== ...

最新文章

  1. JS数组去重,JS根据数组里面的对象属性值去重
  2. 微软发布了云Bot-as-a-Service平台
  3. udp 传输文件 java_Java 网络编程 之 UDP 文件传输
  4. 关于爬虫本地JS Hook的研究
  5. (原创)shell脚本编程之---正则表达式的使用
  6. Parrot 发布新版本——基于Debian的Linux 发行版
  7. 如何启动一个本地静态服务器
  8. r720换固态硬盘后如何重装系统_联想R720重装Winddows10无法识别固态硬盘咋办
  9. 整理转载:分枝定界图解(含 Real-Time Loop Closure in 2D LIDAR SLAM论文部分解读及BB代码部分解读)
  10. 武汉大学国际软件学院夏令营笔试和面试简介
  11. 2021年六级翻译:云南
  12. 查看计算机配置在哪里,怎么看电脑配置 查看电脑配置的方法有哪些
  13. 宿命论,三年前的演讲稿!,怀念那些力不从心的光景。。
  14. 投票丨鹿晗关晓彤曝光恋情 是如何搞垮新浪服务器的
  15. ChatGPT提示词工程(六):Expanding扩展
  16. FTP网络主机间文件传输指令
  17. 以圆桌骑士为例浅尝HTML5游戏开发
  18. JAVASE——2.IO流
  19. 【原创】极验滑块验证:AST还原混淆JS
  20. org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.dxm.mapper.User

热门文章

  1. RH358管理打印机和打印文件--配置和管理打印机
  2. ico图标和制作网站(比特虫)
  3. 不小心误删注册表exe,所有exe程序无法运行
  4. 对称加密之流密码RC4
  5. porphet论文_时间序列神器之争:Prophet VS LSTM
  6. python 中画球体_python – 有效地绘制许多球体
  7. 黑苹果装机成功需要做的几件事
  8. linux dbg,linux下dbg
  9. 天天影院在线购票平台的实现(SSM)
  10. matlab 矩阵 幂运算符,matlab矩阵的乘方power运算