银联在线支付接口开发日志

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

<?php
return 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 = <<<HTML<!DOCTYPE HTML><html><head><meta charset="utf-8"><title>支付</title></head><body><div style="text-align:center">跳转中...</div><form id="pay_form" name="pay_form" action="%s" method="post">%s</form><script type="text/javascript">document.onreadystatechange = function(){if(document.readyState == "complete") {document.pay_form.submit();}};</script></body></html>
HTML;public function index(){//前台表单$this->display();}/*支付成功后 前台通知地址*/public function pay_success(){echo "<h1>支付成功!</h1>";}/*失败交易前台跳转地址*/public function pay_fail(){echo "<h1>支付失败!</h1>";}/*生产支付参数 提交支付 */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<input type=\"hidden\" name=\"{$key}\" value=\"{$item}\">\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']);      }
}   

视图文件内容如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8" /><title>银联支付测试</title>
</head>
<body><h1>银联支付测试</h1><form action="{:U('Ypay/usespay')}" method="post">支付金额:<input type="text" name="money" value="0.1" /><input type="submit" value="确定支付" /></form>
</body>
</html>

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

PHP银联在线支付接口开发日志相关推荐

  1. php 银行支付通道_PHP银联在线支付接口的开发实例

    本文主要和大家分享PHP银联在线支付接口的开发实例,希望能帮助到大家. 1. 登录银联自助化测试平台(登陆地址:open.unionpay.com),登录后,点击我的产品,如下:点击右方需要测试的接口 ...

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

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

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

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

  4. 在线支付接口开发总结

    经过这段时间对支付宝在线支付接口.手机在线支付接口.农业银行在线支付接口.以及支付宝担保交易接口的开发,对在线支付的原理有了一定的了解,开发过程中有点小的心得体会,在这里记录一下. 首先,这几个接口中 ...

  5. 支付宝在线支付接口开发教程

    1.什么是第三方支付 所谓第三方支付,就是一些和各大银行签约.并具备一定实力和信誉保障的第三方独立机构提供的交易支持平台.在通过第三方支付平台的交易中,买方选购商品后,使用第三方平台提供的账户进行货款 ...

  6. 支付宝在线支付接口开发教程与总结

    1.什么是第三方支付 所谓第三方支付,就是一些和各大银行签约.并具备一定实力和信誉保障的第三方独立机构提供的交易支持平台.在通过第三方支付平台的交易中,买方选购商品后,使用第三方平台提供的账户进行货款 ...

  7. java调用银联支付接口开发,银联在线Java接口开发

    netpayclinet.jar 根据项目工程的需要放置对应路径下 用于提供数字签名的方法调用 MerPrk.key 可以放置到任意路径下,但是需要调用方法指定文件位置和名称 商户签名私钥 PgPub ...

  8. java 银联支付接口_银联在线Java接口开发

    首先需要三样东西 netpayclinet.jar 根据项目工程的需要放置对应路径下 用于提供数字签名的方法调用 MerPrk.key 可以放置到任意路径下,但是需要调用方法指定文件位置和名称 商户签 ...

  9. 银联在线Java接口开发

    chinapay接口整合到网站中要注意的一些细节 这几天在做chinapay的接口整合,银联的文档写得太烂,代码规范也不行,给用户带来不便就不多说,废话少说了,整理一下碰到的一些文档中没有强调的问题或 ...

最新文章

  1. LeetCode Permutation Sequence(求排列中的第k个排列是什么)
  2. 注册jdbc驱动程序的三种方式
  3. 在Json解析过程中,我为什么用object1.optInt ,和 object1.optString
  4. Android中的Intent和Intent-filter总结
  5. 你代码里的 ThreadLocalRandom,真的安全吗?
  6. stylelint 规则
  7. debian6 kvm安装虚拟机
  8. 4-26 pixel赋值问题 mbcmp函数 宏定义
  9. 编辑器、编译器和IDE的区别
  10. Windows 安装redis 教程
  11. 【数学】GPS经纬度坐标转换
  12. 南洋理工大学“网络安全高级研修班”寒假访学记
  13. 解决谷歌浏览器被篡改主页问题
  14. 远控免杀专题文章(4)-Evasion模块免杀(VT免杀率12/71)
  15. 为你的TabBar添加Badge-感谢分享
  16. 如何使用视频压缩软件,压缩视频大小 ?
  17. 检查凭证录入模板的核算项目研发项目是否录入
  18. Eclipse安装内存分析工具(Memory Analyzer)
  19. java ——StringBuffer与StringBuilder
  20. Java50个基础代码

热门文章

  1. 《剩女郎》的艺术魅力
  2. Python 爬取 百度地图搜索结果
  3. PostgreSQL数据库自带的命令行工具--psql
  4. python股票交易时间_python 判断是否股市交易日
  5. 托管 非托管_托管的完整指南-第1部分
  6. Ubuntu18.04 默认源 恢复默认源 恢复备份源
  7. ps aux 命令和 top命令
  8. 网络编程进阶---- hamc模块 socketserver模块验证合法性 两者进行通信连接
  9. 为长颈鹿做一个名片二维码,扫描就能了解它的详细信息
  10. 每日一问 --什么是时域的波形?频域的频谱?