信阳做网站公司汉狮价格,php网站后台验证码不显示,网页设计师在哪里工作,软件开发学习路线文章目录 1 问题背景2 思路3 代码实现 1 问题背景 在发起支付的时候#xff0c;一般都需要对发送的请求参数进行加密或者签名#xff0c;下文简称这个过程为“签名”。行业内比较普遍的签发算法有#xff1a; #xff08;1#xff09;按支付渠道给定的字段排序进行拼接一般都需要对发送的请求参数进行加密或者签名下文简称这个过程为“签名”。行业内比较普遍的签发算法有 1按支付渠道给定的字段排序进行拼接最后再拼一个密钥形成一个待签名的字符串tobeSign然后对这个tobeSign进行MD5编码。比如MD5(商户号子应用ID商户订单号流水号金额币种密钥) 2针对请求参数中的字段仅针对第一层的字段不需要针对字段里面的字段即不需要递归进行字典升序排序用格式keyvalue和连接符拼接最后再拼一个密钥再用MD5编码比如MD5(avalue1bvalue2key密钥) 这次遇到一种比较有趣的签名算法笔者认为是基于第2的变种渠道方要求针对请求参数中的字段如果该字段是对象类型那么该字段里面的字段也要按字典升序排序进行拼接相当于是递归字典升序困难度有一点提升 2 思路 文字描述得有点抽象可以结合第3小节的代码实现来看 遍历每一层字段都用一个容器存起来要按字典升序存。维护一个层序遍历的容器——双向队列。将前面升序的数据入队。遍历队列的每一元素元素从队头出队再遍历元素中的字段是否是对象类型或者数组类型使用一个容器存起来要按字典降序存存完后使用头插法入队。使用头插法倒叙入队每一次从队头遍历那么每一次遍历都是升序遍历。
3 代码实现 解释代码中的BeansUtil.bean2MapIgnoreEmptyStr()是将对象转成一个Map。SymbolConstant.EQUAL的值是一个SymbolConstant.AND的值是一个 public static String buildToBeSignStr(Object payReq) {// 将对象转成一个MapMapString, String map BeansUtil.bean2MapIgnoreEmptyStr(payReq);TreeMapString, String treeMap new TreeMap(map);ListString result new LinkedList();for (Map.EntryString, String entry : treeMap.entrySet()) {// 层序遍历容器DequeMap.EntryString, String bfsHolder new LinkedList();// 结果暂存容器ListString tmpResult new LinkedList();// 入队bfsHolder.offer(entry);while (CollectionUtils.isNotEmpty(bfsHolder)) {Map.EntryString, String pollEntry bfsHolder.poll();String pKey pollEntry.getKey();String pVal pollEntry.getValue();if (StringUtils.isNotBlank(pVal) JSONValidator.from(pVal).validate()) {// 是json串仍需要继续解析log.info(value of key:{} is json str., pKey);// 解析JSON字符串Object parsedObject JSON.parse(pVal);boolean isJSONObject parsedObject instanceof JSONObject;boolean isJSONArray parsedObject instanceof JSONArray;if (isJSONObject || isJSONArray) {MapString, String map1 null;if (isJSONObject) {log.info(JSON字符串是一个对象);JSONObject jsonObject (JSONObject) parsedObject;// 处理对象map1 BeansUtil.buildMapFromJsonStr(pVal);} else if (isJSONArray) {System.out.println(JSON字符串是一个数组);JSONArray jsonArray (JSONArray) parsedObject;// 处理数组for (Object o : jsonArray) {map1 BeansUtil.bean2MapIgnoreEmptyStr(o);}}if (MapUtils.isNotEmpty(map1)) {// 倒叙排序MapString, String treeMap1 new TreeMap(Comparator.reverseOrder());treeMap1.putAll(map1);// 插入到队头Streams.of(treeMap1.entrySet()).forEach(bfsHolder::offerFirst);}} else {tmpResult.add(pKey SymbolConstant.EQUAL pVal);}} else {tmpResult.add(pKey SymbolConstant.EQUAL pVal);}}if (CollectionUtils.isNotEmpty(tmpResult)) {String tmpResultStr String.join(SymbolConstant.AND, tmpResult);result.add(tmpResultStr);}}if (CollectionUtils.isNotEmpty(result)) {return String.join(SymbolConstant.AND, result);}return ;}