Skip to content

数据签名规范

  1. 所有通信都使用MD5计算摘要作为签名数据
  2. 所有参数按照字段名的 ASCII 码从小到大排序后使用 QueryString 的格式(即key1=value1&key2=value2…)拼接而成,再直接拼接秘钥 key 做为签名串,签名结果需要转换为小写

注意以下重要规则

  • 参数名ASCII码从小到大排序(字典序)
  • 使用 QueryString 的格式(即key1=value1&key2=value2…) 拼接,之后直接连接key的值进行加密
  • 不要再加入&key=这几个字符
  • 空值不参与签名,参数名也不必提交

例如

accNo=123&bankCode=21002&firstName=john&lastName=tom&merchantNo=mer618218&orderAmt=1000&orderNo=1723595359882&payEmail=john.tom@gmail.com&payPhone=02012345678&productCode=11002b980d6f4c5c4485e9160d63155e22365

JAVA示例

import java.util.Map;
import java.util.TreeMap;
import java.util.HashMap;
import java.util.Map.Entry;

public class SignUtil {

    public static String sign(Map<String, Object> paramMap, String signKey) {
        try {
            TreeMap<String, Object> sort = new TreeMap<>(paramMap);
            StringBuilder sb = new StringBuilder();
            for (Map.Entry<String, Object> entry : sort.entrySet()) {
                String key = entry.getKey();
                if ("sign".equals(key)) {
                    continue;
                }
                if (entry.getValue() == null || "".equals(entry.getValue())) {
                    continue;
                }
                String value = entry.getValue().toString();
                sb.append(key).append("=").append(value).append("&");
            }
            if (sb.length() > 0) {
                sb.deleteCharAt(sb.length() - 1);
            }
            sb.append(signKey);
            String verStr = SecureUtil.md5(sb.toString());
            return verStr;
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

    public static void main(String[] args) {
        String key = "b980d6f4c5c4485e9160d63155e22365";
        Map<String, Object> map = new HashMap<>();
        map.put("merchantNo", "mer618218");
        map.put("orderNo", "2343243243432");
        map.put("orderAmt", "10000");
        map.put("firstName", "john");
        map.put("lastName", "tom");
        map.put("payEmail", "john.tom@gmail.com");
        map.put("payPhone", "02012345678");
        map.put("productCode", "11002");
        map.put("notifyUrl", "http://www.xxx.com/notify");
        String sign = sign(map, key);
        map.put("sign", sign);
        System.out.println("签名结果: " + sign);
    }
}

NET示例

using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;

public class Program
{
    public static string Sign(Dictionary<string, object> paramMap, string signKey)
    {
        try
        {
            var sortedMap = paramMap
                .Where(kvp => kvp.Key != "sign" && kvp.Value != null && kvp.Value.ToString() != "")
                .OrderBy(kvp => kvp.Key)
                .ToList();

            var sb = new StringBuilder();
            foreach (var entry in sortedMap)
            {
                string key = entry.Key;
                string value = entry.Value.ToString();
                sb.Append(key).Append("=").Append(value).Append("&");
            }

            if (sb.Length > 0)
            {
                sb.Length--; // Remove the last '&'
            }
            sb.Append(signKey);

            using (var md5 = MD5.Create())
            {
                var hashBytes = md5.ComputeHash(Encoding.UTF8.GetBytes(sb.ToString()));
                return BitConverter.ToString(hashBytes).Replace("-", "").ToLowerInvariant();
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
            return "";
        }
    }

    public static void Main()
    {
        string key = "b980d6f4c5c4485e9160d63155e22365";
        var map = new Dictionary<string, object>
        {
            { "merchantNo", "mer618218" },
            { "orderNo", "2343243243432" },
            { "orderAmt", "10000" },
            { "firstName", "john" },
            { "lastName", "tom" },
            { "payEmail", "john.tom@gmail.com" },
            { "payPhone", "02012345678" },
            { "productCode", "11002" },
            { "notifyUrl", "http://www.xxx.com/notify" }
        };

        string sign = Sign(map, key);
        map["sign"] = sign;
    }
}

PHP示例

<?php

function sign($paramMap, $signKey) {
    try {
        ksort($paramMap);
        $sb = '';
        foreach ($paramMap as $key => $value) {
            if ($key === 'sign' || $value === null || $value === '') {
                continue;
            }
            $sb .= $key . '=' . $value . '&';
        }
        $sb = rtrim($sb, '&');
        $sb .= $signKey;

        return md5($sb);
    } catch (Exception $e) {
        echo $e->getMessage();
        return '';
    }
}

$key = "b980d6f4c5c4485e9160d63155e22365";
$map = [
    "merchantNo" => "mer618218",
    "orderNo" => "2343243243432",
    "orderAmt" => "10000",
    "firstName" => "john",
    "lastName" => "tom",
    "payEmail" => "john.tom@gmail.com",
    "payPhone" => "02012345678",
    "productCode" => "11002",
    "notifyUrl" => "http://www.xxx.com/notify"
];

$sign = sign($map, $key);
$map["sign"] = $sign;

?>