# 苹果IAP支付接入说明

更新时间:2024-09-26 19:12:43

# 一、 前置说明

# 1.1 关于接入

IAP全称是“In-App purchase”,是指苹果App Store的应用内购买,IAP是苹果为App内购买虚拟商品或服务提供的一套支付系统。IAP是在iOS客户端支付虚拟商品时必须要走的支付路径。

快手小程序接入iOS的IAP支付,相较于担保支付(单次) (opens new window)有两处变动改造点

  1. 使用/openapi/mp/developer/epay/iap/create_order预下单接口
  2. ks.pay接口增加苹果内购标识

具体信息在本文下面章节

注:IAP支付接入,仅因对iOS系统内,安卓系统无需关注,使用老的担保支付即可

# 1.2 关于退款

  • 苹果内购不支持线上退款,因此没有退款请求接口。若用户有退款请求,可使用以下方式
    • 商家可联系用户线下协商退款
    • 引导用户至苹果客服侧申请退款
  • 若退款方式为苹果客服侧退款,在苹果侧受理退款后,会将退款消息通知至快手小程序平台,平台通过退款回调(回调地址 refund_notify_url)告知开发者退款信息

# 1.3 关于订单同步

# 1.4 关于账单查询

与担保支付的账单查询接口保持一致:担保支付|账单查询能力 (opens new window)

支付方式为APPLE_PAY的订单,即为苹果支付的订单

IAP订单会在支付账单里面添加

  • 订单原价
  • 用户支付金额
  • 平台补贴金额
  • 支付渠道:APPLE_PAY

在退款账单新增:

  • 支付渠道:APPLE_PAY

# 1.5 版本说明

在iOS系统中,快手11.6.50版本开始封禁小程序支付能力,无法通过微信或者支付宝支付。

在12.0.20版本中支持苹果IAP支付,因此在接入IAP支付时,需要把测试机版本升级到12.0.20及以上

# 1.6 用户端支付loading展示

平台提供默认loading展示,无需小程序开发者开发相关功能。

# 二、IAP 支付 OPEN-API

# 2.1 预下单接口

  1. 支付回调地址会优先使用开发者传入的 notify_url,如果接口没有传入,会填充开发者在开发者平台设置的 支付回调,该支付回调地址设置与查看步骤如下【小程序开发者平台 -> 交易管理 -> 支付管理 -> 支付设置 (opens new window) -> 默认回调地址】
  2. 退款回调地址会优先使用开发者传入的 refund_notify_url,如果接口没有传入,会填充开发者在开发者平台设置的 退款回调,该退款回调地址设置与查看步骤同上

# 2.1.1 基本信息

名称内容
HTTP URLhttps://open.kuaishou.com/openapi/mp/developer/epay/iap/create_order
HTTP MethodPOST
Scope需要具有小程序担保支付权限(scope.ks.epay)

# 2.1.2 请求头

名称字段类型内容
Content-TypeString固定值: "application/json"

# 2.1.3 请求参数

以下字段放在 query param 处:

字段名类型是否必填是否参与签名参数位置说明
app_idstringquery param小程序AppId 例如:ks707065143182458884
access_tokenstringquery param拥有小程序支付权限的access token,获取方式见getAccessToken

以下字段放在 body json 处:

字段名类型是否必填是否参与签名参数位置说明
out_order_nostring[6,32]body json商户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一
示例值:1217752501201407033233368018
open_idstringbody json快手用户在当前小程序的open_id,可通过login操作获取。
subjectstring[1,128]body json商品名称或者商品描述简介,建议长度在10个汉字以内,在收银台页面、支付账单中供用户查看使用。注:不可传入特殊符号、emoji 表情等,否则会影响支付成功,1汉字=2字符。
detailstring[1,1024]body json商品详情。注:不可传入特殊符号、emoji 表情等,否则会影响支付成功,1汉字=2字符。
typenumberbody json商品类型,不同商品类目的编号见 担保支付商品类目编号
order_amountnumberbody json订单原价,单位为[分],不允许传非整数的数值。
user_pay_amountnumberbody json

用户实际金额,单位为[分]。
请仔细阅读以下信息:

1. 如果订单没有补贴,则user_pay_amount=order_amount

2. 如果订单有补贴,那么user_pay_amount 是原价基础上补贴后的价格。该金额需要匹配上苹果内购的价格档位。苹果价格档位信息,第一列为价格档位信息,第二列为苹果服务费,第三列为苹果扣除苹果税后实际结算的金额。

如果有补贴,并且补贴价格为subsidyAmount,user_pay_amount-subsidyAmount为实际折扣后价格,如果user_pay_amount-subsidyAmount

恰好等于苹果某档位,那么user_pay_amount传user_pay_amount-subsidyAmount

如果 档位A < user_pay_amount-subsidyAmount < 档位B,那么user_pay_amount传档位A或者档位B的任意值均可,由开发者自行选择。

举例:
订单原价为3元,补贴1元,折扣后价格为2元,2元正好是苹果内购档位,那么user_pay_amount传2;
订单原价为3元,补贴1.1元,折扣后价格为1.9元,1.9元最近的上档位为1.8元,下档位为2元,那么user_pay_amount传1.8元或者2元均可

goods_idstring[1, 256]否(本地生活类必填)body json下单商品id,需与商品对接时的product_id一致,长度限制256个英文字符,1个汉字=2个英文字符;短剧类,如果要用补贴,必传
goods_detail_urlstring[1, 500]否(本地生活类必填)body json

订单详情页跳转path。长度限制500个英文字符,1个汉字=2个英文字符;

示例值:/page/index/anima

expire_timenumberbody json订单过期时间,单位秒,300s - 3600s
attachstring[0,128]body json

开发者自定义字段,回调原样回传.

注:1汉字=2字符;勿回传敏感信息

notify_urlstring[1, 256]body json

支付回调

通知URL必须为直接可访问的URL,不允许携带查询串。

refund_notify_urlstring[1, 256]body json

退款回调

用户在苹果appStore发起退款后,小程序平台通知给开发者。

通知URL必须为直接可访问的URL,不允许携带查询串。

activity_infostring[1:128]body json

 

[
  {
    "bid_id": 1241,  // 请求报价信息中返回的报价id
    "activity_type": "NEW_USER_DISCOUNT" // 活动类型
    }
]

 

订单有参与平台补贴活动,则传入活动信息,否则不用传。

signstringbody json开发者对核心字段签名, 签名方式见 附录

# 2.1.4 请求示例

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
}'

说明:iap支付预下单,和担保支付(单次)下单入参的区别是:

  • 需要传入一个user_pay_amount字段,在无补贴情况下,user_pay_amount=order_amount
  • user_pay_amount一定要是苹果支持的档位,否则无法支付成功
  • refund_notify_url,在预下单时,需要传入退款回调url,用于用户退款时,回调通知给开发者

# 2.1.5 响应结果

返回值为 JSON 形式,其中包括如下字段:

字段名类型说明
resultnumber状态码 1-业务处理成功  非1-请求错误,具体见错误码
error_msgstring错误提示信息,常见错误处理可参考附录常见问题章节
order_infojson string拉起收银台的 orderInfo

示例如下(仅供参考):

{
    "result":1,
    "error_msg":"错误信息提示",
    "order_info":{
        "order_no": "121072611585202788127",// 平台提供的订单号
        "order_info_token": "ChJrc01wUGF5Lm9yZGVyVG9rZW4SULxOUORbNX1NAzmbs3vCE8Fo8FN8EW90EM7iReQujs85RbgDNVDPqxJoGly_jX7Zv9kwTiXsrFuSgwrR-ufuZexCYejepc-C0swHGhJtqssdzyq4aMsYYWjhyloiIOZOjlvg2cPW6VJsOmt6c4Tz2qSsZoAhTeKIZAXM13SRKAUwAQ"
    }
}

# 2.1.6 错误码

当 result 不为 1 时,说明请求错误,全量错误码见附录 (opens new window)

苹果支付预下单相关错误码如下

错误码错误提示解决建议
10000502未申请开启苹果支付能力,请先在开发者后台开通需要在快手小程序开发者后台,交易管理-支付管理-账户开通tab下,开通苹果支付权限。
10000200用户实际支付金额必须大于0,且小于订单金额user_pay_amount参数需要大于0,且小于等于order_amount。
未补贴订单,用户实际支付金额需等于订单原价未参与补贴订单,user_pay_amount需要和order_amount相等
IAP支付下单请求参数必须有refundNotifyUrl且长度不超过356请检查refund_notify_url参数是否传入,且长度是否合法
10000623订单用户支付金额不合法订单信息中用户支付金额user_pay_amount小于0,请联系快手小程序客服支持排查

# 2.2 支付回调

用户支付成功后,和普通担保支付一样,有支付回调,回调信息如下:

{
    "data": {
        "ks_order_no": "124070401619134310455",
        "channel": "APPLE_PAY",
        "developer_promotion_amount": 0,
        "apple_channel_fee": 47,
        "order_amount": 150,
        "subsidy_amount": 0,
        "attach": "iap支付demoiap支付demoiap支付demo",
        "app_id": "ks707065143182458884",
        "out_order_no": "1720077455378iapDemo",
        "sku_id": "",
        "promotion_amount": 0,
        "pay_time": 1720077472000,
        "extra_info": "{\"url\":\"\",\"provider\":\"\",\"item_type\":\"UNKNOWN\",\"item_id\":\"\",\"author_id\":\"\",\"refer_id\":\"\",\"channel_mark\":\"\",\"provider_type\":\"\",\"trade_no\":\"2000000646912252\",\"subsidy\":0,\"upa\":150,\"rnu\":\"https://qa-mp.corp.kuaishou.com/zeus/epay/notify\",\"acf\":47,\"withhold_time\":0,\"withhold_period\":0,\"withhold_template_id\":0,\"from_standard_trade_payment\":false}",
        "enable_promotion": false,
        "trade_no": "2000000646912252",
        "status": "SUCCESS",
        "user_pay_amount": 150
    },
    "biz_type": "PAYMENT",
    "message_id": "63ccf549-0906-408c-9111-e66d86479843",
    "app_id": "ks707065143182458884",
    "timestamp": 1720077476139
}

其中重点关注的几个字段如下:

字段类型说明
ks_order_nostring小程序小程序平台订单号
channelstring苹果支付回调固定值为「APPLE_PAY」
apple_channel_feenumber当前订单,苹果收取的苹果通道费
user_pay_amountnumber用户实际支付金额
order_amountnumber

订单原始金额。在用户未参与补贴活动情况下,order_amount=user_pay_amount

(目前小程序平台已下线补贴活动)

statusstring订单支付状态;取值:PROCESSING-处理中|SUCCESS-成功|FAILED-失败
attachstring预下单时携带的开发者自定义信息
enable_promotionboolean是否参与分销,true:分销;false:非分销
developer_promotion_amountnumber预计服务商分销金额,单位:分
promotion_amountnumber预计达人分销金额,单位:分

# 2.3 结算接口

IAP支付订单与普通订单的结算能力相同,具体结算接口详见 担保支付|结算能力 (opens new window)

# 2.4 退款回调

退款流程参考1.2,用户在苹果AppStore申请退款,苹果审核通过同意退款后,回调给快手小程序平台,快手小程序平台回调退款信息给开发者。退款回调参考示例如下:

{
    "data": {
        "ks_order_no": "124061402132935925493",
        "channel": "APPLE_PAY",
        "developer_promotion_amount": 0,
        "apple_channel_fee": 0,
        "order_amount": 100,
        "subsidy_amount": 0,
        "refund_amount": 100,
        "attach": "",
        "app_id": "ks707065143182458884",
        "refund_type": "结算前退款",
        "out_refund_no": "2000000627980015",
        "out_order_no": "1718336680647iapDemo",
        "ks_refund_fail_reason": "用户通过苹果客服申请订单退款",
        "apply_refund_reason": "用户通过苹果客服申请订单退款",
        "promotion_amount": 0,
        "pay_time": 0,
        "enable_promotion": false,
        "ks_refund_no": "224061401403754055493",
        "status": "SUCCESS",
        "user_pay_amount": 100
    },
    "biz_type": "REFUND",
    "message_id": "3641e55b-dd63-4344-9276-527f0c3d54e5",
    "app_id": "ks707065143182458884",
    "timestamp": 1718337814608
}

重点关注如下字段

字段类型说明
ks_order_nostring快手小程序订单号
channelstring苹果支付回调固定值为「APPLE_PAY」
order_amountnumber订单支付金额
refund_amountnumber订单退款金额(对于苹果支付,只会一次性退全部订单金额)
refund_typestring退款来源说明,取值为"结算前退款","结算后退款","保证金账户退款"
ks_refund_nostring快手小程序退款单号
statusstring退款状态,取值为PROCESSING-处理中|SUCCESS-成功|FAILED-失败

# 三、 JS接口

使用API: ks.pay (opens new window)

新增字段payType,仅作用于IAP支付,其他支付方式不传

属性名类型是否必填说明
payTypeStringIAPPurchase苹果内购

tips:在js文件中使用ks.pay时,请勿在同页面内使用无UI支付组件(<payment-list>)

示例:

Page({
    data: {
        payment: {
            provider: '',
            provider_channel_type: '',
        },
    },
    async pay() {
        const paymentChannel = this.data.payment;
        // 执行预下单逻辑
        await this.doPreOrder(payment);
      // 前置判断
      
      // 当前所属平台是否为ios(iphone和ipad的platform均为ios)
      const platform = ks.getSystemInfoSync().platform;
      // 是否支持payType的值为IAPPurchase
      const isSupportApplePay = ks.canIUse('pay.object.payType.IAPPurchase');
      if(platform === 'ios' && isSupportApplePay){
        // 执行支付
        ks.pay({
            serviceId,
            orderInfo,
            paymentChannel,
            payType: 'IAPPurchase'
            success,
            fail,
        })
      } else {
          ks.pay({
            serviceId,
            orderInfo,
            paymentChannel,
            success,
            fail,
        })
      }
    }
})
Copyright ©2024, All Rights Reserved