分享

微信App支付技术架构全解析

 lguo001 2016-08-10

博客:http://www.jianshu.com/users/21716b19302d/latest_articles


简单介绍了微信移动支付的申请、接入、使用、确认支付结果等相关流程

1 申请

申请步骤直接参考官方文档-http://kf.qq.com/faq/120911VrYVrA150906F3qqY3.html

主要2个大块:

  1. 申请开通开放平台

  2. 申请支付开通商户平台

全部申请通过后,获取支付必须的参数如下:

1.1 AppID和AppSecret

开放平台创建的应用唯一标识。 登录微信开放平台,进入应用详情可查看AppID和AppSecret。

1.2 mch_id

微信支付申请完成之后,微信商户平台会给你的邮箱发通知邮件,里面包含开通支付的商户信息

1.3 API秘钥

即商户支付秘钥,主要负责处理通信相关参数加密。登陆微信商户平台(账号密码在微信商户平台发来的邮件里) 点击左侧的「账户设置 - API 安全」(第一次登陆会让你安装操作证书,请先安装操作证书)。点击设置密钥,设置自己的密钥。

1.4 商户证书

用于退款等一些需要证书验证的接口使用。在微信商户平台点击「账户中心 - API 安全」,点击「下载证书」

证书下载后,打开压缩包会看到「apiclientcert.pem」和「apiclientkey.pem」和rootca.pem证书。

2 接入流程

参考接入文档-https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_1

主要几个步骤:

  1. 统一下单(放在服务端,需要加密参数)

  2. 生成支付参数(放在服务端,需要生成签名)

  3. 调用客户端SDK发起支付

  4. 服务端异步接收支付结果

2.1 统一下单

$appid = '';  //你的appid$mch_id = '';  //商户id$wx_api_key = '';    //商户api秘钥$out_trade_no = '';  //自己业务系统生成的交易no,可以唯一标识$client_ip = '';  //客户端ip$notify_url = '';    //接收支付结果通知url$UNIFIED_ORDER_URL = 'https://api.mch.weixin.qq.com/pay/unifiedorder';  //统一下单地址$data = array();$data['appid'] = $appid; $data['mch_id'] =$mch_id;$data['nonce_str'] = randomStr(20);  //随机20位字符串$data['body'] = '微信移动支付测试';$data['detail'] = '微信移动支付测试';$data['out_trade_no'] = $out_trade_no;    $data['total_fee'] = 1;  //注意 单位是分$data['spbill_create_ip'] = $client_ip;$data['notify_url'] = $notify_url;$data['trade_type'] = 'APP';  //交易类型$data['sign'] =sign($data, $wx_api_key);    //签名//转为xml格式$xml_str = arrayToXmlStr($data); //发送请求 使用封装好的curl_post$result = curl_post($UNIFIED_ORDER_URL, $xml_str);//解析得到的值$get_data = simplexml_load_string($raw_data, 'SimpleXMLElement', LIBXML_NOCDATA);$get_para = array();$get_sign = '';foreach ($get_data->children() as $child) {        if($child->getName() == 'sign') {                $get_sign = strval($child);        } else {                $get_para[strval($child->getName())] = strval($child);        }}if($get_para['return_code'] !== 'SUCCESS') {    //return code fail}//验证签名if(!verifySign($get_sign, $get_para, $wx_api_key)) {    //验证签名非法}//可以自行处理解析获得的参数//todo...

一些函数:

/** * array转成xml str * @param $arr */public static function arrayToXmlStr($arr) {        $xml_data = new \SimpleXMLElement('');        Func::arrayToXml($arr, $xml_data);        return $xml_data->asXML();}/** * 生成指定长度的随机字符串(包含大写英文字母, 小写英文字母, 数字) * @param $length int 需要生成的字符串的长度 * @return string 包含 大小写英文字母 和 数字 的随机字符串 */public static function randomStr($length){        //生成一个包含 大写英文字母, 小写英文字母, 数字 的数组        $arr = array_merge(range(0, 9), range('a', 'z'), range('A', 'Z'));        $str = '';        $arr_len = count($arr);        for ($i = 0; $i < $length;="" $i++)=""  =""  {=""  =""  =""  =""  =""  =""  =""  =""  $rand="mt_rand(0," $arr_len-1);=""  =""  =""  =""  =""  =""  =""  =""  $str.="$arr[$rand];"  =""  =""  =""  }=""  =""  =""  =""  return="" $str;}/**="" *="" 微信签名="" *="" @param="" $para="" mixed="" 带签名参数数组="" *="" @param="" $wx_key="" string="" wxkey="" */public="" static="" function="" sign($para,="" $wx_key)="" {=""  =""  =""  =""  $unsign_str="Func::createLinkString(Func::argSort($para))" .="" '&key=' . $wx_key;        $sign = strtoupper(md5($unsign_str));        return $sign;}/** * 微信签名验证 * @param $sign * @param $para * @param $wx_key * @return false-验证失败 true-验证成功 */public static function verifySign($sign, $para, $wx_key) {        $unsign_str = Func::createLinkString(Func::argSort($para)) . ' &key=' . $wx_key;        $sign_str = strtoupper(md5($unsign_str));        if($sign === $sign_str) {            return true;        }        return false;}

2.2 生成支付参数

客户端需要的支付参数是带签名的,所以最好支付参数也在服务端生成后,jsondecode后传入客户端即可直接调用

//生成支付参数$data = array();$data[' appid']="$appid;" $data['mch_id']="$mch_id;$data['prepayid']" =="" $prepayid;=""  =""  //刚才统一下单生成的prepayid$data['package']='Sign=WXPay' ;$data['noncestr']="randomStr(20);$data['timestamp']" =="" time();$data['sign']="sign($data," $wx_api_key);$pay_param="">

3. 调用支付

3.1 Android

注:微信支付在开放平台中填入应用对应的包名和签名,并且测试时要签名打包,不然支付失败

可以直接参考调用我二次封装过的Android SDK。 Github地址:https://github.com/tsy12321/PayAndroid

3.2 iOS

二次封装过的iOS SDK。 Github地址:https://github.com/tsy12321/PayiOS

4 异步结果通知

注:尤其要注意通知结果验证成功后要能正确处理重复通知,放置多次发货造成资金损失

$raw_data = $GLOBALS['HTTP_RAW_POST_DATA'];$get_data = simplexml_load_string($raw_data, 'SimpleXMLElement', LIBXML_NOCDATA);$get_para = array();$get_sign = '';foreach ($get_data->children() as $child) {        if($child->getName() == 'sign') {                $get_sign = strval($child);        } else {                $get_para[strval($child->getName())] = strval($child);        }}if($get_para['return_code'] !== 'SUCCESS') {    //return code fail    die('');}//验证签名if(!verifySign($get_sign, $get_para, $wx_api_key)) {    //验证签名非法    //todo    die('');}//在这其实通知已经接受成功 可以返回成功告诉微信不用再次通知了echo('');//业务状态码判断if ($get_para['result_code'] !== 'SUCCESS') {          //状态码错误    //支付错误 更改订单状态 记录log等    //...}//支付成功 更改订单状态 记录log等 //todo

5 其他

  1. 客户端收到同步支付结果后建议一段时间内轮询检查服务端,获取服务端的结果,支付最终状态以服务端为准


    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多