最近項目涉及到小程序開發:需要進行微信支付模塊,接下來通過敘述,記錄一下微信小程序中微信支付模塊的開發,以便日后翻閱和使用。
學習指南----------微信支付開發文檔:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_11&index=2
1、在開發小程序微信支付之前,首先需要申請賬號,注冊一個小程序開發者賬號,並進行微信認證。
2、小程序開通微信支付
獲取到appid(小程序ID)、AppSecret 、MchID(商戶ID)、API Key
商戶系統和微信支付系統主要交互:
1、小程序登錄接口、獲取openid(小程序登錄)
2、商戶端調用支付統一下單接口,返回預付單信息(統一下單)
3、小程序端顯示二維碼,客戶掃碼支付,小程序端鑒權調起支付,返回支付結果到小程序端(再次簽名)
4、推送支付結果到小程序端(支付結果通知API)
5、商戶查詢支付結果(查詢訂單API)
注意點:
1、簽名 需要對所有非空參數按照參數名ASSIC字典序排序,拼接API密鑰MD5加密后轉大寫。
2、需要將所有參數轉xml形式,使用curl發起請求。再將獲取到的返回值從xml形式轉化為數組進行取值。 注意返回參數都是大寫。
以下幾個通用函數方法:
/** * 簽名算法 * 1、對參數按照key=value的格式,並按照參數名ASCII字典序排序 * ◆ 參數名ASCII碼從小到大排序(字典序); ◆ 如果參數的值為空不參與簽名; ◆ 參數名區分大小寫; ◆ 驗證調用返回或微信主動通知簽名時,傳送的sign參數不參與簽名,將生成的簽名與該sign值作校驗。 ◆ 微信接口可能增加字段,驗證簽名時必須支持增加的擴展字段 *2、 拼接上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; }