微信支付首先要有一个微信公众号和一个微信商户号。我们需要在其中进行设置授权域名。和账号信息获取。
-
在微信公众号中获取,AppId 和 AppSecret.
-
配置网页授权域名。在公众号功能设置模块。其中的js接口安全域名必须要是你使用js调起支付文件的上级目录如
你的js调起支付文件是wcjspay.php,其目录是www.domain.com/wchat/pay/wcjspay.php那么js接口安全域名就要为
www.domain.com/wchat/pay
-
设置网页授权目录这个只需为你的网站根目录即可。
-
在微信商户号中的开发配置中设置授权目录这个和第二步中的一样。在商户号中还要获取到商户号的id 密钥这两个在
开户邮箱中有
-
接下来就是接入支付了下面是php源代码
1.这是调起js支付的代码文件(wcjspay.php)
<?php ini_set('date.timezone','Asia/Shanghai'); require_once "./lib/wclib.php"; require_once "./lib/config.php"; //new 一个工具类。(位于/lib/wclib.php) $tools = new JsApiPay(); //获取openid $openid = $tools->GetOpenid(); //这里需要自行设置参数。 //设置统一下单的数据 $order['body'] = "腾讯充值中心-QQ会员充值"; $order['attach'] = "深圳分店"; $order['out_trade_no'] = WxPayConfig::MCHID.date("YmdHis"); //下单金额 $order['total_fee'] = "1"; $order['time_start']=date("YmdHis"); $order['time_expire']=date("YmdHis", time() + 600); //支付成功后微信返回信息的接收处理页面。 $order['notify_url'] = ""; $order['trade_type']="JSAPI"; $order['openid'] = $openid; //商户号id $order['mch_id'] = WxPayConfig::MCHID; // 公众号id $order['appid'] = WxPayConfig::APPID; //用户端ip $order['spbill_create_ip'] = $_SERVER['REMOTE_ADDR']; //生成随机字符串 $order['nonce_str'] = $tools-> getNonceStr(); //生成签名 $order['sign'] = $tools->MakeSign($order); //将数据转换为xml格式 $xml_order = $tools->ToXml($order); //将数据发送给微信接口并获取返回值。 $result = $tools->unifiedorder($xml_order); //将返回的数据包装成json格式传给微信浏览器内置的js方法,从而调起支付界面。(即我们输入支付密码的界面) //这里返回的是json数据。下面的js代码是微信浏览器内置的。将会使用到此json参数。调起支付。 $jsApiParameters = $tools->GetJsApiParameters($result); //下面的js就是微信内置的调起支付函数。只有微信浏览器能够识别。 ?> <html> <head> <meta http-equiv="content-type" content="text/html;charset=utf-8"/> <meta name="viewport" content="width=device-width, initial-scale=1"/> <script type="text/javascript"> //调用微信JS api 支付 function jsApiCall() { //只能在微信的内置浏览器中使用此js函数。 WeixinJSBridge.invoke( 'getBrandWCPayRequest', <?php echo $jsApiParameters; ?>, function(res){ WeixinJSBridge.log(res.err_msg); alert(res.err_code+res.err_desc+res.err_msg); } ); } 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> <script type="text/javascript"> //获取共享地址 function editAddress() { WeixinJSBridge.invoke( 'editAddress', <?php echo $editAddress; ?>, function(res){ var value1 = res.proviceFirstStageName; var value2 = res.addressCitySecondStageName; var value3 = res.addressCountiesThirdStageName; var value4 = res.addressDetailInfo; var tel = res.telNumber; alert(value1 + value2 + value3 + value4 + ":" + tel); } ); } window.onload = function(){ if (typeof WeixinJSBridge == "undefined"){ if( document.addEventListener ){ document.addEventListener('WeixinJSBridgeReady', editAddress, false); }else if (document.attachEvent){ document.attachEvent('WeixinJSBridgeReady', editAddress); document.attachEvent('onWeixinJSBridgeReady', editAddress); } }else{ editAddress(); } }; </script> </head> <body> <br/> <font color="#9ACD32"><b>该笔订单支付金额为<span style="color:#f00;font-size:50px">1分</span>钱</b></font><br/><br/> <div align="center"> <button style="width:210px; height:50px; border-radius: 15px;background-color:#FE6714; border:0px #FE6714 solid; cursor: pointer; color:white; font-size:16px;" type="button" οnclick="callpay()" >立即支付</button> </div> </body> </html>
2.下面是位于lib文件夹中的功能函数文件配置文件和证书文件(证书文件请自行下载)
wclib.php文件
注意在此文件中使用了php 的curl模块。如果php没有安装此模块运行会出错。
<?php //require_once "./config.php"; class JsApiPay { //获取用户openid public function GetOpenid() { //通过code获得openid if (!isset($_GET['code'])){ //触发微信返回code码 $baseUrl = urlencode('http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'].$_SERVER['QUERY_STRING']); $url = $this->__CreateOauthUrlForCode($baseUrl); Header("Location: $url"); exit(); } else { //获取code码,以获取openid $code = $_GET['code']; $openid = $this->GetOpenidFromMp($code); return $openid; } } //通过code获取openid public function GetOpenidFromMp($code) { $url = $this->__CreateOauthUrlForOpenid($code); //初始化curl $ch = curl_init(); //设置超时 curl_setopt($ch, CURLOPT_TIMEOUT, $this->curl_timeout); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,FALSE); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST,FALSE); curl_setopt($ch, CURLOPT_HEADER, FALSE); curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); //运行curl,结果以json形式返回 $res = curl_exec($ch); curl_close($ch); //取出openid $data = json_decode($res,true); $openid = $data['openid']; return $openid; } //获取jsapi支付的参数 public function GetJsApiParameters($UnifiedOrderResult) { $jsapi_data['appId'] = $UnifiedOrderResult["appid"]; $jsapi_data['nonceStr'] = $this->getNonceStr(); $jsapi_data['package'] = "prepay_id=" . $UnifiedOrderResult['prepay_id']; $jsapi_data['signType'] = "MD5"; $jsapi_data['timeStamp'] = time(); $jsapi_data['paySign'] = $this->MakeSign($jsapi_data,WxPayConfig::KEY); $parameters = json_encode($jsapi_data); return $parameters; } // 构造获取code的url连接 public function __CreateOauthUrlForCode($redirectUrl) { $urlObj["appid"] = WxPayConfig::APPID; $urlObj["redirect_uri"] = "$redirectUrl"; $urlObj["response_type"] = "code"; $urlObj["scope"] = "snsapi_base"; $urlObj["state"] = "STATE"."#wechat_redirect"; $bizString = $this->ToUrlParams($urlObj); return "https://open.weixin.qq.com/connect/oauth2/authorize?".$bizString; } // 构造获取openid和access_toke的url地址 public function __CreateOauthUrlForOpenid($code) { $urlObj["appid"] = WxPayConfig::APPID; $urlObj["secret"] = WxPayConfig::APPSECRET; $urlObj["code"] = $code; $urlObj["grant_type"] = "authorization_code"; $bizString = $this->ToUrlParams($urlObj); return "https://api.weixin.qq.com/sns/oauth2/access_token?".$bizString; } //将xml格式的统一下单数据发送给微信接口并返回数据(prepay_id) public function unifiedOrder($xml_order, $timeOut = 6) { $url = "https://api.mch.weixin.qq.com/pay/unifiedorder"; $response = $this->postXmlCurl($xml_order, $url, false, $timeOut); $result = $this->FromXml($response); return $result; } //将xml格式数据转化为数组 public function FromXml($xml) { //将XML转为array //禁止引用外部xml实体 libxml_disable_entity_loader(true); $response_data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true); return $response_data; } // 以post方式提交xml到对应的接口url public function postXmlCurl($xml, $url, $useCert = false, $second = 30) { $ch = curl_init(); //设置超时 curl_setopt($ch, CURLOPT_TIMEOUT, $second); curl_setopt($ch,CURLOPT_URL, $url); curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,TRUE); curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,2);//严格校验 //设置header curl_setopt($ch, CURLOPT_HEADER, FALSE); //要求结果为字符串且输出到屏幕上 curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); if($useCert == true){ //设置证书 //使用证书:cert 与 key 分别属于两个.pem文件 curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM'); curl_setopt($ch,CURLOPT_SSLCERT, WxPayConfig::SSLCERT_PATH); curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM'); curl_setopt($ch,CURLOPT_SSLKEY, WxPayConfig::SSLKEY_PATH); } //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); } } //签名算法 public function MakeSign($order) { //签名步骤一:按字典序排序参数 ksort($order); $string = $this->ToUrlParams($order); //签名步骤二:在string后加入KEY $string = $string . "&key=".WxPayConfig::KEY; //签名步骤三:MD5加密 $string = md5($string); //签名步骤四:所有字符转为大写 $result = strtoupper($string); return $result; } /** * 格式化参数格式化成url参数 */ public function ToUrlParams($order) { $buff = ""; foreach ($order as $k => $v) { if($k != "sign" && $v != "" && !is_array($v)){ $buff .= $k . "=" . $v . "&"; } } $buff = trim($buff, "&"); return $buff; } //生成随机字符串 public 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; } //将数组转换成xml格式。 public function ToXml($order) { $xml = "<xml>"; foreach ($order as $key=>$val) { if (is_numeric($val)){ $xml.="<".$key.">".$val."</".$key.">"; }else{ $xml.="<".$key."><![CDATA[".$val."]]></".$key.">"; } } $xml.="</xml>"; return $xml; } } ?>
接下来是配置文件config.php
<?php class WxPayConfig{ //用户公众号的appid const APPID = ''; //公众号密钥 const APPSECRET = ''; //商户号的id const MCHID = ''; //商户号密钥 const KEY = ''; //证书地址。 const SSLCERT_PATH = './apiclient_cert.pem'; const SSLKEY_PATH = './apiclient_key.pem'; } ?>