APP支付(支付宝和微信生成客户端签名及回调验签)

    xiaoxiao2021-12-14  19

     

    <?php namespace Pn\Controller; use Think\Controller\RestController; class PayController extends RestController{ public function __construct(){ import('Vendor.WePay.WeEncryption'); import('Vendor.WePay.Curl'); } public function Payment(){ $arr['appid'] = $_POST['appid'];//应用id $arr['userdid'] = $_POST['userdid'];//登录用户id $arr['paytype'] = $_POST['paytype'];//支付方式 $arr['productid'] = $_POST['productid'];//商品id $arr['time'] = $_POST['time']; $sign = $_POST['sign'];//安全验证sign $vsign = strrank($arr);//签名加密 if($vsign!=$sign){ $return['respCode'] = 1001; $return['msg'] = "签名错误"; $this -> response($return,'json');//返回数据 exit(); }else{ switch ($_POST["paytype"]){ case 1://支付宝 $data["signdata"] = $this->alipay(); echo json_encode($data); break; case 2://微信支付 $data = $this->wechatpay($_POST['appid'],$_POST['userdid'],$_POST['productid']); echo $data; break; default: $return["respCode"] = "error"; $return['msg'] = "支付方式错误"; $this -> response($return,'json');//返回数据 exit(); } } } /** * 微信APP客户端支付 */ public function wechatpay($appid,$userdid,$productid){ $WeEncryption = new \WeEncryption(); //实例化传输类; switch ($productid){ case 1://季付商品(¥100) $body = "陪你季付VIP";//商品描述 $total_fee = "100.00";//总金额 break; case 2://月付商品(¥50) $body = "陪你月付VIP";//商品描述 $total_fee = "50.00";//总金额 break; } $out_trade_no = date("YmdHis").rand(10,100);//商户订单号 $spbill_create_ip = getclientip();//终端IP $data = array( 'body' => $body, 'out_trade_no' => $out_trade_no, 'total_fee' => $total_fee, 'spbill_create_ip' => $spbill_create_ip, ); $encpt = $WeEncryption::getInstance(); //实例化签名类 $url = "http://xxxx.com/Pay/wx_notify_verify"; $encpt->setNotifyUrl($url); //设置异步通知地址 $curl = new \Curl(); //实例化传输类; $xml_data = $encpt->sendRequest($curl, $data); //发送请求 $postObj = $encpt->xmlToObject($xml_data); //解析返回数据 if ($postObj === false) { echo 'FAIL'; exit; } if ($postObj->return_code == 'FAIL') { echo $postObj->return_msg; } else { $resignData = array( 'appid' => $postObj->appid, 'partnerid' => $postObj->mch_id, 'prepayid' => $postObj->prepay_id, 'noncestr' => $postObj->nonce_str, 'timestamp' => time(), 'package' => 'Sign=WXPay' ); $sign = $encpt->getClientPay($resignData); $resignData['sign'] = $sign; return json_encode($resignData); } } /** * 微信App支付回调 */ public function wx_notify_verify(){ $WeEncryption = new \WeEncryption(); //实例化传输类; $encpt = $WeEncryption::getInstance(); $obj = $encpt->getNotifyData(); if ($obj === false) { exit; } if ($obj) { $data = array( 'appid' => $obj->appid, 'mch_id' => $obj->mch_id, 'nonce_str' => $obj->nonce_str, 'result_code' => $obj->result_code, 'openid' => $obj->openid, 'trade_type' => $obj->trade_type, 'bank_type' => $obj->bank_type, 'total_fee' => $obj->total_fee, 'cash_fee' => $obj->cash_fee, 'transaction_id' => $obj->transaction_id, 'out_trade_no' => $obj->out_trade_no, 'time_end' => $obj->time_end ); $sign = $encpt->getSign($data); if ($sign == $obj->sign) {//验签通过 $reply = "<xml> <return_code><![CDATA[SUCCESS]]></return_code> <return_msg><![CDATA[OK]]></return_msg> </xml>"; echo $reply; exit; }else{ $reply = "<xml> <return_code><![CDATA[FAIL]]></return_code> <return_msg><![CDATA[NO]]></return_msg> </xml>"; echo $reply; exit; } } } /** * https://doc.open.alipay.com/doc2/detail.htm?spm=a219a.7629140.0.0.NgdeQA&treeId=59&articleId=103663&docType=1 * 服务端生成app支付使用的参数以及签名 * @param $params <Array> * @return <Array> */ public function alipay(){ $ali = array( 'service' => 'mobile.securitypay.pay', 'partner' => 'xxxx', '_input_charset' => 'utf-8', 'sign_type' => 'RSA', 'sign' => '', 'notify_url' => 'http://xxxxxxxx.com/Pay/alipay_notify_url',//回调地址 'out_trade_no' => date("YmdHis").rand(10,100),//商户网站唯一订单号 'subject' => '测试',//商品名称 'payment_type' => 1,//支付类型 'seller_id' => 'lql@jieku.com',//支付宝账号 'total_fee' => '0.01',//总金额 'body' => 'Iphone6 16G',//商品详情 ); $ali = self::argSort($ali); $str = ''; foreach($ali as $key=>$val){ if($key == 'sign_type' || $key == 'sign'){ continue; }else{ if($str == ''){ $str = $key.'='.'"'.$val.'"'; }else{ $str = $str.'&'.$key.'='.'"'.$val.'"'; } } } $sign = urlencode(self::sign($str)); $str = $str.'&sign='.'"'.$sign.'"'.'&sign_type='.'"'.$ali['sign_type'].'"';//传给支付宝接口的数据 return $str; } /** * 准备签名参数 */ public function argSort($para) { ksort($para); reset($para); return $para; } /** * 生成请求参数的签名 * @param $params <Array> * @return <String> * */ public function sign($data) { //读取私钥文件 $priKey = file_get_contents('./Public/key/rsa_private_key.pem');//私钥文件路径 //转换为openssl密钥,必须是没有经过pkcs8转换的私钥 $res = openssl_get_privatekey($priKey); //调用openssl内置签名方法,生成签名$sign openssl_sign($data, $sign, $res); //释放资源 openssl_free_key($res); //base64编码 $sign = base64_encode($sign); return $sign; } /** * 支付宝回调地址 */ public function alipay_notify_url(){ $orderpay = M("orderpay"); $async = empty($_GET); $data = $async ? $_POST : $_GET; if (empty($data)) { return FALSE; } $signValid = $this->verifyParameters($data, $data["sign"]);//验签 $notify_id = isset($data['notify_id']) ? $data['notify_id'] : NULL; //获取支付宝远程服务器ATN结果(验证是否是支付宝发来的消息) $responseTxt = 'true'; if (!empty($notify_id)) { $responseTxt = $this->verifyFromServer($notify_id); } if($signValid && preg_match("/true$/i", $responseTxt)){//验证成功 if($_POST['trade_status'] == 'TRADE_FINISHED'){ $_POST["createdatetime"] = time(); if($orderpay->create()){ $orderpay->add(); echo "success"; }else{ echo "fail";//验证失败 } } else if ($_POST['trade_status'] == 'TRADE_SUCCESS') { $_POST["createdatetime"] = time(); if($orderpay->create()){ $orderpay->add(); echo "success"; }else{ echo "fail";//验证失败 } } }else{ echo "fail";//验证失败 } } /** * 将剩下参数进行url_decode, 然后进行字典排序,组成字符串,得到待签名字符串 * @param unknown $params * @param unknown $sign * @return boolean */ function verifyParameters($params, $sign) { $public_key_path = './Public/key/alipay_public_key.pem';//公钥(合作伙伴) $params = $this->filterSignParameter($params); ksort($params); reset($params); $content = urldecode(http_build_query($params)); return $this->rsaVerify($content, $public_key_path, $sign); } /** * 过滤参数,去除sign/sign_type参数 * @param $params * @return <Array> */ function filterSignParameter($params) { $result = array(); foreach ($params as $key => $value) { if ($key != 'sign' && $key != 'sign_type' && $value) { $result[$key] = $value; } } return $result; } /** * RSA验签,注意验签的公钥是支付宝的公钥,不是自己生成的rsa公钥,可以在淘宝的demo中获得 * @param $data string 待签名数据 * @param $ali_public_key_path string 支付宝的公钥文件路径 * @param $sign string 要校对的的签名结果 * @return <Boolean> 验证结果 * @throws Exception */ function rsaVerify($data, $ali_public_key_path, $sign) { $pubKey = file_get_contents($ali_public_key_path); $res = openssl_get_publickey($pubKey); if(!$res){ throw new \Exception('公钥格式错误'); } $result = (bool)openssl_verify($data, base64_decode($sign), $res); openssl_free_key($res); return $result; } function verifyFromServer($notify_id) { $transport = "http"; $partner = "xxxxxxxxxxx"; $cacert = "./Public/key/cacert.pem"; $transport = strtolower(trim($transport)); $partner = trim($partner); $veryfy_url = "http://notify.alipay.com/trade/notify_query.do?partner=$partner¬ify_id=$notify_id"; $curl = curl_init($veryfy_url); curl_setopt($curl, CURLOPT_HEADER, 0); // 过滤HTTP头 curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);//SSL证书认证 curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);//严格认证 curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);// 显示输出结果 curl_setopt($curl, CURLOPT_CAINFO, $cacert);//证书地址 $responseText = curl_exec($curl); // var_dump( curl_error($curl) );//如果执行curl过程中出现异常,可打开此开关,以便查看异常内容 curl_close($curl); return $responseText; }   /**格式化公钥     * $pubKey PKCS#1格式的公钥串     * return pem格式公钥, 可以保存为.pem文件     */    function formatPubKey($pubKey) {        $fKey = "-----BEGIN PUBLIC KEY-----\n";        $len = strlen($pubKey);        for($i = 0; $i < $len; ) {            $fKey = $fKey . substr($pubKey, $i, 64) . "\n";            $i += 64;        }        $fKey .= "-----END PUBLIC KEY-----";        return $fKey;    } } 问题咨询QQ1370373713http://blog.csdn.net/apensu/article/details/46945193

     

    转载请注明原文地址: https://ju.6miu.com/read-963618.html

    最新回复(0)