API 签名

签名参数

参数名

参数说明

备注

timestamp

⼗三位时间戳

1699261493465

httpMethod

请求方式 GET/POST

请求方式须大写

requestPath

请求路径

不包含域名

bodyString

请求参数

GET:为空
POST:请求参数

第一步:生成签名字符串

签名字符串固定为:timestamp + httpMethod + requestPath + bodyString

其中 requestPath、bodyString 中的参数,依据参数名使⽤字典顺序排序,去掉空值。

POST 请求

如:创建订单接口

  • timestamp:1699261493465
  • httpMethod:POST
  • requestPath:/open/api/v4/merchant/trade/create
  • bodyString:
{ "side": "BUY", "cryptoCurrency": "USDT", "address": "0xef17748b259a133a581e236ebc97edce3b50aaaf", "network": "TRX", "fiatCurrency": "USD", "amount": "100", "depositType": 2, "payWayCode": "10001", "alpha2": "US", "redirectUrl": "", "callbackUrl": "http://payment.jyoumoney.com/alchemyRamp/pay/callback?tradeNo=DZ02207091800356504" }bo'dbo'dd

(1)bodyString 参数排序

{"address":"0xef17748b259a133a581e236ebc97edce3b50aaaf","alpha2":"US","amount":"100","callbackUrl":"http://payment.jyoumoney.com/alchemyRamp/pay/callback?tradeNo=DZ02207091800356304","cryptoCurrency":"USDT","depositType":2,"fiatCurrency":"USD","network":"TRX","payWayCode":"10001","side":"BUY"}

(2)拼接签名字符串:

1699261493465POST/open/api/v4/merchant/trade/create{"address":"0xef17748b259a133a581e236ebc97edce3b50aaaf","alpha2":"US","amount":"100","callbackUrl":"http://payment.jyoumoney.com/alchemyRamp/pay/callback?tradeNo=DZ02207091800356304","cryptoCurrency":"USDT","depositType":2,"fiatCurrency":"USD","network":"TRX","payWayCode":"10001","side":"BUY"}

GET 请求

如:查询订单状态接口

  • timestamp:1699261493465
  • httpMethod:GET
  • requestPath:/open/api/v4/merchant/query/trade?orderNo=1028577684629876736&side=BUY&email=abc@gamial.com
  • bodyString:

(1)requestPath 参数排序

email=abc@gamial.com&orderNo=1028577684629876736&side=BUY

(2)拼接签名字符串

1699261493465GET/open/api/v4/merchant/query/trade?email=abc@gamil.com&orderNo=1028577684629876736&side=BUY

第二步:生成您的签名

public class AchSign { public static String apiSign(String timestamp, String method, String path, Map<String, String> paramMap, String secretkey) throws NoSuchAlgorithmException, InvalidKeyException { String content = timestamp + method.toUpperCase() + path + getJsonBody(paramMap); Base64.Encoder base = Base64.getEncoder(); String signVal = base.encodeToString(sha256(content.getBytes(StandardCharsets.UTF_8), secretkey.getBytes(StandardCharsets.UTF_8))); return signVal; } public static byte[] sha256(byte[] message, byte[] secret) throws NoSuchAlgorithmException, InvalidKeyException { Mac sha256_HMAC = Mac.getInstance("HmacSha256"); SecretKeySpec secretKey = new SecretKeySpec(secret, "HmacSha256"); sha256_HMAC.init(secretKey); return sha256_HMAC.doFinal(message); } private static String getJsonBody(Map<String,String> parameters) { if (parameters == null || parameters.isEmpty()) { return ""; } parameters = removeEmptyKeys(parameters); parameters = (Map) sortObject(parameters); return JSON.toJSONString(parameters); } private static Map removeEmptyKeys(Map map) { if (map.isEmpty()) { return map; } Map retMap = new HashMap(); Iterator<Map.Entry> iterator = map.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry<String, Object> entry = iterator.next(); if (entry.getValue() != null && !entry.getValue().equals("")) { retMap.put(entry.getKey(), entry.getValue()); } } return retMap; } private static Object sortObject(Object obj) { if (obj instanceof Map) { return sortMap((Map) obj); } else if (obj instanceof List) { sortList((List) obj); return obj; } return null; } private static Map sortMap(Map map) { if (map.isEmpty()) { return null; } SortedMap<String, Object> sortedMap = new TreeMap<>(removeEmptyKeys(map)); for (String sortKey : sortedMap.keySet()) { if (sortedMap.get(sortKey) instanceof Map) { sortedMap.put(sortKey, sortMap((Map) sortedMap.get(sortKey))); } else if (sortedMap.get(sortKey) instanceof List) { sortedMap.put(sortKey, sortList((List) sortedMap.get(sortKey))); } } return sortedMap; } private static List sortList(List list) { if (list.isEmpty()) { return null; } List objectList = new ArrayList(); List intList = new ArrayList(); List floatList = new ArrayList(); List stringList = new ArrayList(); List jsonArray = new ArrayList(); for (Object obj : list) { if (obj instanceof Map || obj instanceof List) { jsonArray.add(obj); } else if (obj instanceof Integer) { intList.add(obj); } else if (obj instanceof BigDecimal) { floatList.add(obj); } else if (obj instanceof String) { stringList.add(obj); } else { intList.add(obj); } } Collections.sort(intList); Collections.sort(floatList); Collections.sort(stringList); objectList.addAll(intList); objectList.addAll(floatList); objectList.addAll(stringList); objectList.addAll(jsonArray); list.clear(); list.addAll(objectList); List retList = new ArrayList(); for (Object obj : list) { if (obj instanceof Map) { retList.add(sortMap((Map) obj)); } else if (obj instanceof List) { retList.add(sortList((List) obj)); } else { retList.add(obj); } } return retList; } public static void main(String[] args) throws Exception { String timestamp = String.valueOf(System.currentTimeMillis()); String method = ""; String path = ""; Map map = new hashMap(); String secretkey = ""; String sign = apiSign(timestamp, method, path, map, secretkey); System.out.println(timestamp); System.out.println(sign); System.out.println(URLEncoder.encode(sign)); } }
<?php function generateSignature($timestamp, $httpMethod, $requestPath,$bodyString, $secretKey) { // Concatenate parameters for signature string $signatureString = $timestamp . $httpMethod . $requestPath . $bodyString ; echo "\n"."signatureString:".$signatureString; // Generate HMAC SHA256 signature using the secret key $signature = base64_encode(hash_hmac('sha256', $signatureString, $secretKey, true)); return $signature; } //Sort the parameters in lexicographical order and return json String function getStringToSign($params) { ksort($params); $json = json_encode($params); return stripslashes($json); } // Example for On Ramp $onRampHttpMethod = "POST"; $onRampRequestPath = "/open/api/v4/merchant/trade/create"; $appId= "f83Is2y7L425rxl8"; $onRampSecretKey = "4Yn8RkxDXN71Q3p0"; $timestamp = strval(time() * 1000); echo "timestamp:".$timestamp; //request parameters $paramsToSign = array( 'address' => 'TSx82tWNWe5Ns6t3w94Ye3Gt6E5KeHSoP8', 'alpha2' => 'US', 'amount' => '100', 'callbackUrl' => 'http://payment.jyoumoney.com/alchemyRamp/pay/callback?tradeNo=DZ02207091800356304', 'cryptoCurrency' => 'USDT', 'depositType' => '2', 'network' => 'TRX', 'fiatCurrency' => 'USD', 'payWayCode' => '10001', 'side' => 'BUY', ); $rawDataToSign = getStringToSign($paramsToSign); $onRampSignature = generateSignature($timestamp, $onRampHttpMethod, $onRampRequestPath, $rawDataToSign,$onRampSecretKey); echo "\n"."On Ramp Signature: " . $onRampSignature . PHP_EOL; ?>
import base64 import hashlib import hmac import json from urllib.parse import urlparse, urlencode def api_sign(timestamp, method, request_url, body, secretkey): content = timestamp + method.upper() + get_path(request_url) + get_json_body(body) print(content) key = secretkey.encode('utf-8') message = content.encode('utf-8') signature = hmac.new(key, message, hashlib.sha256).digest() signature_b64 = base64.b64encode(signature).decode('utf-8') return signature_b64 def sha256(message, secret): return hmac.new(secret.encode('utf-8'), message.encode('utf-8'), hashlib.sha256).digest() def get_path(request_url): parsed_url = urlparse(request_url) path = parsed_url.path params = dict(parsed_url.query) if not params: return path sorted_params = {k: params[k] for k in sorted(params)} query_string = urlencode(sorted_params) return f'{path}?{query_string}' def get_json_body(body): try: json_data = json.loads(body) except (json.JSONDecodeError, TypeError): json_data = {} if not json_data: return '' json_data = remove_empty_keys(json_data) return json.dumps(sort_object(json_data), separators=(',', ':')) def parse_path(request_url): parsed_url = urlparse(request_url) path = parsed_url.path params = dict(parsed_url.query) return path, params def is_json(json_string): try: json.loads(json_string) return True except (json.JSONDecodeError, TypeError): return False def remove_empty_keys(data): return {k: v for k, v in data.items() if v} def sort_object(data): if isinstance(data, dict): return {k: sort_object(v) for k, v in sorted(data.items())} elif isinstance(data, list): data.sort(key=sort_object) return [sort_object(item) for item in data] else: return data if __name__ == '__main__': timestamp = "" request_method = "" request_url = "" req_body = { "XXX": "XXXXX" } sign = api_sign(timestamp, method, request_url,get_json_body(json.dumps(req_body)), appSecret) print(sign)
import ( "bytes" "crypto/hmac" "crypto/sha256" "encoding/base64" "encoding/json" "fmt" "io/ioutil" "net/http" "net/url" "sort" "strings" "testing" "time" ) func PostRequest(url string, headers map[string]string, bodyData map[string]string) ([]byte, error) { requestBody, err := json.Marshal(bodyData) if err != nil { return nil, err } req, err := http.NewRequest("POST", url, bytes.NewBuffer(requestBody)) if err != nil { return nil, err } for key, value := range headers { req.Header.Set(key, value) } req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { return nil, err } defer resp.Body.Close() responseBody, err := ioutil.ReadAll(resp.Body) if err != nil { return nil, err } return responseBody, nil } func APISign(timestamp string, method string, requestURL string, body string, secretKey string) (string, error) { content := timestamp + strings.ToUpper(method) + getPath(requestURL) + getJSONBody(body) signature, err := calculateHMACSHA256([]byte(content), []byte(secretKey)) if err != nil { return "", err } return base64.StdEncoding.EncodeToString(signature), nil } func calculateHMACSHA256(message []byte, secret []byte) ([]byte, error) { hash := hmac.New(sha256.New, secret) _, err := hash.Write(message) if err != nil { return nil, err } return hash.Sum(nil), nil } func getPath(requestURL string) string { u, err := url.Parse(requestURL) if err != nil { return "" } path := u.Path query := u.Query() query.Del("") keys := make([]string, 0, len(query)) for key := range query { keys = append(keys, key) } sort.Strings(keys) var encodedParams []string for _, key := range keys { encodedParams = append(encodedParams, fmt.Sprintf("%s=%s", key, query.Get(key))) } paramsString := strings.Join(encodedParams, "&") if paramsString != "" { return path + "?" + paramsString } return path } func getJSONBody(body string) string { if body == "" { return "" } var data interface{} err := json.Unmarshal([]byte(body), &data) if err != nil { return "" } if dataMap, ok := data.(map[string]interface{}); ok && len(dataMap) == 0 { return "" } removeEmptyKeys(data) sortedData := sortObject(data) jsonBytes, err := json.Marshal(sortedData) if err != nil { return "" } return string(jsonBytes) } func removeEmptyKeys(data interface{}) { switch value := data.(type) { case map[string]interface{}: for key, v := range value { if v == nil || v == "" { delete(value, key) } else { removeEmptyKeys(v) } } case []interface{}: for _, v := range value { removeEmptyKeys(v) } } } func sortObject(data interface{}) interface{} { switch value := data.(type) { case map[string]interface{}: keys := make([]string, 0, len(value)) for k := range value { keys = append(keys, k) } sort.Strings(keys) sortedMap := make(map[string]interface{}) for _, k := range keys { v := sortObject(value[k]) sortedMap[k] = v } return sortedMap case []interface{}: for i, v := range value { value[i] = sortObject(v) } return value default: return value } } func main() { timestamp := fmt.Sprintf("%d", time.Now().UnixNano()/int64(time.Millisecond)) method := "XX" requestURL := "XXXXX" req_body := map[string]string{ "XXX": "XXXXX", } dataType, _ := json.Marshal(req_body) dataString := string(dataType) appId := "XXXXX" secretKey := "XXXXX" sign, err := APISign(timestamp, method, requestURL, dataString, secretKey) if err != nil { fmt.Println("Error:", err.Error()) return } headers := map[string]string{ "appId": appId, "timestamp": timestamp, "sign": sign, } response, err := PostRequest(requestURL, headers, req_body) if err != nil { fmt.Println("Error:", err) } else { fmt.Println(string(response)) }
const crypto = require('crypto'); const url = require('url'); function apiSign(timestamp, method, requestUrl, body, secretkey) { const content = timestamp + method.toUpperCase() + getPath(requestUrl) + getJsonBody(body); const signVal = crypto.createHmac('sha256', secretkey) .update(content, 'utf8') .digest('base64'); return signVal; } function sha256(message, secret) { const hmac = crypto.createHmac('sha256', secret); hmac.update(message); return hmac.digest(); } function getPath(requestUrl) { const uri = new URL(requestUrl); const path = uri.pathname; const params = Array.from(uri.searchParams.entries()); if (params.length === 0) { return path; } else { const sortedParams = [...params].sort(([aKey], [bKey]) => aKey.localeCompare(bKey)); const queryString = sortedParams.map(([key, value]) => `${key}=${value}`).join('&'); return `${path}?${queryString}`; } } function getJsonBody(body) { let map; try { map = JSON.parse(body); } catch (error) { map = {}; } if (Object.keys(map).length === 0) { return ''; } map = removeEmptyKeys(map); map = sortObject(map); return JSON.stringify(map); } function parsePath(requestUrl) { const uri = new URL(requestUrl); const path = uri.pathname; const params = Object.fromEntries(uri.searchParams.entries()); return { path, params }; } function isJson(jsonString) { if (!jsonString || jsonString === '') { return false; } try { JSON.parse(jsonString); return true; } catch (error) { return false; } } function removeEmptyKeys(map) { const retMap = {}; for (const [key, value] of Object.entries(map)) { if (value !== null && value !== '') { retMap[key] = value; } } return retMap; } function sortObject(obj) { if (typeof obj === 'object') { if (Array.isArray(obj)) { return sortList(obj); } else { return sortMap(obj); } } return obj; } function sortMap(map) { const sortedMap = new Map(Object.entries(removeEmptyKeys(map)).sort(([aKey], [bKey]) => aKey.localeCompare(bKey))); for (const [key, value] of sortedMap.entries()) { if (typeof value === 'object') { sortedMap.set(key, sortObject(value)); } } return Object.fromEntries(sortedMap.entries()); } function sortList(list) { const objectList = []; const intList = []; const floatList = []; const stringList = []; const jsonArray = []; for (const item of list) { if (typeof item === 'object') { jsonArray.push(item); } else if (Number.isInteger(item)) { intList.push(item); } else if (typeof item === 'number') { floatList.push(item); } else if (typeof item === 'string') { stringList.push(item); } else { intList.push(item); } } intList.sort((a, b) => a - b); floatList.sort((a, b) => a - b); stringList.sort(); objectList.push(...intList, ...floatList, ...stringList, ...jsonArray); list.length = 0; list.push(...objectList); const retList = []; for (const item of list) { if (typeof item === 'object') { retList.push(sortObject(item)); } else { retList.push(item); } } return retList; } const timestamp = String(Date.now()); const method = 'XXXXX'; const requestUrl = 'XXXXX'; const body = ''; const secretkey = 'XXXXX'; const sign = apiSign(timestamp, method, requestUrl, body, secretkey); console.log(timestamp); console.log(sign); console.log(encodeURIComponent(sign));

Did this page help you?