Skip to content

介绍

环境信息

环境地址
测试环境API地址请联系运营人员
测试环境商户后台请联系运营人员
生产请联系运营人员

注意,哥伦比亚时区为 GMT-5

API签名规范

注意,此规范适用于全部国家的API接入。

请求方式

Cashy所有的API接口都为 POST请求

通用请求头

参数名必选类型说明
Content-TypeYstringapplication/json
MerchantIdYint商户Id ,由Cashy生成,并提供给您
SignYstring请求签名,签名机制请见下文

通用响应结构

Cashy响应体示例

json
{
  "code": 200,
  "msg": "SUCCESS",
  "data": {}
}
参数名类型说明
codeint响应码,200为成功
msgstring响应消息
dataobject响应数据

TIP

注意 code 为 200 时,才代表请求成功,其他情况均为请求失败。具体失败原因请参考 msg 字段(可在每个国家文档附录中查阅)。

签名机制

为保证交易安全和API调用安全,Cashy会对所有接口的请求进行签名验证,您需要对所有的的请求进行签名,以供Cashy确认您的身份。

在接入前,Cashy会为接入商户分配商户沙盒环境的商户ID和商户apiKeyapiKey用于签名,商户ID用于标识商户身份。

TIP

  • 商户在请求Cashy的API接口时,应通过请求头MerchantId字段传递商户ID。
  • 商户在请求Cashy的API接口时,应采用MD5摘要算法对请求进行签名,签名通过请求头的Sign字段传递。

商户可以按照以下步骤生成请求签名。

  1. 拼接请求包体和商户apiKey。 content=请求包体+apiKey
  2. 通过Md5摘要算法计算签名。 signature = MD5(content)
  3. 通过请求头的Sign字段传递签名。

异步回调验签

Cashy在向您发送异步回调通知时,会按照上述机制对回调请求进行签名。您在接收到异步回调通知后,需要对回调请求进行验签,以确认回调请求确实来自Cashy。

  1. 计算签名 根据签名机制,获取Cashy异步回调通知的完整包体和您的商户Key拼接后,进行MD5计算,获得签名值。
  2. 验证签名 比较Cashy异步回调请求头中Sign字段的签名值与您计算出的签名值是否一致,若一致则验签通过,否则验签失败。

DANGER

我们强烈建议您 : 在处理来自Cashy的异步回调通知时,一定要验签,这样能最大程度保障您的资金安全。

签名/验签代码示例

java
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class DocsMerchantSignUtils {

    public static void main(String[] args) {
        String merchantId = "112345678";
        String apiKey = "K-xxxxxxxxxx";

        String httpRequestBody = "{\"orderNumber\":\"P123456\"}";

        // 签名
        String sign = DocsMerchantSignUtils.sign(httpRequestBody, apiKey);
        System.out.println(sign);
        // 验签
        System.out.println(DocsMerchantSignUtils.verifySign(sign, httpRequestBody, apiKey));
    }

    /**
     * @param content   content
     * @param secretKey secretKey
     * @return String  sign
     */
    public static String sign(String content, String secretKey) {
        String signStr = content + secretKey;
        MessageDigest md = null;
        try {
            md = MessageDigest.getInstance("MD5");
            md.update(signStr.getBytes());
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
        return byte2HexString(md.digest());
    }


    /**
     * @param sign      sign
     * @param content   content
     * @param secretKey secretKey
     * @return verify result
     */
    public static boolean verifySign(String sign, String content, String secretKey) {
        return sign.equalsIgnoreCase(sign(content, secretKey));
    }

    /**
     * @param data data
     * @return String
     */
    private static String byte2HexString(byte[] data) {
        final char[] alphabets = "0123456789ABCDEF".toCharArray();
        int len = data.length;
        char[] res = new char[len << 1];
        int i = 0;
        for (int j = 0; i < len; ++i) {
            res[j++] = alphabets[(240 & data[i]) >>> 4];
            res[j++] = alphabets[15 & data[i]];
        }
        return new String(res);
    }
}
go
package main

import (
 "crypto/md5"
 "fmt"
)

func Md5UtilsHash(bodyJson, apiKey string) string {
 data := []byte(bodyJson + apiKey)
 has := md5.Sum(data)
 md5str1 := fmt.Sprintf("%x", has) // Convert []byte to decimal
 return md5str1
}

func main() {
 body := "{\"test\":\"test\"}"
 apiKey := "K-xxxxxxx"// Your merchant key
 sign := Md5UtilsHash(body, apiKey)
 fmt.Println(sign)
}
php
<?php
function md5UtilsHash($bodyJson, $apiKey) {
    $data = $bodyJson . $apiKey;
    $md5str1 = md5($data);
    return $md5str1;
}
$body = "{\"test\":\"test\"}"; // RequestBody
$apiKey = 'K-xxxxxxx'; // ApiKey
$sign = md5UtilsHash($body, $apiKey);
echo $sign;
python
import hashlib
def md5_utils_hash(body_json, api_key):
    data = body_json + api_key
    md5_hash = hashlib.md5(data.encode()).hexdigest()
    return md5_hash
body = "{\"test\":\"test\"}" # RequestBody
api_key = 'K-xxxxxxx'  # ApiKey
sign = md5_utils_hash(body, api_key)
print(sign)

Released under the MIT License.