苍穹外卖-DAY09

  • 百度地图

    1
    https://lbsyun.baidu.com/apiconsole/key

    用来检测地址是否超过配送距离

    检验方式

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134


    /**
    * 检查客户的收货地址是否超出配送范围
    */
    private void checkOutOfRange(String address) throws UnsupportedEncodingException {
    // --- 第一步:获取店铺经纬度 ---
    Map<String, String> shopMap = new LinkedHashMap<>();
    shopMap.put("address", shopAddress);
    shopMap.put("output", "json");
    shopMap.put("ak", ak);

    // 【新增】必须添加 timestamp 参数,值为当前时间戳(毫秒)
    shopMap.put("timestamp", String.valueOf(System.currentTimeMillis()));

    // 计算SN并加入参数
    String shopSn = generateSn("/geocoding/v3", shopMap);
    shopMap.put("sn", shopSn);

    String shopCoordinate = HttpClientUtil.doGet("https://api.map.baidu.com/geocoding/v3", shopMap);
    JSONObject shopJson = JSON.parseObject(shopCoordinate);
    if (!"0".equals(shopJson.getString("status"))) {
    throw new OrderBusinessException("店铺地址解析失败: " + shopJson.getString("message"));
    }
    JSONObject shopLocation = shopJson.getJSONObject("result").getJSONObject("location");
    String shopLngLat = shopLocation.getString("lat") + "," + shopLocation.getString("lng");


    // --- 第二步:获取用户收货地址经纬度 ---
    Map<String, String> userMap = new LinkedHashMap<>();
    userMap.put("address", address);
    userMap.put("output", "json");
    userMap.put("ak", ak);

    // 【新增】必须添加 timestamp 参数
    userMap.put("timestamp", String.valueOf(System.currentTimeMillis()));

    // 计算SN并加入参数
    String userSn = generateSn("/geocoding/v3", userMap);
    userMap.put("sn", userSn);

    String userCoordinate = HttpClientUtil.doGet("https://api.map.baidu.com/geocoding/v3", userMap);
    JSONObject userJson = JSON.parseObject(userCoordinate);
    if (!"0".equals(userJson.getString("status"))) {
    throw new OrderBusinessException("收货地址解析失败: " + userJson.getString("message"));
    }
    JSONObject userLocation = userJson.getJSONObject("result").getJSONObject("location");
    String userLngLat = userLocation.getString("lat") + "," + userLocation.getString("lng");


    // --- 第三步:路线规划 (驾车) ---
    Map<String, String> driveMap = new LinkedHashMap<>();
    driveMap.put("origin", shopLngLat);
    driveMap.put("destination", userLngLat);
    driveMap.put("steps_info", "0");
    driveMap.put("ak", ak);

    // 【新增】必须添加 timestamp 参数
    driveMap.put("timestamp", String.valueOf(System.currentTimeMillis()));

    // 计算SN并加入参数 (注意URI变成了 directionlite/v1/driving)
    String driveSn = generateSn("/directionlite/v1/driving", driveMap);
    driveMap.put("sn", driveSn);

    String driveJsonStr = HttpClientUtil.doGet("https://api.map.baidu.com/directionlite/v1/driving", driveMap);
    JSONObject driveJson = JSON.parseObject(driveJsonStr);
    if (!"0".equals(driveJson.getString("status"))) {
    throw new OrderBusinessException("配送路线规划失败: " + driveJson.getString("message"));
    }

    JSONObject result = driveJson.getJSONObject("result");
    JSONArray jsonArray = result.getJSONArray("routes");
    Integer distance = jsonArray.getJSONObject(0).getInteger("distance");

    if (distance > 5000) {
    throw new OrderBusinessException("超出配送范围");
    }
    }

    /**
    * 核心算法:生成SN签名
    * 基于百度地图官方Java Demo改编
    *
    * @param uri 接口的URI,例如 /geocoding/v3
    * @param data 已经put好参数的LinkedHashMap
    * @return 计算后的sn字符串
    */
    private String generateSn(String uri, Map<String, String> data) throws UnsupportedEncodingException {
    try {
    // 1. 将Map参数转换为UrlEncoded的查询字符串
    StringBuilder queryString = new StringBuilder();
    for (Map.Entry<String, String> pair : data.entrySet()) {
    queryString.append(pair.getKey()).append("=");
    //以此处为例,Value必须进行UTF-8编码
    queryString.append(URLEncoder.encode(pair.getValue(), "UTF-8")).append("&");
    }
    if (queryString.length() > 0) {
    queryString.deleteCharAt(queryString.length() - 1);
    }

    // 2. 拼接:URI + ? + QueryString + SK
    String wholeStr = uri + "?" + queryString.toString() + sk;

    // 3. 对整个拼接后的字符串再次进行URLEncode (这一步非常关键,官方文档强调的)
    String tempStr = URLEncoder.encode(wholeStr, "UTF-8");

    // 4. MD5加密
    return MD5(tempStr);
    } catch (UnsupportedEncodingException e) {
    e.printStackTrace();
    return null;
    }
    }

    /**
    * MD5计算辅助方法
    */
    private String MD5(String md5) {
    try {
    java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
    byte[] array = md.digest(md5.getBytes());
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < array.length; ++i) {
    sb.append(Integer.toHexString((array[i] & 0xFF) | 0x100).substring(1, 3));
    }
    return sb.toString();
    } catch (NoSuchAlgorithmException e) {
    e.printStackTrace();
    }
    return null;
    }

    }

    总体代码如上

    image-20260208012405844