关于签名

简介

🚧

用于生成API请求输入参数签名的秘钥应由商户安全地管理,不得向他人披露。

生成签名字符串的步骤如下:

  1. 把所有需要验证的参数,放入一个数组中。
  2. 按参数名称按照ASCII升序对数组进行排序。只按照参数名称进行排序,而非参数中的值。
  3. 在生成签名之前,从数组中排除 'sign' 参数本身。

示例

{  
    "appId": "TEST000001",  
    "sign": "TEST000001",  
    "merchantOrderNo": "11126",  
    "userId": "[email protected]",  
    "orderAmount": "1000",  
    "payCurrency": "USD",  
    "paymentTokens": "USDT,ETH",  
    "paymentExchange": "16f021b0-f220-4bbb-aa3b-82d423301957,9226e5c2-ebc3-4fdd-94f6-ed52cdce1420"  
}

准备签名串的拼接,将格式转换为 parameter_name=parameter_value,用 '&' 连接起来,最后附加密钥(secret)。结果如下所示:

appId=TEST000001&merchantOrderNo=11126&orderAmount=1000&payCurrency=USD&paymentExchange=16f021b0-f220-4bbb-aa3b-82d423301957,9226e5c2-ebc3-4fdd-94f6-ed52cdce1420&paymentTokens=USDT,ETH&[email protected]&key=***************W0b5nCak

从准备好的签名字符串继续操作,使用SHA-512算法生成最终的签名,并将其改为大写字母。签名的结果如下:

 3962E8FF2ABD24B806D744C6630B95A05855A2AB86944CCF52009D6E2582787EB0F34CFF323843DDA55B148D770390598AF335DDBECC61D702AA1A87EE93D

生成签名代码示例

import java.io.*;
import java.net.*;
import java.security.*;
import java.util.*;

public class Sha512Signer {
    
    public static String sha512Sign(Map<String, String> dataMap, String secretKey) throws NoSuchAlgorithmException {

        List<String> keys = new ArrayList<>(dataMap.keySet());
        Collections.sort(keys);


        StringBuilder queryString = new StringBuilder();
        for (String key : keys) {
            queryString.append(key).append("=").append(dataMap.get(key)).append("&");
        }


        queryString.append("key=").append(secretKey);
        String stringToSign = queryString.toString();
        System.out.println("String to sign: " + stringToSign);

        MessageDigest md = MessageDigest.getInstance("SHA-512");
        byte[] hash = md.digest(stringToSign.getBytes());
        StringBuilder hexString = new StringBuilder();
        for (byte b : hash) {
            hexString.append(String.format("%02x", b));
        }

        return hexString.toString().toUpperCase();
    }

    public static void main(String[] args) throws Exception {

        String url = "https://crypto-payment.alchemytech.cc/XXXXX";
        String appId = "XXXXX";
        String secret = "XXXXX";


        Map<String, String> reqData = new HashMap<>();
        reqData.put("merchantOrderNo", "XXXXX");
        reqData.put("appId", appId);


        String sign = sha512Sign(reqData, secret);
        reqData.put("sign", sign);


        StringBuilder jsonData = new StringBuilder("{");
        for (Map.Entry<String, String> entry : reqData.entrySet()) {
            jsonData.append("\"").append(entry.getKey()).append("\":\"").append(entry.getValue()).append("\",");
        }
        jsonData.deleteCharAt(jsonData.length() - 1); 
        jsonData.append("}");


        sendPostRequest(url, jsonData.toString());
    }


    private static void sendPostRequest(String url, String jsonData) throws IOException {
        URL obj = new URL(url);
        HttpURLConnection con = (HttpURLConnection) obj.openConnection();
        

        con.setRequestMethod("POST");
        con.setRequestProperty("Content-Type", "application/json");
        con.setDoOutput(true);
        

        try (OutputStream os = con.getOutputStream()) {
            byte[] input = jsonData.getBytes("utf-8");
            os.write(input, 0, input.length);	
        }


        int responseCode = con.getResponseCode();
        System.out.println("Response Code: " + responseCode);
        
        try (BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()))) {
            String inputLine;
            StringBuilder response = new StringBuilder();
            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine);
            }

            System.out.println("Response: " + response.toString());
        }
    }
}

import requests
import hashlib


def sha512_sign(data_dict, secret_key):
    sorted_items = sorted(data_dict.items())
    query_string = '&'.join(f"{str(k)}={str(v)}" for k, v in sorted_items)
    string_to_sign = query_string + f"&key={secret_key}"
    print(string_to_sign)
    sha512_hash = hashlib.sha512(string_to_sign.encode('utf-8')).hexdigest().upper()
    return sha512_hash

urls = "https://crypto-payment.alchemytech.cc/XXXXX"
appId = "XXXXX"
secret = "XXXXX"
req_data = {
    "merchantOrderNo":"XXXXX",
    "appId":appId,
}

sign = sha512_sign(req_data, secret)
req_data["sign"] = sign

print(requests.post(urls, json=req_data).text)
package main

import (
	"bytes"
	"crypto/sha512"
	"encoding/hex"
	"fmt"
	"io/ioutil"
	"net/http"
	"sort"
	"strings"
)

func sha512Sign(dataMap map[string]string, secretKey string) string {
	keys := make([]string, 0, len(dataMap))
	for key := range dataMap {
		keys = append(keys, key)
	}
	sort.Strings(keys)

	var queryStrings []string
	for _, key := range keys {
		queryStrings = append(queryStrings, fmt.Sprintf("%s=%s", key, dataMap[key]))
	}
	queryString := strings.Join(queryStrings, "&")


	stringToSign := queryString + "&key=" + secretKey
	fmt.Println("String to sign:", stringToSign)


	hash := sha512.New()
	hash.Write([]byte(stringToSign))
	signature := hex.EncodeToString(hash.Sum(nil))
	return strings.ToUpper(signature)
}

func main() {
	url := "https://crypto-payment.alchemytech.cc/XXXXX"
	appId := "XXXXX"
	secret := "XXXXX"


	reqData := map[string]string{
		"merchantOrderNo": "XXXXX",
		"appId":           appId,
	}


	sign := sha512Sign(reqData, secret)
	reqData["sign"] = sign

	jsonData := "{"
	for key, value := range reqData {
		jsonData += fmt.Sprintf("\"%s\":\"%s\",", key, value)
	}
	jsonData = jsonData[:len(jsonData)-1] + "}"

	resp, err := http.Post(url, "application/json", bytes.NewBuffer([]byte(jsonData)))
	if err != nil {
		fmt.Println("Error sending request:", err)
		return
	}
	defer resp.Body.Close()


	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println("Error reading response:", err)
		return
	}

	fmt.Println("Response:", string(body))
}