anyuan

有独自开发一个Java的项目,项目中有对接到 美团餐饮开放平台,当时做的功能是将美团App的订单通过url回调给自己的系统,当作一笔新的订单做相应的逻辑后入库。

结果在回调请求的验证签名时卡了好一会,因为 美团餐饮开放平台 的请求比较特殊

 1: 推送API会持续更新,所以接收参数不能使用固定的Form进行接收。

2: 参数均为普通Post参数而非Json,Content-Type字段为text,所以要用特别的方式进行接收。 

计算签名官方提供的SDK自己试了一遍,可能是自己用的方式不对,自己生成的Sig和请求的Sig一直对不上,所以自己动手写了一个校验签名的Demo

以下是生成签名的文档介绍,也可以查看官方文档

 

创建一个Controller来接收美团发起的回调请求:

1: 回调的参数不固定,这里使用 HttpServletRequest 对象来获取所有的参数

2: 字母排序的话,直接使用 TreeMap 搞定

package com.demo.www.controller.openapi;


import com.google.common.base.Joiner;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Enumeration;
import java.util.TreeMap;

/**
 * 美团餐饮开放平台回调接口
 * @author AnYuan
 */

@RestController
public class DemoController {

    /**
     * 签名的字段名
     */
    private final static String SIG_FIELD_NAME = "sig";

    /**
     * 校验签名
     * @param request  HttpServletRequest对象
     * @return 签名是否正确
     */
    public Boolean checkSign(HttpServletRequest request) {

        String url = String.format("%s://%s%s", request.getScheme(), request.getServerName(), request.getRequestURI());
        TreeMap<String, String> treeMap = new TreeMap<>();
        Enumeration<String> parameterNames = request.getParameterNames();

        while(parameterNames.hasMoreElements()){
            String name = parameterNames.nextElement();
            String value = request.getParameter(name);
            if (!SIG_FIELD_NAME.equals(name)) {
                treeMap.put(name, value);
            }
        }

        String sign = sign(url, treeMap);
        if (sign.equals(request.getParameter(SIG_FIELD_NAME))) {
            System.out.println("签名正确");
            return true;
        }
        System.out.println("签名错误");
        return false;
    }

    /**
     * 生成签名
     * @param url 请求的完整的url
     * @param treeMap 请求的全部参数
     * @return sign
     */
    private String sign(String url, TreeMap<String, String> treeMap) {
        String queryString = Joiner.on("&").useForNull("").withKeyValueSeparator("=").join(treeMap);
        String md5str = url.concat("?").concat(queryString).concat("美团开放平台的APP密钥");
        try {
            return DigestUtils.md5DigestAsHex(URLDecoder.decode(md5str, "UTF-8").getBytes());
        } catch (UnsupportedEncodingException encodingException) {
            System.out.println("签名生成失败");
        }
        return "";
    }
}

  

这里 “美团餐饮开放平台的APP密钥” 是美团开发后台创建引用后获取的,不要直接写在代码里面,建议用配置文件进行管理。

 

分类:

技术点:

相关文章:

  • 2021-06-14
  • 2021-09-13
  • 2022-12-23
  • 2021-09-05
  • 2021-07-02
  • 2021-09-16
  • 2021-12-03
猜你喜欢
  • 2021-11-01
  • 2021-11-28
  • 2022-02-06
  • 2022-12-23
  • 2021-11-23
  • 2022-12-23
  • 2021-11-09
相关资源
相似解决方案