# 附录

更新时间:2025-06-09 16:41:11

# 附录1、请求签名算法

所有由开发者发起到快手平台的接口请求,都需要使用开发者的 app_secret (opens new window) 签名,以保证请求来源和请求数据完整性。

# 如何计算请求具体的参数签名?

请求中参与签名的字段有两类:

  1. URL中的请求参数;
  2. POST 的 body 参数字段。

注:以下两种字段不参与签名:

  • 特定字段名:sign、access_token。
  • 值为空的字段

将上述收集的字段(K)和对应的字段值(V),放到 Map<K, V> 中,并按照字段的 ASCII 码升序排列,按照下述方式连接,组装成参数字符串:

注:最后需要将开发者的 app_secret 拼接在参数字符串后面,使用MD5计算。

app_secret获取路径如下

# 请求示例

# 担保支付预下单

请求信息:

curl --location --request POST 'https://open.kuaishou.com/openapi/mp/developer/epay/create_order?app_id=ks707065143182423884&access_token=ChFvYXV0aC5hY2Nlc3NUb2tlbhIw0FKGX_0HpB-TDCypkcRcw3o_KHSda-Vy5hK89LPgfTa_XBClfLUgotP1YGpX0lD9hTzMiIHyaI8naVBqJZm6kCdtxZB7IBIpdenq8m9SqxQ1Py7U0KAUwAQ' 
--header 'Content-Type: application/json' 
--data-raw '{
    "open_id":"5b748c61ef2901405450656638e8f702d3",
    "out_order_no":"kdj1231113454676",
    "total_amount":100,
    "subject":"肯德基10元代金券",
    "type":1,
    "detail":"详情介绍",
    "expire_time":3600,
    "notify_url":"https://xxxx.kuaishou.com/zeus/epay/notify",
    "sign":"dfb2a4b482d4f9a0cb4a60ad7fbe839e"
}'

签名参数信息:

Map<String, Object> signParamMap = new HashMap();
signParamMap.put("app_id", "ks707065143182423884");
signParamMap.put("open_id", "5b748c61ef2901405450656638e8f702d3");
signParamMap.put("out_order_no", "kdj1231113454676");
signParamMap.put("total_amount", 100);
signParamMap.put("subject", "肯德基10元代金券");
signParamMap.put("type", 1);
signParamMap.put("detail", "详情介绍");
signParamMap.put("expire_time", 3600);
signParamMap.put("notify_url", "https://xxxx.kuaishou.com/zeus/epay/notify");

待签名字符串:

app_id=ks707065143182423884&detail=详情介绍&expire_time=3600¬ify_url=https://xxxx.kuaishou.com/zeus/epay/notify&open_id=5b748c61ef2901405450656638e8f702d3&out_order_no=kdj1231113454676&subject=肯德基10元代金券&total_amount=100&type=1your_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 -> StringUtils.isNotBlank(item.getKey()) && ObjectUtils.isNotEmpty(item.getValue()))
            .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);
    }

# 支付并签约预下单

请求信息

curl --location --request POST 'https://open.kuaishou.com/openapi/mp/developer/epay/create_contract_order?app_id=ks707065143182458884&access_token=ChFvYXV0aC5hY2Nlc3NUb2tlbhJQj7WUW3mucBZlklkzQT1nZ3g-u0129JVjCDj-H68v__XCG_u1tKpvETKfwCSVxJotPH_omhiHHbax-XAlebkX1f293Un9KHxWB2k3lBICFocaEngsUCp0IQD00y-GC9Pzapqg_iIgb0ga72EMrnCLrIbzwOewukr0fySa1lMFsjOJhI8VXTgoDzAB' \
--header 'Content-Type: application/json' \
--data '{
    "open_id": "5b748c61ef290140c0656638eaa0d69c",
    "out_order_no": "1703147868993contractDemo3",
    "total_amount": "1",
    "subject": "自动续费VIP",
    "type": "89999",
    "detail": "签约",
    "expire_time": "300",
    "attach": "",
    "pay_notify_url": "https://www.abidu.com/zeus/epay/notify",
    "contract_notify_url": "https://www.abidu.com/contract_notify",
    "withhold_notify_url": "https://www.abidu.com/withhold_notify",
    "goods_detail_url": "1222",
    "contract_info": {
        "withhold_amount": 1,
        "template_type": 2,
        "withhold_product": "ks_vip_card",
        "first_withhold_time":1704274954000
    },
    "provider": {
        "provider_channel_type": "NORMAL",
        "provider": "ALIPAY"
    },
    "sign": "5a5546dd7b1fbb13ded3b86a901647f9"
}'

签名参数信息

Map<String, Object> signParamMap = new HashMap();
signParamMap.put("app_id", "ks707065143182423884");
signParamMap.put("open_id", "5b748c61ef290140c0656638eaa0d69c");
signParamMap.put("out_order_no", "1703147868993contractDemo3");
signParamMap.put("total_amount", 1);
signParamMap.put("subject", "自动续费VIP");
signParamMap.put("type", 89999);
signParamMap.put("detail", "签约");
signParamMap.put("expire_time", 300);
signParamMap.put("attach", "");
signParamMap.put("pay_notify_url", "https://xxxx.kuaishou.com/zeus/epay/notify");
signParamMap.put("contract_notify_url", "https://www.abidu.com/contract_notify");
signParamMap.put("withhold_notify_url", "https://www.abidu.com/withhold_notify");
signParamMap.put("goods_detail_url", "1222");
signParamMap.put("contract_info", "{\"template_type\":2,\"withhold_amount\":1,\"withhold_product\":\"ks_vip_card\",\"first_withhold_time\":1704274954000}");
signParamMap.put("provider", "{\"provider\": \"ALIPAY\",\"provider_channel_type\":\"NORMAL\"}");

待签名字符串,生成签名代码和上述一样

其中有如下注意点:

  1. contract_info中的json字符串,需要按照template_type/withhold_amount/withhold_product/first_withhold_time的顺序排列
  2. provider中的json字符串,需要按照provider/provider_channel_type的顺序排列
app_id=ks707065143182423884&contract_info={"template_type":2,"withhold_amount":1,"withhold_product":"ks_vip_card","first_withhold_time":1704274954000}&contract_notify_url=https://www.abidu.com/contract_notify&detail=签约&expire_time=300&goods_detail_url=1222&open_id=5b748c61ef290140c0656638eaa0d69c&out_order_no=1703147868993contractDemo3&pay_notify_url=https://xxxx.kuaishou.com/zeus/epay/notify&provider={"provider": "ALIPAY","provider_channel_type":"NORMAL"}&subject=自动续费VIP&total_amount=1&type=89999&withhold_notify_url=https://www.abidu.com/withhold_notifyyour_app_secret

# 苹果支付预下单

请求信息

curl --location --request POST 'https://open.kuaishou.com/openapi/mp/developer/epay/iap/create_order?app_id=ks707065143182458884&access_token=ChFvYXV0aC5hY2Nlc3NUb2tlbhJQcpTii72q9RcEb4iBAo2sQ-MNDRv4ksDSV9sA-u6yX_8BdNJRWHQxFXjdzlVph-8MGCWrzxQylHXsI6zKUKANl7tzt3O10ZK-O4UmLXmyQqcaEqr20o3-d0Tt4_ZJzk9p2G6vnyIg-5C3geR6MIqH53T7CrvtiC9nkZvAR4VU0J8kynIpi-koDzAB' \
--header 'Content-Type: application/json' \
--data-raw '{
    "open_id":"5b748c61ef290140c0656638eaa0d69c",
    "out_order_no":"testiap00006",
    "subject":"测试描述测试iap",
    "detail":"测试描述测试iap详情",
    "type":"74",
    "order_amount":100,
    "user_pay_amount":100,
    "goods_id":"1",
    "goods_detail_url":"/page/index/index",
    "expire_time":"300",
    "attach":"iap支付demoiap支付demoiap支付demo",
    "notify_url":"https://qa-mp.test.kuaishou.com/zeus/epay/notify",
    "refund_notify_url": "https://qa-mp.test.kuaishou.com/zeus/epay/notify",
    "sign":12333
}'

签名参数信息

Map<String, Object> signParamMap = new HashMap();
signParamMap.put("app_id", "ks707065143182423884");
signParamMap.put("open_id", "5b748c61ef290140c0656638eaa0d69c");
signParamMap.put("out_order_no", "testiap00006");
signParamMap.put("order_amount", 100);
signParamMap.put("user_pay_amount", 100);
signParamMap.put("subject", "测试描述测试iap");
signParamMap.put("type", 74);
signParamMap.put("goods_id", "1");
signParamMap.put("detail", "测试描述测试iap详情");
signParamMap.put("expire_time", 300);
signParamMap.put("attach", "iap支付demoiap支付demoiap支付demo");
signParamMap.put("goods_detail_url", "/page/index/index");
signParamMap.put("notify_url", "https://qa-mp.test.kuaishou.com/zeus/epay/notify");
signParamMap.put("refund_notify_url", "https://qa-mp.test.kuaishou.com/zeus/epay/notify");

待签名字符串如下,生成签名代码和上述一样

app_id=ks707065143182423884&attach=iap支付demoiap支付demoiap支付demo&detail=测试描述测试iap详情&expire_time=300&goods_detail_url=/page/index/index&goods_id=1&notify_url=https://qa-mp.test.kuaishou.com/zeus/epay/notify&open_id=5b748c61ef290140c0656638eaa0d69c&order_amount=100&out_order_no=testiap00006&refund_notify_url=https://qa-mp.test.kuaishou.com/zeus/epay/notify&subject=测试描述测试iap&type=74&user_pay_amount=100your_app_secret

# 附录2、回调方式和策略

在支付、退款、结算流程中,如果流程结束,小程序平台通过POST方式回调开发者提供的URL地址,以通知开发者流程状态和信息。请求内容使用app_secret 签名,需要开发者对接收到的请求内容验签。

# 请求的内容

header

参数描述示例
kwaisign对本次请求的签名e10adc3949ba59abbe56e057f20f883e

body

{
    "data": {
        "xxxx1": "0007",
        "xxxx2": 1234,
        "xxxx3": "this is some attach",
    },
    "message_id": "61901a3a-2b1f-40b6-af14-de34660d7541",
    "biz_type": "REFUND",
    "app_id": "ks656399649443988986",
    "timestamp": 1625728322061
}

具体的字段说明

字段名类型说明
datajson string业务状态和信息,具体内容参考具体流程的回调接口说明。
message_idstring当前回调消息的唯一ID,在同一个消息多次通知时,保持一致。
biz_typestring业务类型。取值如下:
PAYMENT - 支付
REFUND - 退款
SETTLE - 结算
WITHHOLD - 代扣
CONTRACT - 签解约
app_idstring当前小程序的AppID
timestampnumber流程变动的时间戳

签名方式

取出http body中的原始字符串拼接app_secret,然后使用MD5进行签名:MD5(${http_body_string} + ${app_secret})  

签名示例  

请求如下:

curl --location --request POST
'https://yourdomain.com/kuaishou/pay/event_push' \
--header 'kwaisign: e10adc3949ba59abbe56e057f20f883e' \
--header 'Content-Type: application/json' \
--data-raw '{"data":{"out_refund_no":null,"settle_amount":null,"channel":"WECHAT","out_order_no":"2021091314414946589","out_settle_no":null,"refund_amount":null,"attach":"自定义消息","status":"SUCCESS"},"biz_type":"PAYMENT","message_id":"76a50e0c-a843-492b-9bc6-463c1b178a9c","app_id":"ks696650570360602063","timestamp":1631515320564}'

签名验证:

appSecret = "Xgm23lSgws235hlgK"; // 小程序密钥

toSignStr = ${http_body} + ${appSecret} // 待签名字符串
即:toSignStr = {"data":{"out_refund_no":null,"settle_amount":null,"channel":"WECHAT","out_order_no":"2021091314414946589","out_settle_no":null,"refund_amount":null,"attach":"自定义消息","status":"SUCCESS"},"biz_type":"PAYMENT","message_id":"76a50e0c-a843-492b-9bc6-463c1b178a9c","app_id":"ks696650570360602063","timestamp":1631515320564}Xgm23lSgws235hlgK

sign = MD5(toSignStr) // 签名结果

boolean result = sign.equals(kwaisign); // 验证是否相同

# 开发者返回

开发者在接收到回调消息,并正确处理后,需要返回以下内容格式,以通知小程序平台不再持续回调:  

{
  "result" : 1,   //必填。 1-成功,其他-失败。失败小程序平台会尝试重推此消息
  "message_id" : "ChFvYXV0aC5hY2Nlc3NUb2tlbhJQvpR51x8In46B1sDB" //当前消息的message_id
}

如果开发者没有返回或者返回的result不等于1,则小程序平台会尝试重复推送此消息,开发者务必做好消息的幂等处理!

# 回调重试策略

对于未收到成功返回的通知,消息最大重试次数为 16 次,重试次数和初次发送回调消息时间的延迟关系如下:

重试次数距初次发送回调消息的延迟时间
110s
230s
31m
42m
53m
64m
75m
86m
97m
108m
119m
1210m
1311m
1412m
151h
162h

# 附录3、手续费及分佣金额计算规则

一笔订单在分账给商户之前,可能产生如下费用

费率类型是否必须收费条件
苹果通道费仅在苹果支付渠道下又苹果方收取,具体收费标准见:苹果价格档位信息 | 快手小程序文档
平台服务费快手平台收取,一般为2%,部分小程序可能有特殊配置
达人分销费订单又达人带货产生
服务商分销费小程序借助第三方服务商开发运营上线,收取服务商分销费

计算规则如下:

平台服务费 = floor((订单总金额-订单结算前已退款金额 - 苹果服务费)*平台服务费费率)

苹果通道费:在30%左右,固定数额,具体见:苹果价格档位信息 | 快手小程序文档 (opens new window)

达人分销费=floor((订单总金额-已退款金额 - 苹果服务费)*达人分销费率)

服务商分销费=floor((订单总金额-已退款金额 - 苹果服务费)*服务商分销费率)

即: 在计算服务费(单位:分)时,乘费率后的金额向下取整,即为该笔交易的手续费。

# 附录4、错误码和常见问题

# 错误码

错误码含义排查建议
10000011token 过期/
10000200参数有误,需要检查参数是否为空或者格式错误。/
10000302请求频率太快,被限速。/
10000303命中反垃圾策略/
10000500系统故障/
10000501稍后重试/
10000601订单不存在/
10000602订单信息不一致/
10000603订单过期/
10000604订单状态不正确/
10000605回调地址异常/
10000606接口参数签名错误/
10000607不合理的订单金额/
10000608不支持的service_id/
10000609非法的orderInfo/
10000610重复下单/
10000611查询订单信息失败/
10000612费用信息错误/
10000621支付中台验签失败/
10000623校验订单金额失败/
10000624支付订单回调失败/
10000625退款回调消息解析失败/
10000626结算回调消息解析失败/
10000627退款调用异常/
10000628结算调用异常/
10000631配置错误/
10000632内部错误/
10000633支付中心异常/
10000634发送webhook失败/
10000641帐户id已绑定到别的小程序/
10000642帐户已绑定进件人,无法重复绑定/
10000643帐户尚未绑定进件人/
10000644回调域名设置有误/
10000645商家提现次数限制/
10200501OAuth验签失败/
10200502查询条件无效/
10000681类目被封禁/
10000682当前未到可结算时间,请在支付成功7日后发起结算/
10000683订单未支付,无可结算金额/
10000684该单已处理完成/
10000685当前订单未到可结算时间,请在核销后3天发起结算。如满足结算条件请查看商户是否被处罚。/
10000686当前有正在结算中的订单/
10000687当前有正在退款中的订单/
10000689保证金账户余额不足/
10000690保证金账户不存在/
10000726未传入商品id传入商品id
10000727无商品信息,暂不支持购买传入非指定商品id,请参考good_id传入规范
10000728商品暂不支持购买课程已下架,暂不支持购买;下架原因,请参考知识付费接入文档中4.5节
Copyright ©2025, All Rights Reserved