介绍
环境信息
类型 | 值 |
---|---|
测试/生产环境API地址 | 请联系运营人员 |
时区 | GMT+8 |
API签名规范
注意,此规范适用于全部国家的API接入。
请求方式
Cashy所有的API接口都为 POST
请求
通用请求头
参数名 | 必选 | 类型 | 说明 |
---|---|---|---|
Content-Type | Y | string | application/json |
MerchantId | Y | int | 商户Id ,由Cashy生成,并提供给您 |
Sign | Y | string | 请求签名,签名机制请见下文 |
通用响应结构
Cashy响应体示例
json
{
"code": 200,
"msg": "SUCCESS",
"data": {}
}
参数名 | 类型 | 说明 |
---|---|---|
code | int | 响应码,200为成功 |
msg | string | 响应消息 |
data | object | 响应数据 |
TIP
注意 code 为 200 时,才代表请求成功,其他情况均为请求失败。具体失败原因请参考 msg 字段(可在每个国家文档附录中查阅)。
签名机制
为保证交易安全和API调用安全,Cashy会对所有接口的请求进行签名验证,您需要对所有的的请求进行签名,以供Cashy确认您的身份。
在接入前,Cashy会为接入商户分配商户沙盒环境的商户ID和商户apiKey
,apiKey
用于签名,商户ID用于标识商户身份。
TIP
- 商户在请求Cashy的API接口时,应通过请求头
MerchantId
字段传递商户ID。 - 商户在请求Cashy的API接口时,应采用MD5摘要算法对请求进行签名,签名通过请求头的Sign字段传递。
商户可以按照以下步骤生成请求签名。
- 拼接请求包体和商户apiKey。
content
=请求包体
+apiKey
- 通过Md5摘要算法计算签名。
signature
=MD5(content)
- 通过请求头的Sign字段传递签名。
异步回调验签
Cashy在向您发送异步回调通知时,会按照上述机制对回调请求进行签名。您在接收到异步回调通知后,需要对回调请求进行验签,以确认回调请求确实来自Cashy。
- 计算签名 根据签名机制,获取Cashy异步回调通知的完整包体和您的商户Key拼接后,进行MD5计算,获得签名值。
- 验证签名 比较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\":\"1386556787811426305\"}";
// 签名
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)