首先在extend目录新建一个文件夹建立如下脚本:
WxPayApi.php 脚本如下:
GetNotifyUrl(); $appid =$config->GetAppId(); $mch_id = $config->GetMerchantId(); $onoce_str = $this->createNoncestr(); $data["appid"] = $appid; $data["body"] = $body; $data["mch_id"] = $mch_id; $data["nonce_str"] = $onoce_str; $data["notify_url"] = $notify_url; $data["out_trade_no"] = "whkjtjy".date("YmdHis"); $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); return $parameters; } /** * * 统一下单 小程序 * $openId 用户openid 必填 * $body 商品信息 必填 * $total_fee 商品金额 必填 */ public function wxappunifiedOrder($openId,$body,$total_fee) { $url = "https://api.mch.weixin.qq.com/pay/unifiedorder"; $config = new WxPayConfig(); $appid =$config->GetWxAppId(); $mch_id = $config->GetMerchantId(); $notify_url = $config->GetWxAppNotifyUrl(); $onoce_str = $this->createNoncestr(); $data["appid"] = $appid; $data["body"] = $body; $data["mch_id"] = $mch_id; $data["nonce_str"] = $onoce_str; $data["notify_url"] = $notify_url; $data["out_trade_no"] = "whkjtjy".date("YmdHis"); $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); return $parameters; } /** * 作用:产生随机字符串,不长于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; } /** * 生成签名 */ public function getSign($Obj) { $config = new WxPayConfig(); $key = $config->GetKey(); foreach ($Obj as $k => $v){ $Parameters[$k] = $v; } //签名步骤一:按字典序排序参数 ksort($Parameters); $String = $this->formatBizQueryParaMap($Parameters, false); //echo '【string1】'.$String.''; //签名步骤二:在string后加入KEY $String = $String."&key=".$key; //echo "【string2】".$String.""; //签名步骤三:MD5加密 $String = md5($String); //echo "【string3】 ".$String.""; //签名步骤四:所有字符转为大写 $result_ = strtoupper($String); //echo "【result】 ".$result_.""; return $result_; } /** * 数组转xml * */ public function arrayToXml($arr){ $xml = ""; foreach ($arr as $key=>$val){ if (is_numeric($val)){ $xml.="<".$key.">".$val."".$key.">"; }else{ $xml.="<".$key.">".$key.">"; } } $xml.=" "; return $xml; } /** * 作用:以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; } /** * 作用:将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; } /** * 记录支付信息log */ public static function wxpay_log($basename=null,$msg=null) { $msg = '['.date("Y-m-d H:i:s").']'.'文件名:'.$basename.'[Log]:'.$msg; // 日志文件名:日期.txt $path = ROOT_PATH.DS.'public'. DS .'logs'. DS .date("Ymd").'.txt'; file_put_contents($path, $msg.PHP_EOL,FILE_APPEND); } }
WxPayConfig.php 如下
WxPayConfigInterface.php脚本如下:WxPayJsApi.php 脚本如下:_CreateOauthUrlForCode($baseUrl); Header("Location: $url"); exit(); } else { //获取code码,以获取openid $code = $_GET['code']; $openid = $this->getOpenidFromMp($code); return $openid; } } /** * * 获取jsapi支付的参数 * @param array $UnifiedOrderResult 统一支付接口返回的数据 * @throws WxPayException * * @return json数据,可直接填入js函数作为参数 */ public function GetJsApiParameters($UnifiedOrderResult) { if(!array_key_exists("appid", $UnifiedOrderResult) || !array_key_exists("prepay_id", $UnifiedOrderResult) || $UnifiedOrderResult['prepay_id'] == "") { throw new WxPayException("参数错误"); } $jsapi = new WxPayJsApiPay(); $jsapi->SetAppid($UnifiedOrderResult["appid"]); $timeStamp = time(); $jsapi->SetTimeStamp("$timeStamp"); $jsapi->SetNonceStr(WxPayApi::getNonceStr()); $jsapi->SetPackage("prepay_id=" . $UnifiedOrderResult['prepay_id']); $config = new WxPayConfig(); $jsapi->SetPaySign($jsapi->MakeSign($config)); $parameters = json_encode($jsapi->GetValues()); return $parameters; } /** * * 通过code从工作平台获取openid机器access_token * @param string $code 微信跳转回来带上的code * * @return openid */ public function GetOpenidFromMp($code) { $url = $this->__CreateOauthUrlForOpenid($code); //初始化curl $ch = curl_init(); $curlVersion = curl_version(); $config = new WxPayConfig(); $ua = "WXPaySDK/3.0.9 (".PHP_OS.") PHP/".PHP_VERSION." CURL/".$curlVersion['version']." " .$config->GetMerchantId(); //设置超时 curl_setopt($ch, CURLOPT_TIMEOUT, 60); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,FALSE); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST,FALSE); curl_setopt($ch, CURLOPT_USERAGENT, $ua); curl_setopt($ch, CURLOPT_HEADER, FALSE); curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); $proxyHost = "0.0.0.0"; $proxyPort = 0; $config->GetProxy($proxyHost, $proxyPort); if($proxyHost != "0.0.0.0" && $proxyPort != 0){ curl_setopt($ch,CURLOPT_PROXY, $proxyHost); curl_setopt($ch,CURLOPT_PROXYPORT, $proxyPort); } //运行curl,结果以jason形式返回 $res = curl_exec($ch); curl_close($ch); //取出openid $data = json_decode($res,true); $this->data = $data; $openid = $data['openid']; return $openid; } /** * * 拼接签名字符串 * @param array $urlObj * * @return 返回已经拼接好的字符串 */ private function ToUrlParams($urlObj) { $buff = ""; foreach ($urlObj as $k => $v) { if($k != "sign"){ $buff .= $k . "=" . $v . "&"; } } $buff = trim($buff, "&"); return $buff; } /** * * 获取地址js参数 * * @return 获取共享收货地址js函数需要的参数,json格式可以直接做参数使用 */ public function GetEditAddressParameters() { $config = new WxPayConfig(); $getData = $this->data; $data = array(); $data["appid"] = $config->GetAppId(); $data["url"] = "http://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']; $time = time(); $data["timestamp"] = "$time"; $data["noncestr"] = WxPayApi::getNonceStr(); $data["accesstoken"] = $getData["access_token"]; ksort($data); $params = $this->ToUrlParams($data); $addrSign = sha1($params); $afterData = array( "addrSign" => $addrSign, "signType" => "sha1", "scope" => "jsapi_address", "appId" => $config->GetAppId(), "timeStamp" => $data["timestamp"], "nonceStr" => $data["noncestr"] ); $parameters = json_encode($afterData); return $parameters; } /** * * 构造获取code的url连接 * @param string $redirectUrl 微信服务器回跳的url,需要url编码 * * @return 返回构造好的url */ private function _CreateOauthUrlForCode($redirectUrl) { $config = new WxPayConfig(); $urlObj["appid"] = $config->GetAppId(); $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; } /** * * 构造获取open和access_toke的url地址 * @param string $code,微信跳转带回的code * * @return 请求的url */ private function __CreateOauthUrlForOpenid($code) { $config = new WxPayConfig(); $urlObj["appid"] = $config->GetAppId(); $urlObj["secret"] = $config->GetAppSecret(); $urlObj["code"] = $code; $urlObj["grant_type"] = "authorization_code"; $bizString = $this->ToUrlParams($urlObj); return "https://api.weixin.qq.com/sns/oauth2/access_token?".$bizString; } }OK到处所有准备工作都做完了 接下来如何调用:
公众号支付 public function index() { //获取openid $tools = new WxPayJsApi(); $openId = $tools->GetOpenid(); //统一下单 $wxpay = new WxPayApi(); $res = $wxpay->unifiedOrder($openId,"好帅的李佳","1"); //显示支付网页 $this->assign("res",$res); return $this->fetch('wechatpay'); }小程序支付
public function wxapppay($openId,$body,$fee) { //post $wp = new WxPayApi(); $result = $wp->wxappunifiedOrder($openId,$body,$fee); return $result; }支付回调
public function notify(){ $testxml = file_get_contents("php://input"); $jsonxml = json_encode(simplexml_load_string($testxml, 'SimpleXMLElement', LIBXML_NOCDATA)); $result = json_decode($jsonxml, true);//转成数组, if($result){ //如果成功返回了 $out_trade_no = $result['out_trade_no']; if($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS'){ //执行业务逻辑 //记录支付信息在数据库--此步骤暂时略。。。。 WxPayApi::wxpay_log('【小程序】支付订单号:'.$out_trade_no,$jsonxml); } exit(''); } } 完成!