重构封装微信服务号支付接口
微信支付支付接口提供sdk太多,太复杂,修改很不方便,于是自已重新封装,支付测试成功!
1 微信支付数据配置
2 unifiedorder() 支付方法 ,notify() 微信支付结果通知回调
微信支付,有太多的坑,需要技术支持联系我QQ2420355482
<?php namespace app\index\controller; class WxPay extends Common { private $config; //前置操作 public function _initialize() { $this->config = $this->config(); } //微信支付数据配置 private function config() { $config = array(); $config['appid']= '请填写'; //微信分配的公众账号ID $config['MerchantId'] = '请填写'; //商户号 $config['key'] = '请填写'; //商户支付密钥 $config['notify_url'] = '请填写'; //接收微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数。 return $config; } public function unifiedorder($orderData=array()) { $input = array(); //自定义订单数据 $input['attach'] = '支付测试'; //附加数据,在查询API和支付通知中原样返回,该字段主要用于商户携带订单的自定义数据 $input['body'] = '支付测试'; //商品简单描述 $input['openid'] = 'onXiXv-af8He2UkIqovTBwWfAmF8'; //接收微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数。 $input['out_trade_no'] = '14156599995568'; //商户系统内部的订单号,32个字符内、可包含字母, $input['total_fee'] = 1; //订单总金额,单位为分 //配置数据 $input['appid'] = $this->config['appid']; //微信分配的公众账号ID 支付测试 $input['mch_id'] = $this->config['MerchantId']; //微信支付分配的商户号 $input['notify_url'] = $this->config['notify_url']; //接收微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数。 //预置数据 $input['spbill_create_ip'] = $_SERVER['REMOTE_ADDR']; //终端ip $input['nonce_str'] = $this->getNonceStr(); //随机字符串 $input['trade_type'] = 'JSAPI'; //JSAPI支付的交易类型为MWEB $input['time_start']= date("YmdHis"); //设置订单生成时间,格式为yyyyMMddHHmmss,如2009年12月25日9点10分10秒表示为20091225091010。 $input['time_expire']= date("YmdHis", time() + 600); //设置订单失效时间,格式为yyyyMMddHHmmss,如2009年12月27日9点10分10秒表示为20091227091010。// $input['sign'] = $this->sign($input); //获取签名 $data = $this->ToXml($input); //提交的xml格式数据 $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder'; //统一下单接口 $res = $this->postXmlCurl($data,$url); //psot提交 $jsApiParameters = $this->GetJsApiParameters($res); //获取jsapi支付的参数 $this->assign('jsApiParameters',$jsApiParameters); return view(); } //微信支付结果通知回调 public function notify() { if(request()->isPost()){ $xml = file_get_contents("php://input"); //将xml转化为json格式 $xml = json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)); //转成数组 $result = json_decode($xml, true); if($result){ if($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS'){ //支付成功操作 return true; }else{ //支付失败操作 return false; } } } } //签名 private function sign($value){ //签名步骤一:按字典序排序参数 ksort($value); //--格式化参数格式化成url参数 $buff = ""; foreach ($value as $k => $v) { if($k != "sign" && $v != "" && !is_array($v)){ $buff .= $k . "=" . $v . "&"; } } $buff = trim($buff, "&"); $string = $buff; //签名步骤二:在string后加入KEY $string = $string . "&key=".$this->config['key']; //签名步骤三:MD5加密或者HMAC-SHA256 //$string =hash_hmac("sha256",$string,$key); $string = md5($string); //签名步骤四:所有字符转为大写 $result = strtoupper($string); //将据转换为xml格式 // $value['sign'] = $result; // $xmlData = $this->ToXml($value); // dump($xmlData); return $result; } /** * 输出xml字符 * @throws WxPayException **/ public function ToXml($value) { if(!is_array($value) || count($value) <= 0) { throw new WxPayException("数组数据异常!"); } $xml = "<xml>"; foreach ($value as $key=>$val) { if (is_numeric($val)){ $xml.="<".$key.">".$val."</".$key.">"; }else{ $xml.="<".$key."><![CDATA[".$val."]]></".$key.">"; } } $xml.="</xml>"; return $xml; } /* * 以post方式提交xml到对应的接口url * * @param string $xml 需要post的xml数据 * @param string $url url 提交的接口地址 * @param int $second url执行超时时间,默认30s * @throws WxPayException */ private static function postXmlCurl($xml, $url, $second = 30) { $ch = curl_init(); curl_setopt($ch, CURLOPT_TIMEOUT, $second);//设置超时 curl_setopt($ch,CURLOPT_URL, $url); //指定URL curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,TRUE); //忽略证书 curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,false);//忽略证书 curl_setopt($ch, CURLOPT_HEADER, FALSE); //忽略header头信息 curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); //设定请求后返回结果 //post提交方式 curl_setopt($ch, CURLOPT_POST, TRUE); curl_setopt($ch, CURLOPT_POSTFIELDS, $xml); //运行curl $data = curl_exec($ch); //返回结果 if($data){ curl_close($ch); return $data; } else { $error = curl_errno($ch); curl_close($ch); throw new WxPayException("curl出错,错误码:$error"); } } /** * * 产生随机字符串,不长于32位 * @param int $length * @return 产生的随机字符串 */ public static function getNonceStr($length = 32) { $chars = "abcdefghijklmnopqrstuvwxyz0123456789"; $str =""; for ( $i = 0; $i < $length; $i++ ) { $str .= substr($chars, mt_rand(0, strlen($chars)-1), 1); } return $str; } /** * 获取毫秒级别的时间戳 */ private static function getMillisecond() { //获取毫秒的时间戳 $time = explode ( " ", microtime () ); $time = $time[1] . ($time[0] * 1000); $time2 = explode( ".", $time ); $time = $time2[0]; return $time; } //获取jsapi支付的参数,将xml数据转为json public function GetJsApiParameters($xml){ $arr = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true); //dump($arr); $data = array(); $data['appId'] = $arr['appid']; $data['nonceStr'] = $this->getMillisecond(); $data['package'] = 'prepay_id='.$arr['prepay_id']; $data['signType'] = 'MD5'; $data['timeStamp'] =$this->getMillisecond(); $data['paySign'] = $this->sign($data); //二次签名 return json_encode($data); } }
前端js发起支付
<script type="text/javascript"> // //调用微信JS api 支付 function jsApiCall() { WeixinJSBridge.invoke( 'getBrandWCPayRequest', {$jsApiParameters}, function(res){ if(res.err_msg == "get_brand_wcpay_request:ok"){ paySuccess(); }else{ payFail(); } } ); } function callpay() { if (typeof WeixinJSBridge == "undefined"){ if( document.addEventListener ){ document.addEventListener('WeixinJSBridgeReady', jsApiCall, false); }else if (document.attachEvent){ document.attachEvent('WeixinJSBridgeReady', jsApiCall); document.attachEvent('onWeixinJSBridgeReady', jsApiCall); } }else{ jsApiCall(); } } //支付成功 function paySuccess() { //进行操作 } //支付失败 function payFail() { //进行操作 } //获取get参数 function getQueryVariable(variable){ var query = window.location.search.substring(1); var vars = query.split("&"); for (var i=0;i<vars.length;i++) { var pair = vars[i].split("="); if(pair[0] == variable){return pair[1];} } return(false); } callpay(); //发起支付 </script>