最近项目涉及到小程序开发:需要进行微信支付模块,接下来通过叙述,记录一下微信小程序中微信支付模块的开发,以便日后翻阅和使用。
学习指南----------微信支付开发文档: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; }