控制器controller:
index.php
get_access_token($code); $userinfo=$Weixin->get_openid_userinfo($res['access_token'],$res['openid']); halt($userinfo); } $res=$Weixin->code_shouquan(); } public function pay() { $userAgent = $_SERVER['HTTP_USER_AGENT']; if (strpos($userAgent, 'MicroMessenger')) { $Weixin=new Weixin(); $code=(input('param.code')); if (!empty($code)) { $res=$Weixin->get_access_token($code); $userinfo=$Weixin->get_openid_userinfo($res['access_token'],$res['openid']); $openid=$userinfo['openid']; // halt($openid); $Weixin_pay=new Weixin_pay(); $total_fee=1; $body="JSAPI支付测试"; $order_sn=time(); $res=$Weixin_pay->pay($openid,$total_fee,$body,$order_sn); $this->assign("res",$res); return $this->fetch("index"); }else{ $res=$Weixin->code_shouquan(); } }else{ //非微信浏览器 $Weixin_pay=new Weixin_pay(); //h5支付不用传递openid 此处与微信jsapi支付不同 $openid=""; $total_fee=1; $body="wamp支付测试"; $order_sn=time(); $res=$Weixin_pay->payh5($openid,$total_fee,$body,$order_sn); // halt($res); $this->assign("res",$res); return $this->fetch("h5"); } } public function orderquery(){ $Weixin_pay=new Weixin_pay(); // $openid="oZX2QwaUBh37C4Ev7I-NUdp6udao"; $total_fee=1; $body="JSAPI支付测试"; $order_sn=time(); $res=$Weixin_pay-> orderquery(); } public function notify(){ $xml = $GLOBALS['HTTP_RAW_POST_DATA']; Log::record($xml); }}
model层
Weixin.php
appScrect=$appScrect; $this->appId=$appId; } public function code_shouquan(){ // echo $this->appScrect; // echo $this->appId; $redirect_uri=urlencode("你自己的域名/index/index/pay");//微信获取网页授权地址 // 1、引导用户进入授权页面同意授权,获取code // 2、通过code换取网页授权access_token // 3、如果需要,开发者可以刷新网页授权access_token,避免过期 // 4、通过网页授权access_token和openid获取用户基本信息(支持UnionID机制) $url="https://open.weixin.qq.com/connect/oauth2/authorize?appid=".$this->appId."&redirect_uri=".$redirect_uri."&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect"; header("Location: $url"); } public function get_access_token($code){ //检测缓存中是否有access_token(2小时),如果存在直接返回,不存在则检测缓存中的refresh_token(30天), // refresh_token如果存在调用刷新缓存;如果不存在重新发起授权code授权 $url="https://api.weixin.qq.com/sns/oauth2/access_token?appid=".$this->appId."&secret=".$this->appScrect."&code=".$code."&grant_type=authorization_code"; $res= file_get_contents($url); $res=json_decode($res,true); return $res; } public function get_refresh_token($refresh_token){ $url="https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=".$this->appId."&grant_type=refresh_token&refresh_token=".$refresh_token; $res= file_get_contents($url); $res=json_decode($res,true); return $res; } public function get_openid_userinfo($access_token,$openid){ $url="https://api.weixin.qq.com/sns/userinfo?access_token=".$access_token."&openid=".$openid."&lang=zh_CN"; $res= file_get_contents($url); $res=json_decode($res,true); return $res; }}
Weixin_pay.php
appScrect=$appScrect; $this->appId=$appId; $this->key=$key; $this->mch_id=$mch_id; } public function pay($openid,$total_fee,$body,$out_trade_no){ $config= config('wxpay'); $url = "https://api.mch.weixin.qq.com/pay/unifiedorder"; $notify_url ='http://'.$_SERVER['HTTP_HOST'].'/index/index/notify'; $onoce_str = $this->createNoncestr(); $data["appid"] = $this->appId; $data["body"] = $body; $data["mch_id"] = $this->mch_id; $data["nonce_str"] = $onoce_str; $data["notify_url"] = $notify_url; $data["out_trade_no"] = $out_trade_no; $data["spbill_create_ip"] = $this->get_client_ip(); $data["total_fee"] = $total_fee; $data["trade_type"] = "JSAPI"; $data["openid"] = $openid; $sign = $this->getSign($data); // halt($data); $data["sign"] = $sign; $xml = $this->arrayToXml($data); $response = $this->postXmlCurl($xml, $url); //将微信返回的结果xml转成数组 $response = $this->xmlToArray($response); $response['package']="prepay_id=".$response['prepay_id']; $jsapi=array(); $timeStamp = time(); $jsapi['appId']=($response["appid"]); $jsapi['timeStamp']=("$timeStamp"); $jsapi['nonceStr']=($this->createNoncestr()); $jsapi['package']=("prepay_id=" . $response['prepay_id']); $jsapi['signType']=("MD5"); $jsapi['paySign']=($this->getSign($jsapi)); $parameters = json_encode($jsapi); // halt($jsapi); //请求数据,统一下单 return $parameters; } public function payh5($openid,$total_fee,$body,$out_trade_no){ $config= config('wxpay'); $ip= request()->ip(); $url = "https://api.mch.weixin.qq.com/pay/unifiedorder"; $notify_url ='http://'.$_SERVER['HTTP_HOST'].'/index/index/notify'; $onoce_str = $this->createNoncestr(); $data["appid"] = $this->appId; $data["body"] = $body; $data["mch_id"] = $this->mch_id; $data["nonce_str"] = $onoce_str; $data["notify_url"] = $notify_url; $data["out_trade_no"] = $out_trade_no; $data["spbill_create_ip"] = $ip; $data["total_fee"] = $total_fee; $data["trade_type"] = "MWEB"; // $data["openid"] = $openid; $data["scene_info"] = "{'h5_info': {'type':'Wap','wap_url': $notify_url,'wap_name': '测试充值'}}"; $sign = $this->getSign($data); // halt($data); $data["sign"] = $sign; $xml = $this->arrayToXml($data); $response = $this->postXmlCurl($xml, $url); //将微信返回的结果xml转成数组 $response = $this->xmlToArray($response); //请求数据,统一下单 return $response; } 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; } // /*生成签名*/ public function getSign($Obj){ foreach ($Obj as $k => $v){ $Parameters[$k] = $v; } //签名步骤一:按字典序排序参数 ksort($Parameters); $String = $this->formatBizQueryParaMap($Parameters, false); //echo '【string1】'.$String.''; //签名步骤二:在string后加入KEY $String = $String."&key=".$this->key; //echo "【string2】".$String.""; //签名步骤三:MD5加密 $String = md5($String); //echo "【string3】 ".$String.""; //签名步骤四:所有字符转为大写 $result_ = strtoupper($String); //echo "【result】 ".$result_.""; return $result_; } /** * 作用:产生随机字符串,不长于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; } //数组转xml public function arrayToXml($arr){ $xml = ""; foreach ($arr as $key=>$val){ if (is_numeric($val)){ $xml.="<".$key.">".$val." "; }else{ $xml.="<".$key."> "; } } $xml.=" "; return $xml; } /** * 作用:将xml转为array */ public function xmlToArray($xml){ //将XML转为array $array_data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true); return $array_data; } /** * 作用:以post方式提交xml到对应的接口url */ public function postXmlCurl($xml,$url,$second=30){ //初始化curl $ch = curl_init(); //设置超时 curl_setopt($ch, CURLOPT_TIMEOUT, $second); //这里设置代理,如果有的话 //curl_setopt($ch,CURLOPT_PROXY, '8.8.8.8'); //curl_setopt($ch,CURLOPT_PROXYPORT, 8080); curl_setopt($ch,CURLOPT_URL, $url); curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE); curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE); //设置header curl_setopt($ch, CURLOPT_HEADER, FALSE); //要求结果为字符串且输出到屏幕上 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); echo "curl出错,错误码:$error".""; curl_close($ch); return false; } } /* 获取当前服务器的IP */ public function get_client_ip(){ if ($_SERVER['REMOTE_ADDR']) { $cip = $_SERVER['REMOTE_ADDR']; } elseif (getenv("REMOTE_ADDR")) { $cip = getenv("REMOTE_ADDR"); } elseif (getenv("HTTP_CLIENT_IP")) { $cip = getenv("HTTP_CLIENT_IP"); } else { $cip = "unknown"; } return $cip; } /** * 作用:格式化参数,签名过程需要使用 */ public function formatBizQueryParaMap($paraMap, $urlencode){ $buff = ""; ksort($paraMap); foreach ($paraMap as $k => $v){ if($urlencode){ $v = urlencode($v); } $buff .= $k . "=" . $v . "&"; } $reqPar; if (strlen($buff) > 0){ $reqPar = substr($buff, 0, strlen($buff)-1); } return $reqPar; } public function MakeSign($unifiedorder) { $this->values=$unifiedorder; //签名步骤一:按字典序排序参数 // ksort($this->values); $string = $this->ToUrlParams();// halt($string); //签名步骤二:在string后加入KEY $string = $string . "&key=".$this->key; //签名步骤三:MD5加密 $string = md5($string); //签名步骤四:所有字符转为大写 $result = strtoupper($string); return $result; } public function ToUrlParams() { $buff = ""; foreach ($this->values as $k => $v) { if($k != "sign" && $v != "" && !is_array($v)){ $buff .= $k . "=" . $v . "&"; } } $buff = trim($buff, "&"); return $buff; } function array2xml($array) { $xml=''; foreach($array as $key=>$val){ if(is_numeric($key)){ $key="item id=\"$key\""; }else{ //去掉空格,只取空格之前文字为key list($key,)=explode(' ',$key); } $xml.="<$key>"; $xml.=is_array($val)?$this->_array2xml($val):$val; //去掉空格,只取空格之前文字为key list($key,)=explode(' ',$key); $xml.=" "; } $xml.=" "; return $xml; } function xml2array($xml) { //禁止引用外部xml实体 libxml_disable_entity_loader(true); $values = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true); return $values; } public function request_post($url = '', $param = '') { if (empty($url) || empty($param)) { return false; } $postUrl = $url; $curlPost = $param; $ch = curl_init(); //初始化curl curl_setopt($ch, CURLOPT_URL, $postUrl); //抓取指定网页 curl_setopt($ch, CURLOPT_HEADER, 0); //设置header curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //要求结果为字符串且输出到屏幕上 curl_setopt($ch, CURLOPT_POST, 1); //post提交方式 curl_setopt($ch, CURLOPT_POSTFIELDS, $curlPost); $data = curl_exec($ch); //运行curl curl_close($ch); return $data; } function curl_post_ssl($url, $vars, $second=30,$aHeader=array()) { $ch = curl_init(); //curl_setopt($ch,CURLOPT_VERBOSE,'1'); curl_setopt($ch,CURLOPT_TIMEOUT,$second); curl_setopt($ch,CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch,CURLOPT_URL,$url); curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false); curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,false); curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM'); curl_setopt($ch,CURLOPT_SSLCERT,'/data/cert/php.pem'); curl_setopt($ch,CURLOPT_SSLCERTPASSWD,'1234'); curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM'); curl_setopt($ch,CURLOPT_SSLKEY,'/data/cert/php_private.pem'); if( count($aHeader) >= 1 ){ curl_setopt($ch, CURLOPT_HTTPHEADER, $aHeader); } curl_setopt($ch,CURLOPT_POST, 1); curl_setopt($ch,CURLOPT_POSTFIELDS,$vars); $data = curl_exec($ch); curl_close($ch); if($data){ return $data; }else{ return false; } }}