Development example of PHP UnionPay online payment interface
This article mainly shares with you the development examples of PHP UnionPay online payment interface, hoping to help everyone.
1. Log in to the UnionPay self-service test platform (login address: open.unionpay.com). After logging in, click on My Products, as follows: Click on the interface to be tested on the right. In this example, mobile web payment is used ( WAP payment) as an example.
2. Click on the test parameters on the left menu to see the parameters required for the test process, as shown below: Click on the test certificate to download two certificates. One is a private key certificate with the suffix .pfx, and the other is a public key certificate with the suffix .cer. After downloading them, the name of the private key certificate file is changed to acp_test_sign.pfx. Or if you don’t download it, you can just use this example directly. In the TP3.2 example, Public/cer already contains all certificate files.
3. There is relevant code in the TP3.2 example that can be used for testing. Please use the parameters of the test environment when testing. There are comments in the code. Before you start, make sure that your environment's PHP version is based on 5.3. You need to enable the curl and openssl functions, and the test must be done online. Local virtual domain names will not work. If you encounter any problems, you can refer to the official instructions. There is a PHP Version SDK in this folder, which is an official document. Just refer to the instructions inside. Their example couldn't run when I tested it. I don't know what happened. reason.
4. Switch to the production environment and pay attention to the following issues:
4.1 First, according to the instructions in the merchant activation email you received, visit the website http://cs.cfca.com.cn/
Download the production Certificate file:
After clicking download, after the download operation is completed, a successful download prompt will appear on the page. The downloaded certificate is automatically stored in IE. The next step is to export the certificate.
4.2 Export the certificate file: Open the IE browser, click the gear in the upper right corner, open Tools=》Internet Options=》Content=》Certificate, as shown in the picture:
After clicking on the certificate, find the certificate you just downloaded. You can identify it by its name. It is marked in the merchant’s email:
The name marked in red in the picture above should be the same as the name you downloaded. Same.
Find it and click Export: The next step along the way, you need to pay attention to the following steps
Upload the acp_prod_sign.pfx file you just exported and click Upload.
Next step, download the UnionPay public key
Unzip the file and put the two certificates inside also into /Public/cer. Then go to config.php and switch to the production environment according to the file comments.
The following is the code information of 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', //交易币种 ), );?>
The controller code is as follows:
<?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> <meta> <title>支付</title> <p>跳转中...</p>
支付成功!
"; } /*失败交易前台跳转地址*/ 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'] 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']); } }The content of the view file is as follows:
nbsp;html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <meta> <title>银联支付测试</title> <h1 id="银联支付测试">银联支付测试</h1>
The certificate file cannot be uploaded here, so just put a screenshot, and you can download it yourself:
Related Recommended:
The above is the detailed content of Development example of PHP UnionPay online payment interface. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics



PHP 8.4 brings several new features, security improvements, and performance improvements with healthy amounts of feature deprecations and removals. This guide explains how to install PHP 8.4 or upgrade to PHP 8.4 on Ubuntu, Debian, or their derivati

Visual Studio Code, also known as VS Code, is a free source code editor — or integrated development environment (IDE) — available for all major operating systems. With a large collection of extensions for many programming languages, VS Code can be c

If you are an experienced PHP developer, you might have the feeling that you’ve been there and done that already.You have developed a significant number of applications, debugged millions of lines of code, and tweaked a bunch of scripts to achieve op

This tutorial demonstrates how to efficiently process XML documents using PHP. XML (eXtensible Markup Language) is a versatile text-based markup language designed for both human readability and machine parsing. It's commonly used for data storage an

JWT is an open standard based on JSON, used to securely transmit information between parties, mainly for identity authentication and information exchange. 1. JWT consists of three parts: Header, Payload and Signature. 2. The working principle of JWT includes three steps: generating JWT, verifying JWT and parsing Payload. 3. When using JWT for authentication in PHP, JWT can be generated and verified, and user role and permission information can be included in advanced usage. 4. Common errors include signature verification failure, token expiration, and payload oversized. Debugging skills include using debugging tools and logging. 5. Performance optimization and best practices include using appropriate signature algorithms, setting validity periods reasonably,

A string is a sequence of characters, including letters, numbers, and symbols. This tutorial will learn how to calculate the number of vowels in a given string in PHP using different methods. The vowels in English are a, e, i, o, u, and they can be uppercase or lowercase. What is a vowel? Vowels are alphabetic characters that represent a specific pronunciation. There are five vowels in English, including uppercase and lowercase: a, e, i, o, u Example 1 Input: String = "Tutorialspoint" Output: 6 explain The vowels in the string "Tutorialspoint" are u, o, i, a, o, i. There are 6 yuan in total

Static binding (static::) implements late static binding (LSB) in PHP, allowing calling classes to be referenced in static contexts rather than defining classes. 1) The parsing process is performed at runtime, 2) Look up the call class in the inheritance relationship, 3) It may bring performance overhead.

What are the magic methods of PHP? PHP's magic methods include: 1.\_\_construct, used to initialize objects; 2.\_\_destruct, used to clean up resources; 3.\_\_call, handle non-existent method calls; 4.\_\_get, implement dynamic attribute access; 5.\_\_set, implement dynamic attribute settings. These methods are automatically called in certain situations, improving code flexibility and efficiency.
