必读说明,几分钟让你掌握所有接口对接方法(常见问题这里都有说明)
开发必读接口说明
这里讲述了接口的一些规范、请求方法、统一响应结构注释、全局公共参数、请求签名计算、请求数据加密规则、响应数据验签规则、响应数据解密、请求防劫持篡改验证、响应数据格式等一系列传输的说明
应用区分接口说明
栓Q验证系统的部分接口是区分应用类型的,有的接口区分有的不区分通用,每个应用类型都有不同的对接场景,每个应用的接口也都不一样
接口请求方法与入参说明
默认所有接口都同时支持Get、Post请求(除了一些文件上传等特殊接口固定为Post),每个应用都支持对每个接口独立设置请求方法,可指定为Get或Post请求,而入参方式支持以上两种方式外还支持路由地址参数,通常以上两种入参方式的参数数据格式为key1=value1&key2=value2&key3=value3,而路由地址参数只需要在接口地址后面拼接上对应的kv参数,示例格式:/key1/value1/key2/value2/key3/value3,假设请求接口地址为http://demo.shuanq.cn/api/app/get_app_info,那么加上路由参数则为http://demo.shuanq.cn/api/app/get_app_info/key1/value1/key2/value2/key3/value3
接口统一响应结构说明(默认响应JSON格式)
{
"code":1,
"message":"获取成功",
"timestamp":1673806650,
"nonceStr":"0f172f4ac2d8eafa5a0175a541cb1f81",
"data":"{\"info\":{\"name\":\"无加密算法测试-单码\",\"avatar\":\"http:\\/\\/yanzheng.giao.cc\\/index\\/system\\/get_custom_image\\/name\\/dXBsb2Fkcy9pbWFnZXMvc3lzdGVtX2ltYWdlLzIwMjIwNzAxLzkzZjQxOTVjMmQxZGFhNjM0YjQ4ZmY1NWUzNTEzMDA1LkpQRw==\",\"type\":0,\"addtime\":1664864027,\"param_extend_config\":{}},\"user_safe_config\":{\"token_verify_open\":false,\"token_unlimited\":true,\"machine_code_binding_top_limit\":\"2\",\"online_machine_upper_limit\":\"2\",\"online_machine_upper_limit_login_scheme\":1,\"token_invalid_duration\":\"1\",\"machine_code_verify\":true,\"online_time_difference\":\"60\",\"token_update_mechanism\":0,\"self_service_unbinding\":{\"open\":false,\"verify_user_token\":false,\"interval\":0,\"frequency_limit_type\":0,\"frequency_limit_value\":0,\"deduction_time\":0,\"verify_original_machine\":false}},\"moreOtherData\":{\"api_extra_data\":\"\",\"request_safe_code\":\"\"}}",
"signature":"56e0afb0ec3055b561e53582fbebd7ca"
}
参数名 | 类型 | 说明 | 必填 |
---|---|---|---|
code | integer | 业务码(1为成功,其他为失败-支持后台自定义更改) | 是 |
message | string | 返回业务信息-支持后台自定义更改 | 是 |
data | string | 数据信息(通常为接口的业务数据,是一个转JSON字符串的object,若开启响应返回值加密则是加密后的密文) | 是 |
timestamp | integer | 当前时间戳(10位) | 是 |
nonceStr | string | 随机字串 | 是 |
signature | string | 本次响应签名 | 是 |
统一响应结构data字段内的moreOtherData对象字段说明
参数名 | 类型 | 说明 | 必填 |
---|---|---|---|
api_extra_data | string | 接口设置的自定义额外返回数据 | 是 |
request_safe_code | string | 请求防劫持安全验证码 | 是 |
全局公共请求参数说明
注意,公共参数在不同应用功能场景下有的参数是非必填的
参数名 | 类型 | 说明 |
---|---|---|
appid | string | 应用ID,如果请求的接口路由地址是默认的那么就必须传入此参数 |
timestamp | integer | 客户端当前时间戳(10位),如果设置启用了接口传输签名验证则需要传递此参数 |
signature | string | 参数签名,如果设置启用了接口传输签名验证则需要传递此参数,签名计算规则详见请求签名计算说明 |
request_safe_code | string | 本次请求防劫持安全验证码,非必填,若有防劫持验证判断的需求可传入此参数,参数值自定,服务器会原样响应返回给客户端进行验证判断 |
integer | 指定分页页数(非必填,默认值1,针对一些需要列表分页接口) | |
integer | 每页数据数量(非必填,默认值10,针对一些需要列表分页接口) | |
string | 用户机器码-此参数在需要验证用户身份情况下且开启机器设备验证时传入 | |
string | 用户的token(登录后可取得),此参数在需要验证用户身份情况下且开启token验证时传入 | |
string | 用户卡密-此参数在单码应用且需要验证用户身份情况下传入 | |
integer | 用户ID-此参数在会员应用且需要验证用户身份情况下传入 | |
string | 用户授权信息(自定义值用户唯一标识码)-此参数在授权应用且需要验证用户身份情况下传入 |
接口响应码与响应信息说明
自栓Q验证系统V6.3版本后,新增了接口响应码管理,在这里可以查看所有接口的响应码和响应信息,也可以按每个应用进行更改,默认全局的接口业务成功响应码为1,系统异常响应码为-2,业务处理失败响应码为-1或其他值
所有的接口响应码与响应信息都是可以按每个应用自定义更改的,在应用管理的接口响应码管理,可以看见所有的响应码以及对应的业务信息,你也可以输入响应码搜索查找该码的业务信息是什么意思,也可以按某个接口搜索响应码等(注:由于我这边是开发环境所以有添加、编辑、删除等操作,正式版搭建后是没有的,所以不用纠结这个问题)
选择你想要更改的响应码、响应业务信息点击应用单独配置(跟应用接口单独配置是一样的),然后输入你想要自定义的业务码或业务信息,不填则是使用默认的信息
接口请求签名计算说明
开启传输验签方式功能后请求所有接口都需要额外传递参数timestamp=10位时间戳、signature=参数签名值,计算签名值的方法:所有参数按照字典排序拼接参数字符串结尾加上应用密钥再加密即可,签名示例: 假设你设置的传输验签方式是MD5,应用密钥是abc888,请求某个接口传递的参数是a=1&e=2&c=3×tamp=1666688004&k=4,那么字典排序就是a=1&c=3&e=2&k=4×tamp=1666688004,字典排序后将应用密钥拼在结尾,最终待加密的签名字串是a=1&c=3&e=2&k=4×tamp=1666688004abc888,最后再取md5即可
C++签名示例
//获取计算参数签名字符串方法
std::string getParamsSignString(std::map<std::string, std::string> params) {
//开始计算签名值(遍历所有参数key value进行字符串拼接,除了appid和空value外)
std::string signStr = "";
for (std::map<std::string, std::string>::iterator it = params.begin(); it != params.end(); ++it) {
if (it->first != "" && it->second != "" && it->first != "appid" && it->first != "signature") {
if (signStr != "") {
signStr.append("&");
}
signStr.append(it->first + "=" + it->second);
}
}
return signStr;
}
void main()
{
std::string ShuanQ_AppKey="这里是你的应用密钥";
std::map<std::string, std::string> params;
params["shuanq"]="shuanq.cn";
params["qq"]="775294852";
std::string signatureStr=getParamsSignString(params)+ShuanQ_AppKey;
std::cout << "签名字符串-未md5/sha1:" << signatureStr << std::endl;
}
PHP签名示例
//获取计算参数签名字符串方法
function getParamsSignString($paramArr): string
{
if(empty($paramArr)) return '';
ksort($paramArr);
$str = '';
foreach ($paramArr as $k => $v){
if(!empty($v) && $k!='signature' && $k!='appid'){
$str .= $k.'='.$v.'&';
}
}
$signStr=rtrim($str,'&');
return $signStr;
}
$params=[
"shuanq"=>"shuanq.cn",
"qq"=>"775294852"
];
$ShuanQ_AppKey="这里是你的应用密钥";
$signatureStr=getParamsSignString($params) . ShuanQ_AppKey;
echo "签名字符串-未md5/sha1:" . signatureStr;
Java签名示例
//获取计算参数签名字符串方法
public static String getParamsSignString(Map<String, String> map) {
String result = "";
try {
List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(map.entrySet());
// 对所有传入参数按照字段名的 ASCII 码从小到大排序(字典序)
Collections.sort(infoIds, new Comparator<Map.Entry<String, String>>() {
public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
return (o1.getKey()).toString().compareTo(o2.getKey());
}
});
// 构造签名键值对的格式
StringBuilder sb = new StringBuilder();
for (Map.Entry<String, String> item : infoIds) {
if (item.getKey() != null || item.getKey() != "") {
String key = item.getKey();
String val = item.getValue();
if (!val.equals("") && val != null && !key.equals("signature") && !key.equals("appid")) {
sb.append(key + "=" + val + "&");
}
}
}
result = sb.toString();
result = trimFirstAndLastChar(result, '&');
} catch (Exception e) {
return null;
}
return result;
}
public static void main(String[] args)
{
HashMap<String, String> params = new HashMap<>();
params.put("shuanq","shuanq.cn");
params.put("qq","775294852");
String ShuanQ_AppKey="这里是你的应用密钥";
String signatureStr=getParamsSignString(params)+ShuanQ_AppKey;
System.out.println("签名字符串-未md5/sha1:" + signatureStr);
}
...更多语言案例可在群文件或网盘下载对应对接案例查看
接口响应签名计算说明
接口响应签名验证可提升数据安全性,每次请求接口服务器都会进行响应签名,客户端可接收签名参数进行验签,也可以不进行验签,这个取决于自己并非强制,验签字串计算规则目前有多种方式,每一种方式组成的签名字串都是不一样的,并且验签字串加密方法也是自选的,具体看后台是如何设置的
以下为每种方式的签名计算方法说明(假设加密方法为md5)
方式1:signature=md5(响应数据data + 应用密钥)
方式2:与接口请求签名计算规则一致
方式3:signature=md5(响应数据data + 响应数据timestamp + 应用密钥)
接口请求参数加密说明
默认不加密也就是明文请求传输,如果开启了参数名或参数值加密,那么传递的参数就必须加密然后进行编码,否则服务器会收到参数后会进行解密操作,如果解密失败,则会视为没有传递对应的参数,而加密算法可自选或自定义实现,算法对应的密钥可自定义设置
假如加密算法是aes,编码方式为十六进制,传入的参数是key1=value1,那么开启参数名加密的话key1就必须经过aes加密得到加密字节再转十六进制(假设结果为2ab4e),那么最终传入的参数则是2ab4e=value1,同理,开启参数值加密也是一样的,将value1经过aes加密得到加密字节再转十六进制(假设结果为6df2ac),那么最终传入的参数则是2ab4e=6df2ac
关于自定义算法:自定义算法需要自己编写代码实现函数方法(PHP语言,需要使用eval函数请确保没有被禁用),数据转码和解码服务器会自动处理不需要手动接手处理
自定义算法实现示例-加密函数实现方法代码(响应时处理):
//传入的变量 $AppInfo 是当前应用信息所有数据及配置信息-可参照数据库aimakeji_app表查看数据结构
//传入的变量 $ApiInfo 是当前请求的接口信息数据-可参照数据库aimakeji_app_api表查看数据结构
//传入的变量 $ApiConfig 是当前应用的当前接口的配置信息数据-可参照数据库aimakeji_app_api_config表查看数据结构
//传入的变量 $AppEncryptionConfig 是当前应用的接口通信与加密配置对象(与当前接口单独配置的参数进行合并后的),可通过它获取当前接口通信加密配置信息(可参考 http://doc.shuanq.cn/doc-2772854 解释)
//传入的变量 $ResponseData 是响应数据data字段内容,为Json字符串(原始数据为响应成功后的data数组)
function apiDataTransferEncryptionEncryptFunction(Array $AppInfo, Array $ApiInfo, Array $ApiConfig, \app\api\common\entity\EncryptionConfig $AppEncryptionConfig, String $ResponseData) : String
{
return openssl_encrypt($ResponseData, 'AES-128-CBC', "myKey_1234567890", OPENSSL_RAW_DATA, "myIv_12345678910");//AES-128-CBC
//return openssl_encrypt($ResponseData, 'AES-128-ECB', "myKey_1234567890", OPENSSL_RAW_DATA);//AES-128-ECB
//return base64_encode($ResponseData);//base64
}
自定义算法实现示例-解密函数实现方法代码(请求时处理):
//传入的变量 $AppInfo 是当前应用信息所有数据及配置信息-可参照数据库aimakeji_app表查看数据结构
//传入的变量 $ApiInfo 是当前请求的接口信息数据-可参照数据库aimakeji_app_api表查看数据结构
//传入的变量 $ApiConfig 是当前应用的当前接口的配置信息数据-可参照数据库aimakeji_app_api_config表查看数据结构
//传入的变量 $AppEncryptionConfig 是当前应用的接口通信与加密配置对象(与当前接口单独配置的参数进行合并后的),可通过它获取当前接口通信加密配置信息(可参考 http://doc.shuanq.cn/doc-2772854 解释)
//传入的变量 $InputData 是当前请求的所有输入的参数信息-请求参数键值对数组
//传入的变量 $Value 是当前需要处理解密的参数键值对内容-可能是key也可能是value
function apiDataTransferEncryptionDecryptFunction(Array $AppInfo, Array $ApiInfo, Array $ApiConfig, \app\api\common\entity\EncryptionConfig $AppEncryptionConfig, Array $InputData, String $Value) : String
{
return openssl_decrypt($this->input_decrypt_decode($Value), 'AES-128-CBC', "myKey_1234567890", OPENSSL_RAW_DATA, "myIv_12345678910");//AES-128-CBC
//return openssl_decrypt($this->input_decrypt_decode($Value), 'AES-128-ECB', "myKey_1234567890", OPENSSL_RAW_DATA);//AES-128-ECB
//return base64_decode($Value);//base64
}
接口请求参数加密与接口请求签名计算功能同时使用如何计算签名?
当遇到同时使用情况下,签名计算规则依旧不变,顺序为先计算签名(明文数据签名),再进行所有参数加密
请求响应返回值加密解密说明
默认返回值是不加密的,若开启 接口响应数据加密 功能后响应数据data就会被加密,而采用的加密算法则是跟传输参数加密的算法是一致的包括编码方式,假设加密算法设置的是aes,编码方式是十六进制,那么拿到响应数据后,先将data数据解码十六进制得到原密文字节,再进行aes加密即可得到明文数据
响应返回值数据格式说明
默认的响应数据格式为JSON格式,可在后台自定义设置可选为JSON、xml、文本标签格式,这里的设置是针对全局接口的
接口参数、接口地址、传输签名和加密以及响应签名加密等一系列接口传输相关的功能如何对某个接口独立定制对应的功能控制?
以上功能是针对全局的,当然也可以按每个应用对某个接口进行独立设置,在接口管理可查看所有接口,点击应用单独配置即可配置每个应用对该接口的独立功能规则
通信与加密独立配置
可按每个应用设置某个接口单独定制设置一遍全局的接口通信与加密独立配置,以上接口相关的所有功能都支持独立设置
接口开关控制
可按每个应用设置某个接口是否禁用,开启禁用后,该接口在该应用下不可请求调用
自定义请求方法、接口路由地址
可按每个应用设置某个接口的请求方法以及自定义个性化的接口请求地址,设置了自定义接口地址后,那么全局公共请求参数的appid可不用传入
自定义请求参数
可按每个应用设置某个接口的自定义请求参数,设置自定义参数名后,请求接口传入数据的参数名将必须按自定义参数名传入,否则服务器将找不到对应的参数
自定义附加响应数据
可按每个应用设置某个接口额外响应返回自定义数据,内置纯文本编辑器、富文本编辑器、代码编辑器(支持多语言高亮)方便数据编辑
自定义控制用户验证
可按每个应用设置某个接口设置是否验证用户身份机器码、登录token等信息