最近項目涉及到小程序開發:須要進行微信支付模塊,接下來經過敘述,記錄一下微信小程序中微信支付模塊的開發,以便往後翻閱和使用。php
學習指南----------微信支付開發文檔:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_11&index=2算法
一、在開發小程序微信支付以前,首先須要申請帳號,註冊一個小程序開發者帳號,並進行微信認證。小程序
二、小程序開通微信支付微信小程序
獲取到appid(小程序ID)、AppSecret 、MchID(商戶ID)、API Keyapi
商戶系統和微信支付系統主要交互:數組
一、小程序登陸接口、獲取openid(小程序登陸)服務器
二、商戶端調用支付統一下單接口,返回預付單信息(統一下單)微信
三、小程序端顯示二維碼,客戶掃碼支付,小程序端鑑權調起支付,返回支付結果到小程序端(再次簽名)app
四、推送支付結果到小程序端(支付結果通知API)curl
五、商戶查詢支付結果(查詢訂單API)
注意點:
一、簽名 須要對全部非空參數按照參數名ASSIC字典序排序,拼接API密鑰MD5加密後轉大寫。
二、須要將全部參數轉xml形式,使用curl發起請求。再將獲取到的返回值從xml形式轉化爲數組進行取值。 注意返回參數都是大寫。
如下幾個通用函數方法:
/** * 簽名算法 * 一、對參數按照key=value的格式,並按照參數名ASCII字典序排序 * ◆ 參數名ASCII碼從小到大排序(字典序); ◆ 若是參數的值爲空不參與簽名; ◆ 參數名區分大小寫; ◆ 驗證調用返回或微信主動通知簽名時,傳送的sign參數不參與簽名,將生成的簽名與該sign值做校驗。 ◆ 微信接口可能增長字段,驗證簽名時必須支持增長的擴展字段 *二、 拼接上key,MD5加密,並將字符串所有轉成大寫,拼接API密鑰 * * @param unknown $post */ function getSign($post){ $stringA = ''; ksort($post);//key值排序 參數名ASCII碼從小到大排序(字典序) foreach ($post as $key=>$value){ if(!$value)continue; if(!$stringA){ $stringA= $key."=".$value; }else{ $stringA.= "&".$key."=".$value; } } $stringA.='&key='.$APIKey; $sign = strtoupper(md5($stringA)); return $sign; }
/** * 隨機的32位字符串 * @param unknown $len */ private function getNonceStr($len){ $a=range('a','z'); $b=range('A','Z'); $c=range('0','9'); $chars=array_merge($a,$b,$c); $charslen=count($chars)-1; shuffle($chars); $nonce_str=''; for($i=0;$i<$len;$i++){ $nonce_str.=$chars[mt_rand(0,$charslen)]; } return $nonce_str; }
/** * curl請求 * @param unknown $url * @param unknown $data * @param array $headers */ private function http_request($url,$data = null,$headers=array()) { $curl = curl_init(); if( count($headers) >= 1 ){ curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); } curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE); if (!empty($data)){ curl_setopt($curl, CURLOPT_POST, 1); curl_setopt($curl, CURLOPT_POSTFIELDS, $data); } curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); $output = curl_exec($curl); curl_close($curl); return $output; }
private function getIP(){ if(!empty($_SERVER['HTTP_CDN_SRC_IP'])){ $ip = $_SERVER['HTTP_CDN_SRC_IP']; }else if (getenv('HTTP_CLIENT_IP')){ $ip = getenv('HTTP_CLIENT_IP'); }else if (getenv('HTTP_X_FORWARDED_FOR')){ //獲取客戶端用代理服務器訪問時的真實ip 地址 $ip = getenv('HTTP_X_FORWARDED_FOR'); }else if (getenv('HTTP_X_FORWARDED')){ $ip = getenv('HTTP_X_FORWARDED'); }else if (getenv('HTTP_FORWARDED_FOR')){ $ip = getenv('HTTP_FORWARDED_FOR'); }else if (getenv('HTTP_FORWARDED')){ $ip = getenv('HTTP_FORWARDED'); }else{ $ip = $_SERVER['REMOTE_ADDR']; } return $ip; }