开发 服务端 担保支付(自动续费) 签约信息查询能力
# 签约信息查询能力
更新时间:2024-07-26 11:21:19
# 1 签约支付单信息查询
# 1.1 接口说明
开发者可以用该接口,查询签约支付单和签约信息
# 1.2 基本信息
名称 | 内容 |
HTTP URL | https://open.kuaishou.com/openapi/mp/developer/epay/contract/query_order_info |
HTTP Method | POST |
Scope | 需要具有小程序担保支付权限(scope.ks.epay) |
# 1.3 请求头
名称 | 字段类型 | 内容 |
Content-Type | String | 固定值: "application/json" |
# 1.4 请求参数
以下字段放在 query param 处:
字段名 | 类型 | 是否必填 | 是否参与签名 | 说明 |
app_id | string | 是 | 是 | 小程序AppId 例如:ks707065143182458884 |
access_token | string | 是 | 否 | 拥有小程序支付权限的access token,获取方式见getAccessToken |
以下字段放置到 body json中:
字段名 | 类型 | 是否必填 | 是否参与签名 | 说明 |
out_order_no | string[6,32] | 是 | 是 | 商户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一 示例值:1217752501201407033233368018 |
sign | string | 是 | 否 | 开发者对核心字段签名, 签名方式见 附录 |
# 1.5 请求示例
curl --location --request POST 'https://open.kuaishou.com/openapi/mp/developer/epay/contract/query_order_info
?app_id=ks707065143182458884&access_token=ChFvYXV0aC5hY2Nlc3NUb2tlbhJQcXi6SorFfkg786OWTtGyvXf1Qz0wbN2pt4YlWHppV78IzJA92mwdcdRqegxMFRwBRTM6r5vVYzMFUlbqAfPpdYYKpRlywCtyzomu7d_mt44aEqr20o3-d0Tt4_ZJzk9p2G6vnyIg4o35UNBVgOdoJEObJmLLnr4IiN6SZO3G2saTmDnPtLEoDzAB' \
--header 'Content-Type: application/json' \
--data '{
"out_order_no":"1711619867139contractDemo",
"sign":"360a9add284bb4e2050673132418a356"
}'
# 1.6 响应结果
返回值为 JSON 形式,其中包括如下字段:
字段名 | 类型 | 说明 |
result | number | 状态码 1-业务处理成功 |
error_msg | string | 错误提示信息,常见错误处理可参考附录常见问题章节 |
payment_info | json |
签约支付单信息 |
contract_info | json |
签约单信息 |
其中 payment_info 各字段含义如下
字段名 | 类型 | 说明 |
open_id | string | 快手用户在当前小程序的唯一id |
order_no | string | 快手小程序平台订单号 |
pay_amount | number | 用户支付/代扣金额,单位为[分] |
pay_channel | string | 支付渠道。 取值: UNKNOWN - 未知 WECHAT - 微信 ALIPAY - 支付宝 |
pay_status | string | 支付状态。 取值: UNKNOWN - 未知 PRE_PAY - 待支付 PROCESSING - 处理中 TIMEOUT - 支付超时 FAILED - 支付失败 SUCCESS - 支付成功 |
pay_time | number | 支付完成时间,毫秒级时间戳 |
其中 contract_info 各字段含义如下
字段名 | 类型 | 说明 |
open_id | string | 快手用户在当前小程序的唯一id |
contract_no | string | 快手小程序平台签约单号 |
contract_status | string | 签约状态。 取值: CONTRACT_PROCESSING - 签约处理中 CONTRACT_SUCCESS - 签约成功 CONTRACT_FAIL - 签约失败 UNCONTRACT_PROCESSING - 解约处理中 UNCONTRACT_SUCCESS - 解约成功 UNCONTRACT_FAIL - 解约失败 |
contract_time | number | 签约时间,毫秒级时间戳 |
uncontract_time | number | 解约时间,毫秒级时间戳 |
示例如下(仅供参考):
{
"result":1,
"error_msg":"错误信息提示",
"payment_info": {
"open_id": "xxxxxxxx",
"order_no": "121072611585202788127",
"pay_amount" : 100,
"pay_channel" : "ALIPAY",
"pay_status" : "SUCCESS",
"pay_time" : 1711933922241
},
"contract_info" : {
"open_id": "xxxxxxxx",
"contract_no" : "524010201547195973250",
"contract_status" : "CONTRACT_SUCCESS",
"contract_time" : 1711973828915,
"uncontract_time" : 1811973828915
}
}
当 result 不为 1 时,说明请求错误,错误信息详见文章末尾 错误码 处。
# 2 签约信息查询
# 2.1 接口说明
开发者可以用该接口,查询用户签约单的详细信息,包括签约信息,支付单信息,所有的代扣单信息
# 2.2 基本信息
名称 | 内容 |
HTTP URL | https://open.kuaishou.com/openapi/mp/developer/epay/contract/query_contract_info |
HTTP Method | POST |
Scope | 需要具有小程序担保支付权限(scope.ks.epay) |
# 2.3 请求头
名称 | 字段类型 | 内容 |
Content-Type | String | 固定值: "application/json" |
# 2.4 请求参数
以下字段放在 query param 处:
字段名 | 类型 | 是否必填 | 是否参与签名 | 说明 |
app_id | string | 是 | 是 | 小程序AppId 例如:ks707065143182458884 |
access_token | string | 是 | 否 | 拥有小程序支付权限的access token,获取方式见getAccessToken |
以下字段放置到 body json中:
字段名 | 类型 | 是否必填 | 是否参与签名 | 说明 |
contract_no | string | 是 | 是 | 签约单号,签约回调里的 contract_no |
sign | string | 是 | 否 | 开发者对核心字段签名, 签名方式见 附录 |
# 2.5 请求示例
curl --location --request POST 'https://open.kuaishou.com/openapi/mp/developer/epay/contract/query_contract_info
?app_id=ks707065143182458884&access_token=ChFvYXV0aC5hY2Nlc3NUb2tlbhJQArRFRpcpLbj-HDpUWMRdDYPAFOO7tmAk8nQCPwzJ4hSFDAh0T1UDzzuFl-PpbeagQXJrGqgg7US3GJWl74FrstOZaJteWiZeccC7VBbLoUMaEiJK7-q_EK3iKvXdVXsh9vuWMiIgeKm-doDgbvfEDy3QS9D8mqh27IbzMmeWVpyKVpOwu9soDzAB' \
--header 'Content-Type: application/json' \
--data '{
"contract_no":"524010201776062339152",
"sign":"00c17abfee6837a7905000ee6c853c10"
}'
# 2.6 响应结果
返回值为 JSON 形式,其中包括如下字段:
字段名 | 类型 | 说明 |
result | number | 状态码 1-业务处理成功 |
error_msg | string | 错误提示信息,常见错误处理可参考附录常见问题章节 |
contract_info | json | 签约信息 |
其中 contract_info 各字段含义如下
字段名 | 类型 | 说明 |
open_id | string | 快手用户在当前小程序的唯一id |
contract_no | string | 快手小程序平台签约号 |
contract_status | string | 签约状态。 取值: CONTRACT_PROCESSING - 签约处理中 CONTRACT_SUCCESS - 签约成功 CONTRACT_FAIL - 签约失败 UNCONTRACT_PROCESSING - 解约处理中 UNCONTRACT_SUCCESS - 解约成功 UNCONTRACT_FAIL - 解约失败 |
contract_product | string | 签约产品名称 |
template_type | number | 签约模版类型 1:周 2:月 3:季度 4:年 5:固定30天 6:固定31天 |
order_info | json |
其中 pay_status 取值如下: 签约支付单信息 |
withhold_infos | json list |
其中 withhold_status 取值如下: 代扣单信息,注意返回的json是代扣单列表 |
pay_channel | string | 支付渠道。 取值: UNKNOWN - 未知 WECHAT - 微信 ALIPAY - 支付宝 |
contract_time | number | 签约时间,毫秒级时间戳 |
uncontract_time | number | 解约时间,毫秒级时间戳 |
next_withhold_start_time | number | 下次代扣开始时间,毫秒级时间戳, 注意: 1. 这个时间精确到日,且是闭区间 2. 只有签约单签约成功时,该字段返回值有意义 |
next_withhold_end_time | number | 下次代扣结束时间,毫秒级时间戳 。 注意: 1. 这个时间精确到日,且是开区间(比如: 返回的是2月15日,2月15日当天并不会扣款) 2.只有签约单签约成功时,该字段返回值有意义 |
示例如下(仅供参考):
{
"result":1,
"error_msg":"错误信息提示",
"contract_info": {
"open_id": "xxxxxxxx",
"contract_no": "524010201547195973250",
"contract_status" : "CONTRACT_SUCCESS",
"contract_product": "kuaishou_vip"
"template_type" : 1,
"order_info" : {
"order_no": "121072611585202788127",
"pay_amount" : 100,
"pay_status" : "SUCCESS",
"pay_time" : 1711933922241
},
"withhold_infos" : [
{
"withhold_order_no": "624010201147476465250",
"withhold_amount" : 100,
"current_period" : 1,
"withhold_status" : "SUCCESS",
"withhold_time" : 1711933922241
},
{
"withhold_order_no": "624010201147476465250",
"withhold_amount" : 100,
"current_period" : 2,
"withhold_status" : "SUCCESS",
"withhold_time" : 1711933922241
}
],
"pay_channel": 2,
"contract_time" : 1711973828915,
"uncontract_time" : 1711983828915,
"next_withhold_start_time": 1711936841430,
"next_withhold_end_time": 1711936841530
}
}
当 result 不为 1 时,说明请求错误,错误信息详见文章末尾 错误码 处。
# 3 退款信息查询
# 3.1 接口说明
开发者可以用该接口,查询用户签约支付单和代扣单退款结果
# 3.2 基本信息
名称 | 内容 |
HTTP URL | https://open.kuaishou.com/openapi/mp/developer/epay/contract/query_refund_info |
HTTP Method | POST |
Scope | 需要具有小程序担保支付权限(scope.ks.epay) |
# 3.3 请求头
名称 | 字段类型 | 内容 |
Content-Type | String | 固定值: "application/json" |
# 3.4 请求参数
以下字段放在 query param 处:
字段名 | 类型 | 是否必填 | 是否参与签名 | 说明 |
app_id | string | 是 | 是 | 小程序AppId 例如:ks707065143182458884 |
access_token | string | 是 | 否 | 拥有小程序支付权限的access token,获取方式见getAccessToken |
以下字段放置到 body json中:
字段名 | 类型 | 是否必填 | 是否参与签名 | 说明 |
out_refund_no | string[6,32] | 是 | 是 | 开发者需要发起退款的支付订单号,商户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一 示例值:2217752501201407033233368018 |
sign | string | 是 | 否 | 开发者对核心字段签名, 签名方式见 附录 |
# 3.5. 请求示例
curl --location --request POST 'https://open.kuaishou.com/openapi/mp/developer/epay/contract/query_refund_info
?app_id=ks707065143182458884&access_token=ChFvYXV0aC5hY2Nlc3NUb2tlbhJQcXi6SorFfkg786OWTtGyvXf1Qz0wbN2pt4YlWHppV78IzJA92mwdcdRqegxMFRwBRTM6r5vVYzMFUlbqAfPpdYYKpRlywCtyzomu7d_mt44aEqr20o3-d0Tt4_ZJzk9p2G6vnyIg4o35UNBVgOdoJEObJmLLnr4IiN6SZO3G2saTmDnPtLEoDzAB' \
--header 'Content-Type: application/json' \
--data '{
"out_refund_no":"1703214721551",
"sign":"2c6be92c19f2f26185381b7dd6cc29a6"
}'
# 3.6 响应结果
返回值为 JSON 形式,其中包括如下字段:
字段名 | 类型 | 说明 |
result | number | 状态码 1-业务处理成功 |
error_msg | string | 错误提示信息,常见错误处理可参考附录常见问题章节 |
refund_info | json |
退款单信息 |
其中 refund_info 各字段含义如下
字段名 | 类型 | 说明 |
ks_refund_no | string | 快手小程序平台退款单号 |
contract_no | string | 快手小程序平台签约单号 |
ks_order_no | string | 快手小程序平台支付单号 |
refund_amount | number | 用户退款金额,单位为[分] |
pay_channel | string | 支付渠道,取值如下 WECHAT-微信|ALIPAY-支付宝 |
refund_status | string | 退款状态: REFUND_PROCESSING - 退款处理中 REFUND_FAILED - 退款失败 REFUND_SUCCESS - 退款成功 |
ks_refund_type | string | 退款账户说明,枚举值为: "结算前退款" "结算后退款" "保证金账户退款" |
apply_refund_reason | string | 申请退款原因 |
ks_refund_fail_reason | string | 退款失败原因 |
refund_apply_time | number | 申请退款时间,毫秒级时间戳 |
refund_complete_time | number | 退款完成时间,毫秒级时间戳 |
示例如下(仅供参考):
{
"result":1,
"error_msg":"错误信息提示",
"contract_no":"签约单号"
"refund_info":{
"ks_refund_no": "2214012312012302837250",
"contract_no": "524010201547195973250",
"ks_order_no": "124010400804337582250",
"refund_amount": 100,
"pay_channel": "WECHAT",
"refund_status": "REFUND_SUCCESS",
"ks_refund_type": "结算前退款",
"apply_refund_reason": "客户申请退款",
"ks_refund_fail_reason": "保证金余额不足",
"refund_apply_time": 1711936841430,
"refund_complete_time": 1711936841530
}
}
当 result 不为 1 时,说明请求错误,错误信息详见文章末尾 错误码 处。
# 4 代扣时间查询
# 4.1 接口说明
开发者可以用该接口,查询用户下次代扣发起的时间,请注意:
- 平台建议:开发者通过该接口获取下次代扣时间后,可以存储此数据,并在此次代扣周期内尽可能减少该接口调用次数,以减少无效调用。
- 平台仅支持查询签约成功的签约单下次代扣时间
- 开发者在签约单本次代扣周期内查询下次代扣时间,返回的仍为本次代扣周期的开始和结束时间
# 4.2 基本信息
名称 | 内容 |
HTTP URL | https://open.kuaishou.com/openapi/mp/developer/epay/contract/query_withhold_time |
HTTP Method | POST |
Scope | 需要具有小程序担保支付权限(scope.ks.epay) |
# 4.3 请求头
名称 | 字段类型 | 内容 |
Content-Type | String | 固定值: "application/json" |
# 4.4 请求参数
以下字段放在 query param 处:
字段名 | 类型 | 是否必填 | 是否参与签名 | 说明 |
app_id | string | 是 | 是 | 小程序AppId 例如:ks707065143182458884 |
access_token | string | 是 | 否 | 拥有小程序支付权限的access token,获取方式见getAccessToken |
以下字段放置到 body json中:
字段名 | 类型 | 是否必填 | 是否参与签名 | 说明 |
contract_no | string | 是 | 是 | 签约单号,签约回调里的 contract_no |
sign | string | 是 | 否 | 开发者对核心字段签名, 签名方式见 附录 |
# 4.5. 请求示例
curl --location --request POST 'https://open.kuaishou.com/openapi/mp/developer/epay/contract/query_withhold_time
?app_id=ks707065143182458884&access_token=ChFvYXV0aC5hY2Nlc3NUb2tlbhJQArRFRpcpLbj-HDpUWMRdDYPAFOO7tmAk8nQCPwzJ4hSFDAh0T1UDzzuFl-PpbeagQXJrGqgg7US3GJWl74FrstOZaJteWiZeccC7VBbLoUMaEiJK7-q_EK3iKvXdVXsh9vuWMiIgeKm-doDgbvfEDy3QS9D8mqh27IbzMmeWVpyKVpOwu9soDzAB' \
--header 'Content-Type: application/json' \
--data '{
"contract_no":"524010201776062339152",
"sign":"00c17abfee6837a7905000ee6c853c10"
}'
# 4.6 响应结果
返回值为 JSON 形式,其中包括如下字段:
字段名 | 类型 | 说明 |
result | number | 状态码 1-业务处理成功 |
error_msg | string | 错误提示信息,常见错误处理可参考附录常见问题章节 |
contract_info | json |
|
其中 contract_info 各字段含义如下
字段名 | 类型 | 说明 |
contract_no | string | 快手小程序平台签约号 |
contract_product | string | 签约产品名称 |
template_type | number | 签约模版类型 1:周 2:月 3:季度 4:年 5:固定30天 6:固定31天 |
next_withhold_start_time | number | 下次代扣开始时间,毫秒级时间戳, 注意: 1. 这个时间精确到日,且是闭区间 2. 只有签约单签约成功时,该字段返回值有意义 |
next_withhold_end_time | number | 下次代扣结束时间,毫秒级时间戳 。 注意: 1. 这个时间精确到日,且是开区间(比如: 返回的是2月15日,2月15日当天并不会扣款) 2.只有签约单签约成功时,该字段返回值有意义 |
示例如下(仅供参考):
{
"result":1,
"error_msg":"错误信息提示",
"contract_no":"签约单号"
"contract_info":{
"contract_no": "524010201547195973250",
"contract_product": "kuaishou_vip",
"template_type" : 1,
"next_withhold_start_time": 1711936841430,
"next_withhold_end_time": 1711936841530
}
}
当 result 不为 1 时,说明请求错误,错误信息详见文章末尾 错误码 处。
# 错误码
错误码 | 描述 | 排查建议 |
10000011 | token 过期 | 调用 getAccessToken 重新生成 token |
10000200 | 参数错误 | 对照错误提示和接口字段定义,检查对应的参数 |
10000302 | 请求频率太快,被限速。 | 请降低访问频率 |
10000500 | 系统故障 | 请联系相关开发人员进行排查 |
10000501 | 稍后重试 | 请等待1-2秒,再重试 |
10000606 | 接口参数签名错误 | 对照接口字段,检查签名字段是否正确 |
10000607 | 不合理的订单金额 | 请检查传入的订单金额是否合理 |
10000632 | 平台内部错误 | 请联系相关开发人员进行排查 |
10200502 | 查询条件无效 | 请对照错误提示和接口字段定义,检查对应参数 |
10000601 | 签约支付单不存在 | 请检查传递的外部订单号对应的订单是否存在 |
10001001 | 签约单不存在 | 请检查传递的订单号/签约单号对应的签约单是否存在 |
10001007 | 代扣订单不存在 | 请检查传递的退款单号对应的代扣单是否存在 |
# 附录
# 附录1、请求签名算法
所有由开发者发起到快手平台的接口请求,都需要使用开发者的 app_secret 签名,以保证请求来源和请求数据完整性。
具体的参数签名方式如下:
参加签名的字段:① URL中的请求参数;② POST 的 body 参数字段。以下两种字段不参与签名:
特定字段名:sign、access_token。
值为空的字段。
将第1步收集的字段(K)和对应的字段值(V),放到 Map<K, V> 中,并按照字段的 ASCII 码升序排列,按照下述方式连接,组装成参数字符串:
将开发者的 app_secret 拼接在参数字符串后面,使用MD5计算。
# 请求示例(如何获取签名字段)
请求信息:
curl --location --request POST 'https://open.kuaishou.com/openapi/mp/developer/epay/contract/query_order_info
app_id=ks707065143182458884&access_token=ChFvYXV0aC5hY2Nlc3NUb2tlbhJQcXi6SorFfkg786OWTtGyvXf1Qz0wbN2pt4YlWHppV78IzJA92mwdcdRqegxMFRwBRTM6r5vVYzMFUlbqAfPpdYYKpRlywCtyzomu7d_mt44aEqr20o3-d0Tt4_ZJzk9p2G6vnyIg4o35UNBVgOdoJEObJmLLnr4IiN6SZO3G2saTmDnPtLEoDzAB' \
--header 'Content-Type: application/json' \
--data '{
"out_order_no":"1711619867139contractDemo",
"sign":"360a9add284bb4e2050673132418a356"
}'
签名参数信息:
Map<String, Object> signParamMap = new HashMap();
signParamMap.put("app_id", "ks707065143182458884");
signParamMap.put("out_order_no", "1711619867139contractDemo");
待签名字符串
app_id=ks707065143182458884&out_order_no=1711619867139contractDemoyour_app_secret
# 签名示例代码
Java 示例代码
/**
* 小程序 app_secret
*/
private static final String APP_SECRET = "your_app_secret";
/**
* 获取参数 Map 的签名结果
*
* @param signParamsMap 含义见上述示例
* @return 返回签名结果
*/
public static String calcSign(Map<String, Object> signParamsMap) {
// 去掉 value 为空的
Map<String, Object> trimmedParamMap = signParamsMap.entrySet()
.stream()
.filter(item -> !Strings.isNullOrEmpty(item.getValue().toString()))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
// 按照字母排序
Map<String, Object> sortedParamMap = trimmedParamMap.entrySet()
.stream()
.sorted(Map.Entry.comparingByKey())
.collect(Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue,
(oldValue, newValue) -> oldValue, LinkedHashMap::new));
// 组装成待签名字符串。(注,引用了guava工具)
String paramStr = Joiner.on("&").withKeyValueSeparator("=").join(sortedParamMap.entrySet());
String signStr = paramStr + APP_SECRET;
// 生成签名返回。(注,引用了commons-codec工具)
return DigestUtils.md5Hex(signStr);
}