签名算法 待签名参数按照字段名的ASCII码大小排序 Android、JS中实现

验签是作为一个api接口避免裸奔的必要手段之一,原理就是前后端约定一套签名规则,首先前端在请求api接口时会增加一个sign参数,其值来源是对所提交的参数按照约定的签名规则去生成;接着后端同样会针对其接收到的参数(除sign外)按照约定的签名规则也生成一个sign,然后对2者进行比较,如果不一致则认为此次请求是未非法无效的,不予处理。

参考微信公众平台的签名算法:
签名生成规则如下:参与签名的字段包括noncestr(随机字符串), 有效的jsapi_ticket, timestamp(时间戳), url(当前网页的URL,不包含#及其后面部分) 。对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1。这里需要注意的是所有参数名均为小写字符。对string1作sha1加密,字段名和字段值都采用原始值,不进行URL 转义。
即signature=sha1(string1)。 
示例:
noncestr=Wm3WZYTPz0wzccnW
jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg
timestamp=1414587457
url=http://mp.weixin.qq.com?params=value
步骤1. 对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1:
jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg&noncestr=Wm3WZYTPz0wzccnW&timestamp=1414587457&url=http://mp.weixin.qq.com?params=value
步骤2. 对string1进行sha1签名,得到signature:
0f9de62fce790f9a083d5c99e95740ceb90c27ed
------------------------------------------------------------
其中核心算法就是:对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1

 

下面就是来说说参数的key值排序的代码实现:

一. Android中:
1.利用TreeMap 默认排序规则:按照key的字典顺序来排序(升序)
   TreeMap<String,String> treeMap=new TreeMap<>();
   treeMap.put("key", "value");
   treeMap.put("ba", "value1");
   treeMap.put("ac", "value2");
   treeMap.put("bb", "value3");

   StringBuffer stringBuffer=new StringBuffer();
   Iterator<Map.Entry<String, String>> it = treeMap.entrySet().iterator();
   while(it.hasNext()) {
       Map.Entry<String, String> entry = it.next();
       stringBuffer.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
   }
   String result=stringBuffer.substring(0,stringBuffer.length()-1);
   System.out.println(result);
=》
I/System.out: ac=value2&ba=value1&bb=value3&key=value

2.利用Arrays.sort 的默认排序
 String[] data = new String[]{"key", "ba", "ac", "bb"};
 Arrays.sort(data);
 for(String i:data){
     System.out.println("array i--" + i);
 }
=》
I/System.out: 
    array i--ac
    array i--ba
    array i--bb
    array i--key


二.JS中
  var data = {
        'key': 'value',
         'ba': 'value1',
         'ac': 'value2',
         'bb': 'value3'
      }
   data = objKeySort(data)
   console.log('newData', data)
   //排序的函数
   function objKeySort(arys) {
      //先用Object内置类的keys方法获取要排序对象的属性名数组,再利用Array的sort方法进行排序
       var newkey = Object.keys(arys).sort();
       console.log('newkey=' + newkey);
       var newObj = ''; //创建一个新的对象,用于存放排好序的键值对
       for (var i = 0; i < newkey.length; i++) {
           //遍历newkey数组
           newObj += [newkey[i]] + '=' + arys[newkey[i]] + '&';
       }
    return newObj.substring(0, newObj.length - 1); 
  }
=》 newkey=ac,ba,bb,key newData ac=value2&ba=value1&bb=value3&key=value

 附加url键值对转为对象方法

//in: aa=1&bb=2 ,out: {"aa":1,"bb":2}
function str2obj(str){
   var paramstr = str.substring(str.indexOf("?")+1);
   var pms = paramstr.split("&");
   var obj = {};
   for(var i=0;i<pms.length;i++){
       if(pms[i].indexOf("=") < 0){
          obj[pms[i]] = "undefined";
       }else{
          var pa = pms[i].split("=");
          obj[pa[0]] = pa[1];
       }
   }
   return obj;
}

 

转载于:https://www.cnblogs.com/langka/p/10690841.html

<think>好的,我现在需要帮助用户了解H5微信支付的实现流程。用户提到了H5支付,并希望了解具体的开发文档和API。首先,我需要回忆一下微信支付的相关知识,尤其是H5支付的流程。 根据用户提供的引用,引用[2]提到微信支付的接入需要根据不同的支付场景选择接入方式,比如H5支付。这里需要明确H5支付的适用场景,通常是在手机浏览器请求支付,适用于移动端网页。接着,用户提供的引用[1]和[3]都涉及到H5支付的具体实现方法,特别是使用WeixinJSBridge.invoke方法,以及可能遇到的回调问题,尤其是在iOS浏览器中的处理。 首先,我需要整理H5支付的基本流程。通常,微信支付的整体流程包括:商户系统生成订单,调用微信统一下单API获取支付参数前端调起支付接口,用户支付成功后处理回调通知。对于H5支付,用户是在浏览器中发起支付,因此需要生成一个支付页面,引导用户前往微信支付,完成后再跳转回商户页面。 接下来,需要确认每一步的具体实现细节。例如,统一下单API需要哪些参数?根据微信支付文档,必要的参数包括appid、mch_id、nonce_str、sign、body、out_trade_no、total_fee、spbill_create_ip、notify_url、trade_type等。其中,trade_type需要设置为MWEB。这一步可能需要后端生成签名,并调用微信的API。 然后,前端需要处理返回的支付参数。在引用[1]中提到使用WeixinJSBridge.invoke方法调起支付,这可能是在微信浏览器中使用的JSAPI,但H5支付通常是在非微信浏览器中,因此可能需要生成一个支付链接,让用户跳转到微信支付页面。这里可能存在混淆,需要确认H5支付的具体调起方式是否正确。例如,H5支付可能返回一个mweb_url,用户需要重定向到这个URL进行支付。 另外,支付完成后,微信服务器会发送异步通知到notify_url,商户需要处理这个通知,验证签名,并返回处理结果。同时,前端可能需要处理支付完成后的页面跳转,例如在redirect_url中携带支付结果信息。 还需要注意安全性问题,比如签名算法是否正确,防止参数被篡改。引用[3]提到在iOS浏览器中处理回调的问题,可能需要配置URL Scheme或者使用Universal Links来处理跳转回应用。 现在需要将这些步骤结构化,分点说明,确保符合用户的要求:实现流程、开发文档、API等。同时,需要检查是否有遗漏的步骤,例如申请H5支付的权限,配置支付域名等前置条件。 可能还需要注意,H5支付需要商户在微信支付商户平台配置H5支付的域名,并且可能需要提交经营资质审核。这一点在引用[2]中提到微信支付的接入步骤,可能包括注册、资质审核、配置支付场景等。 总结来说,H5支付的实现流程大致分为以下几个步骤: 1. 商户系统生成预支付订单,调用统一下单API。 2. 微信返回mweb_url,商户引导用户跳转到该URL进行支付。 3. 用户支付成功后,微信异步通知商户后台,并可能重定向用户回指定页面。 4. 商户后台处理支付结果,更新订单状态。 在代示例部分,可能需要后端生成签名的示例,以及前端跳转的示例。同时,需要注意不同环境下的跳转处理,比如在iOS或Android浏览器中的兼容性问题。 最后,生成相关问题需要考虑用户可能进一步的问题,比如如何处理异步通知、如何调试支付流程、常见错误有哪些等。</think>### H5微信支付实现流程 H5微信支付主要用于手机浏览器环境,用户通过网页发起支付后跳转至微信支付页面完成交易。以下是核心步骤及注意事项: --- #### **1. 前期准备** - **注册与资质审核**:完成微信支付商户注册,提交营业执照等资质文件[^2]。 - **配置支付域名**:在微信商户平台设置`H5支付的授权域名`,确保与实际支付页面域名一致[^2]。 - **获取API密钥**:生成商户API密钥(`mch_key`),用于后续签名计算。 --- #### **2. 统一下单API调用** 商户后端需调用微信支付`统一下单API`生成预支付订单: - **请求参数示例**: ```plaintext appid=wx1234567890 mch_id=10000100 nonce_str=5K8264ILTKCH16CQ2502SI8ZNMTM67VS body=商品描述 out_trade_no=202405200001 total_fee=100 spbill_create_ip=127.0.0.1 notify_url=https://yourdomain.com/notify trade_type=MWEB # 固定为MWEB scene_info={ "h5_info": {"type":"Wap","wap_url":"https://yourdomain.com","wap_name":"商城"}} sign=签名值 ``` - **签名生成**:对所有参数字典序排序后拼接,使用`MD5`或`HMAC-SHA256`加密生成`sign`字段[^1]。 - **API响应**:成功时返回`mweb_url`(支付跳转链接)和`prepay_id`。 --- #### **3. 前端跳转支付** 用户点击支付后,前端需引导用户跳转至`mweb_url`: ```javascript // 示例:自动跳转至微信支付页面 window.location.href = 'https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=wx1234567890...'; ``` - **注意事项**: - 在iOS浏览器中,需通过`URL Scheme`或`Universal Links`实现支付后跳回原页面[^3]。 - 安卓浏览器通常支持直接重定向。 --- #### **4. 异步通知处理** 支付完成后,微信服务器向商户的`notify_url`发送POST请求: ```plaintext POST /notify HTTP/1.1 Content-Type: application/xml <xml> <appid>wx1234567890</appid> <out_trade_no>202405200001</out_trade_no> <transaction_id>1217752501201407033233368018</transaction_id> <result_code>SUCCESS</result_code> <sign>...</sign> </xml> ``` - **验证签名**:校验微信返回的签名,防止篡改。 - **更新订单状态**:根据`result_code`标记订单为已支付,并返回`<return_code><![CDATA[SUCCESS]]></return_code>`响应。 --- #### **5. 支付结果页面跳转** 支付完成后,用户自动返回`redirect_url`(在统一下单参数中指定): ```plaintext https://yourdomain.com/result?out_trade_no=202405200001&status=success ``` - **前端处理**:根据URL参数展示支付结果。 --- ### **代示例(后端签名生成)** ```python import hashlib import random import string def generate_sign(params, api_key): # 按参数排序并拼接字符串 sorted_params = sorted(params.items()) sign_str = '&'.join([f"{k}={v}" for k, v in sorted_params]) + f"&key={api_key}" # MD5加密生成签名 return hashlib.md5(sign_str.encode()).hexdigest().upper() # 示例参数 params = { "appid": "wx1234567890", "mch_id": "10000100", "nonce_str": ''.join(random.choices(string.ascii_letters + string.digits, k=32)), "body": "商品A", "out_trade_no": "202405200001", "total_fee": 100, "spbill_create_ip": "127.0.0.1", "notify_url": "https://yourdomain.com/notify", "trade_type": "MWEB" } api_key = "your_mch_key" params["sign"] = generate_sign(params, api_key) ``` --- ### **常见问题与调试** 1. **签名错误**:检查参数排序、密钥是否正确,使用微信提供的[签名校验工具](https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=20_1)。 2. **支付页面无法打开**:确认`mweb_url`有效,且未在微信客户端内直接访问(需在外部浏览器触发)。 3. **异步通知未接收**:检查服务器网络可达性,确认`notify_url`为公网可访问的HTTPS地址。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值