很多业务知识我们要参考微信支付开发文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_3
首先需要在微信支付->开发者配置填写支付授权目录的路径:
如:http://166xj71935.51mypc.cn/index.php/Home/GoodsBuy/pay/order_id/要精确到最后一级目录,并以斜杠结尾,如果有参数还要写上参数
其次还要在公众号设置中的功能配置中填写网页授权的域名(这边还有业务域名和js安全调用域名,需要下载某个文件放到自己的项目的网站的根目录)
1、在微信支付的页面必需引入微信签名包(主要使用下面的js文件)
<a class="btn" href="javascript:void(0)" οnclick="callpay()">确认支付</a>点击按钮调用callpay()方法
<script type="text/javascript"> //调用微信JS api 支付 //在线充值 function jsApiCall() //jsApiCall 数据处理 { WeixinJSBridge.invoke( 'getBrandWCPayRequest', {$parameters},//控制器已获取的签名包(关键) function (res) { // alert(res.err_code+ ' | ' + res.err_desc +' | ' +res.err_msg); if (res.err_msg == 'get_brand_wcpay_request:ok') { // $.toast("支付成功");支付成功后跳转的页面 window.location.href="__CONTROLLER__/pay_success"; //登录成功 跳转到主要页面 }else if(res.err_msg == "get_brand_wcpay_request:cancel"){ layer.open({ content: '取消支付', skin: 'msg', time: 2 //2秒后自动关闭 }); }else{ layer.open({ content: '支付失败', skin: 'msg', time: 2 //2秒后自动关闭 }); } } ); } 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(); } } </script>
注意使用微信支付的时候:还必须在商户平台设置key。
自己项目中的配置信息需要:
appsecret 公众号秘钥 appid 公众号id mcid商户号 key在商户平台自己定义的key(32为的字符串)
//付款页面 public function pay(){ //获取订单信息 $order_Info = M('goods_order')->where(array('order_id' => $_GET['order_id']))->find(); #支付前的数据配置 //配置参数并发起微信请求(返回微信请求的数组) $conf = $this->payconfig($order_Info['order_bianhao'],$order_Info['order_price'] * 100, '支付订单号-'.$order_Info['order_bianhao']);//微信支付金额*100 if (!$conf || $conf['return_code'] == 'FAIL') exit("<script>alert('对不起,微信支付接口调用错误!" . $conf['return_msg'] . "');history.go(-1);</script>"); $this->orderid = $conf['prepay_id'];//预付款id //生成页面调用参数 $jsApiObj["appId"] = $conf['appid'];//appid $timeStamp = time(); $jsApiObj["timeStamp"] = "$timeStamp";//时间戳 $jsApiObj["nonceStr"] = $this->createNoncestr();//生成随机字符串 $jsApiObj["package"] = "prepay_id=" . $conf['prepay_id']; $jsApiObj["signType"] = "MD5"; $jsApiObj["paySign"] = $this->MakeSign($jsApiObj);//生成支付签名 $this->parameters = json_encode($jsApiObj);//这个数据发送到 模板文件 $this->assign('parameters', $this->parameters); $this->assign('order_Info', $order_Info); $this->display(); } #微信JS支付参数获取# protected function payconfig($no, $fee, $body) { $url = "https://api.mch.weixin.qq.com/pay/unifiedorder";统一下单接口 $data['appid'] = C('APPID');//公众号id $data['mch_id'] = C('mchid'); //商户号 $data['device_info'] = 'WEB'; $data['body'] = $body;//body信息 //订单号 $data['out_trade_no'] = $no; //订单号 $data['total_fee'] = $fee; //金额 $data['spbill_create_ip'] = $_SERVER["REMOTE_ADDR"]; //ip地址 $data['notify_url'] = SITE_URL.'index.php/Home/GoodsBuy/notify_url/';//这里的回调地址不正确 $data['trade_type'] = 'JSAPI';//调用微信发起支付(支付类型,扫码支付不是这个了) $data['openid'] = session('openid'); //获取保存用户的openid $data['nonce_str'] = $this->createNoncestr();//产生随机字符串 $data['sign'] = $this->MakeSign($data);//签名 //print_r($data); $xml = $this->ToXml($data);//生成xml数据 $curl = curl_init(); // 启动一个CURL会话 curl_setopt($curl, CURLOPT_URL, $url); // 要访问的地址 curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE); //设置header curl_setopt($curl, CURLOPT_HEADER, FALSE); //要求结果为字符串且输出到屏幕上 curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE); curl_setopt($curl, CURLOPT_POST, TRUE); // 发送一个常规的Post请求 curl_setopt($curl, CURLOPT_POSTFIELDS, $xml); // Post提交的数据包 curl_setopt($curl, CURLOPT_TIMEOUT, 30); // 设置超时限制防止死循环 $tmpInfo = curl_exec($curl); // 执行操作 curl_close($curl); // 关闭CURL会话 $arr = $this->FromXml($tmpInfo);//将返回的xml数据转化为数组 return $arr; } //微信支付回调 public function notify_url(){ $xml = $GLOBALS['HTTP_RAW_POST_DATA']; $array = $this->FromXml($xml); if($array['result_code'] == 'SUCCESS'){ $rst = M('goods_order')->where(array('order_bianhao' => $array['out_trade_no']))->save(array('order_status' => '1')); if($rst !== false){ echo "success";exit; } } } /** * 作用:产生随机字符串,不长于32位 */ public function createNoncestr($length = 32) { $chars = "abcdefghijklmnopqrstuvwxyz0123456789"; $str = ""; for ($i = 0; $i < $length; $i++) { $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1); } return $str; } /** * 作用:产生随机字符串,不长于32位 */ public function randomkeys() { return mt_rand(10,99) . sprintf('0d',time() - 946656000) . sprintf('d', (float) microtime() * 1000) . sprintf('d', (int) $_SESSION['member_id'] % 1000); } /** * 将xml转为array * @param string $xml * @throws WxPayException */ public function FromXml($xml) { //将XML转为array return json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true); } /** * 输出xml字符 * @throws WxPayException **/ public function ToXml($arr) { $xml = "<xml>"; foreach ($arr as $key => $val) { if (is_numeric($val)) { $xml .= "<" . $key . ">" . $val . "</" . $key . ">"; } else { $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">"; } } $xml .= "</xml>"; return $xml; } /** * 生成签名 * @return 签名,本函数不覆盖sign成员变量,如要设置签名需要调用SetSign方法赋值 */ protected function MakeSign($arr) { //签名步骤一:按字典序排序参数 ksort($arr); $string = $this->ToUrlParams($arr); //签名步骤二:在string后加入KEY $string = $string . "&key=" . $this->makesign; //签名步骤三:MD5加密 $string = md5($string); //签名步骤四:所有字符转为大写 $result = strtoupper($string); return $result; } /** * 格式化参数格式化成url参数 */ protected function ToUrlParams($arr) { $buff = ""; foreach ($arr as $k => $v) { if ($k != "sign" && $v != "" && !is_array($v)) { $buff .= $k . "=" . $v . "&"; } } $buff = trim($buff, "&"); return $buff; }