回调使用方式
回调说明
- 如需回调服务需要在控制台添加回调接口
- 添加回调域后,该服务下回调服务会自动往回调接口上推送数据
回调失败判定
- 当在控制台填写固定回调接口地址后,需要在接口中返回 success 字符串
以PHP为例
exit("success");
- 当回调接口未返回success字符串时,回调服务会被认定为失败,并重试
- 当重试次数达到3次时,该回调信息会被记录到数据库中,请使用接口查询
回调格式
- 通知信息是以 JSON 格式进行组织的,注意这里的 POST 格式的 ContentType 是 application/json。
公共头信息
以下的字段每种类型的回调都一定会携带:
| 参数名 | 类型 | 含义 |
|---|---|---|
| User-Agent | string | 回调代理信息 |
| Content-Type | string | application-json 数据格式 |
| Content-Length | int | 数据长度 |
User-Agent: vhall
Content-Type: application/json
Content-Length: content length
回调签名
使用请求参数构造规范化的请求字符串(Canonicalized Query String)
a) 按照参数名称的字典顺序对请求中所有的请求参数(包括文档中描述的“公共请求参数”和给定了的请求接口的自定义参数,但不能包括“公共请求参数”中提到signature参数本身)进行排序。
注:当使用GET方法提交请求时,这些参数就是请求URI中的参数部分(即URI中“?”之后由“&”连接的部分)。
b) 对每个请求参数的名称和值进行编码。名称和值要使用UTF-8字符集进行URL编码,URL编码的编码规则是:
- 对于字符 A-Z、a-z、0-9以及字符“-”、“_”、“.”、“~”不编码;
c) 对编码后的参数名称、私钥和值使用英文等号(|)进行连接。
d) 再把英文竖线连接得到的字符串按参数名称的字典顺序依次连接,即得到规范化字符串。
e) 如果参数值为数组,则值拼接为 Array 字符串 使用上一步构造的规范化字符MD5计算,即得到签名的字符串:
签名方法示例
//PHP版本代码
$privateKey = 'abcdefg'; // app secret_key
data = $_POST;
$sign = $data['signature'];
unset($data['signature']);
$sign_new = makeSignature($data , $privateKey);//调用签名生成函数
if($sign == $sign_new){
echo 'success';
}else{
echo 'fail';
}
//$privateKey为回调接口私钥
//$data为回传的POST数据数组,剔除掉signature键值
//签名生成函数
function makeSignature(array $data, $privateKey){
ksort($data);
$str = '';
$privateKey = md5($privateKey);
foreach ($data as $k => $v){
// 判断是否为数组
if (is_array($v)) {
$v = 'Array';
}
$str .= $k.'|'.$privateKey.'|'.$v;
}
return md5($str);
}
// JAVA版本代码
// com.test
// file MD5Util
package com.test;
import java.security.MessageDigest;
public class MD5Util {
private static String byteArrayToHexString(byte b[]) {
StringBuffer resultSb = new StringBuffer();
for (int i = 0; i < b.length; i++)
resultSb.append(byteToHexString(b[i]));
return resultSb.toString();
}
private static String byteToHexString(byte b) {
int n = b;
if (n < 0)
n += 256;
int d1 = n / 16;
int d2 = n % 16;
return hexDigits[d1] + hexDigits[d2];
}
public static String MD5Encode(String origin, String charsetname) {
String resultString = null;
try {
resultString = new String(origin);
MessageDigest md = MessageDigest.getInstance("MD5");
if (charsetname == null || "".equals(charsetname))
resultString = byteArrayToHexString(md.digest(resultString
.getBytes()));
else
resultString = byteArrayToHexString(md.digest(resultString
.getBytes(charsetname)));
} catch (Exception exception) {
}
return resultString;
}
private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5",
"6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };
}
// com.test
// file Sign
package com.test;
import java.util.*;
public class TestSign {
public static void sign(SortedMap<Object,Object> parameters, String privateKey) {
String str = "";
privateKey=MD5Util.MD5Encode(privateKey, "UTF-8");
Set es = parameters.entrySet();
Iterator it = es.iterator();
while(it.hasNext()) {
Map.Entry entry = (Map.Entry)it.next();
String key = (String)entry.getKey();
Object value = entry.getValue();
if(value instanceof String[]){
System.out.println("数组替换为 Array");
value = "Array";
}
str = str + key+"|"+privateKey+"|"+value;
}
String finalSign=MD5Util.MD5Encode(str,"UTF-8");
System.out.println("最终签名是\n"+finalSign);
}
}
查询失败回调记录
API 地址
api.vhallyun.com/api/v1/callback/fail-list
描述
查接收服务器未按指定格式返回数据的回调记录,回调方返回格式请参照 回调说明
入参
关于公共请求参数详细内容,请参考 公共请求参数。
| 参数 | 类型 | 是否必选 | 含义 |
|---|---|---|---|
| event | int | 是 | 回调事件 |
| start_time | timestamp | 是 | 查询开始时间,格式为:2017/01/01 00:00:00 |
| end_time | timestamp | 否 | 查询结束时间,默认为当前时间,格式为:2017/01/01 00:00:00 |
出参
| 参数 | 类型 | 是否必选 | 含义 |
|---|---|---|---|
| list | obj | 是 | 回调数据信息(数据同个回调接口产生的回调数据) |
错误码
| 错误码 | 类型 | 含义 |
|---|---|---|
| 10020 | int | 开始时间不能为空 |
| 40004 | int | 时间类型不正确 |
| 40007 | int | 回调事件类型不正确 |
响应格式
{
"code": 200,
"msg": "",
"data": [
{
"id": 0,
"record_id": "70545e9f",
"status": 1
}
]
}
