循环扣款交易
本文档将介绍固定金额循环扣款交易的创建、查询与取消。
信息
如果循环扣款交易中的某一笔计划扣款失败(包括 startDate 当天的首次扣款),该循环扣款将被中止: 订单会被标记为失败(status = 9),系统会发送 failed 通知,并且不会再进行后续扣款。 被中止的循环扣款不会被取消,仍可通过查询接口返回,last_payment 为对应的失败订单。 如需停止循环扣款交易,请使用取消接口;如需继续向客户收款,请创建新的循环扣款。
创建循环扣款
端点
https://ccapi.iotpaycloud.com/v3/recurring/create
方法
POST
头部
Content-Type: application/json;charset=UTF-8
重要
如果请求中未包含 startDate:将把当前日期配置为该订阅的 startDate,并立即进行一次扣款,后续扣款将按循环频率进行。 如果首次扣款失败,不会创建循环扣款交易,retCode 为 FAIL,retData 中包含失败的订单(status = 9)。
如果请求中包含 startDate:创建时不会进行扣款。首次扣款将在 startDate(UTC)当天进行, retData 中包含待处理订单(status = 0),不包含支付详情。
请求
| 名称 | 必需 | 类型 | 示例 | 描述 |
|---|---|---|---|---|
| mchId | y | String | 10000701 | 由 IOTPay 分配 |
| mchOrderNo | y | String(50) | 1234567890abc | 由商户分配,每个商户下必须唯一 |
| cardId | y | String(50) | 添加卡端点所使用的 cardId(direct、redirect)。 | |
| frequency | y | String | [w,2w,4w,m] | 当前可选配置为 w(每周)、2w(每两周)、4w(每 4 周,28 天)或 m(每月,每月固定某一日) |
| startDate | n | Int | 1798761600 | 首次循环扣款的 UNIX 时间戳(秒);例如 1798761600 => Fri Jan 01 2027 00:00:00 GMT+0000。必须是当前 UTC 日期之后,且在 10 年以内的日期。如果未提供 startDate,将立即进行首次扣款 |
| amount | y | Int | 1500 | 以分为单位,必须 > 0 |
| currency | y | String(3) | CAD | 固定为:CAD |
| loginName | y | String(12) | jack123 | 商户登录名 |
| notifyUrl | y | String(200) | http://sample.com/notify | 商户用于接收循环扣款通知的端点,必须为 http 或 https |
| description | n | String(200) | Test recurring order. | 循环扣款交易的可选描述 |
| sign | y | String(32) | 签名算法 |
响应
| 名称 | 必需 | 类型 | 示例 | 描述 |
|---|---|---|---|---|
| retCode | y | String | SUCCESS 或 FAIL | |
| retMsg | y | String | 失败原因在此显示 | |
| retData | y | JSON | 如果 retCode=SUCCESS,则返回订单详细信息 |
retData 包含订单信息:
| 名称 | 必需 | 类型 | 示例 | 描述 |
|---|---|---|---|---|
| payOrderId | y | String | 该循环扣款交易首笔订单的支付订单 Id | |
| mchId | y | String | 您的商户 Id | |
| mchOrderNo | y | String | 应与请求的 mchOrderNo 一致 | |
| currency | y | String | CAD | |
| amount | y | Int | 100 | 以分为单位,与请求 amount 一致 |
| payType | y | String | pay | 固定为 pay |
| refundable | y | Int | 100 | 以分为单位,与 amount 一致 |
| status | y | Int | 0,2,3 | 0 = 待处理订单(已提供 startDate,首次扣款尚未进行),2 或 3 = 成功 |
| invoiceNum | n | String | 如果提供了 startDate,则不返回 | |
| paySuccTime | n | String | 2021-04-07 19:44:51 | 支付成功的时间戳。如果提供了 startDate,则不返回 |
| authNum | n | String | 如果提供了 startDate,则不返回 | |
| transNum | n | String | 如果提供了 startDate,则不返回 | |
| channel | y | String | PF_CC | 固定为 PF_CC |
| recurringId | y | Int | 123 | 新创建的循环扣款 Id,用于查询和取消接口 |
| cardId | y | String(50) | 应与请求的 cardId 一致 | |
| notifyUrl | y | String(200) | http://sample.com/notify | 提供的 notifyUrl,应与请求的 notifyUrl 一致 |
| frequency | y | String | [w,2w,4w,m] | 应与请求的 frequency 一致 |
| startDate | y | String | 2027-01-01 | 首次扣款日期(UTC 时间,YYYY-MM-DD) |
| nextPayment | y | String | 2027-01-08 | 下次计划扣款日期(UTC 时间,YYYY-MM-DD);如果提供了 startDate,则与 startDate 相同 |
| description | n | String(200) | Test recurring order. | 循环扣款交易的可选描述,应与请求的 description 一致 |
按 Id 查询循环扣款
返回与所提供 recurringId 匹配的循环扣款信息,以及该循环扣款已发生的订单(分页列表)
端点
https://ccapi.iotpaycloud.com/v3/recurring/query
方法
POST
头部
Content-Type: application/json;charset=UTF-8
请求
| 名称 | 必需 | 类型 | 示例 | 描述 |
|---|---|---|---|---|
| mchId | y | String | 10000701 | 由 IOTPay 分配 |
| loginName | y | String(12) | jack123 | 商户登录名 |
| recurringId | y | Int | 123 | 创建循环扣款接口 返回的 recurringId。 |
| page | n | Int | 1 | 要返回的 orders 的页码,默认为 1 |
| pageSize | n | Int | 20 | 每页订单数量,默认为 20,最大为 100 |
| sign | y | String(32) | 签名算法 |
响应
| 名称 | 必需 | 类型 | 示例 | 描述 |
|---|---|---|---|---|
| retCode | y | String | SUCCESS 或 FAIL | |
| retMsg | y | String | ||
| retData | y | JSON | 如果 retCode 为 SUCCESS,返回循环扣款详细信息 |
retData 包含以下循环扣款信息:
| 名称 | 必需 | 类型 | 示例 | 描述 |
|---|---|---|---|---|
| id | y | Int | 123 | 循环扣款 Id |
| amount | y | Int | 100 | 以分为单位 |
| mid | y | String | 商户 id | |
| currency | y | String | CAD | 固定为 CAD |
| start_date | y | String | 2027-01-01 | 扣款开始日期(UTC 时间,YYYY-MM-DD) |
| frequency | y | String | [w,2w,4w,m] | 当前可选配置为 w(每周)、2w(每两周)、4w(每 4 周,28 天)或 m(每月,每月固定某一日) |
| description | n | String(200) | Test recurring order. | 循环扣款交易的可选描述 |
| last_paid | y | String | 2027-01-01 | 上次成功扣款日期(UTC 时间,YYYY-MM-DD),若尚未成功扣款则默认为 "1970-01-01" |
| last_payment | y | String | 上次扣款(成功或失败)的 payorderid,若尚未发生扣款则为待处理首笔订单的 payorderid | |
| next_payment | y | String | 2027-01-08 | 下次计划扣款日期(UTC 时间,YYYY-MM-DD)。如果上次扣款失败,则保持为该次扣款的日期,且不再进行后续扣款 |
| cardId | y | String(50) | 与该循环扣款关联的 cardId | |
| orders | y | JSON | 该循环扣款已发生订单的分页列表,最新的在前 |
orders 包含以下分页信息:
| 名称 | 必需 | 类型 | 示例 | 描述 |
|---|---|---|---|---|
| page | y | Int | 1 | 当前页码 |
| pageSize | y | Int | 20 | 每页订单数量 |
| total | y | Int | 45 | 该循环扣款的订单总数 |
| lastPage | y | Int | 3 | 最后一页的页码 |
| list | y | List | 当前页的订单;如果 page 超出 lastPage 则为空 |
orders.list 中每个 JSON object 包含以下订单信息:
| 名称 | 必需 | 类型 | 示例 | 描述 |
|---|---|---|---|---|
| payOrderId | y | String | 由 IOTPay 分配的订单号 | |
| mchId | y | String | 您的商户 Id | |
| mchOrderNo | y | String | 首笔订单为请求的 mchOrderNo,其后订单与 payOrderId 相同 | |
| originalOrderId | y | String | 该循环扣款上一笔订单的支付订单 Id,首笔订单为空 | |
| currency | y | String | CAD | |
| amount | y | Int | 100 | 以分为单位 |
| payType | y | String | pay | 固定为 pay |
| refundable | y | Int | 100 | 以分为单位 |
| status | y | Int | 0,1,2,3,9 | 0 = 待处理订单,1 = 未知,2 或 3 = 成功,9 = 失败 |
| invoiceNum | y | String | ||
| paySuccTime | y | String | 2021-04-07 19:44:51 | 支付成功的时间戳,如果订单尚未扣款则为空 |
| authNum | y | String | ||
| transNum | y | String | ||
| channel | y | String | PF_CC | 固定为 PF_CC |
| recurringId | y | Int | 123 | 应与请求的 recurringId 一致 |
| capture | n | String | Y | 固定为 Y |
| notifyUrl | y | String(200) | http://sample.com/notify | 创建该循环扣款时提供的 notifyUrl |
按 CardId 查询循环扣款
列出使用所提供 cardId 的客户的全部循环扣款
端点
https://ccapi.iotpaycloud.com/v3/recurring/query_by_card
方法
POST
头部
Content-Type: application/json;charset=UTF-8
请求
| 名称 | 必需 | 类型 | 示例 | 描述 |
|---|---|---|---|---|
| mchId | y | String | 10000701 | 由 IOTPay 分配 |
| loginName | y | String(12) | jack123 | 商户登录名 |
| cardId | y | String(50) | 添加卡端点所使用的 cardId(direct、redirect)。 | |
| sign | y | String(32) | 签名算法 |
响应
| 名称 | 必需 | 类型 | 示例 | 描述 |
|---|---|---|---|---|
| retCode | y | String | SUCCESS 或 FAIL | |
| retMsg | y | String | ||
| retData | y | List | 如果 retCode 为 SUCCESS,返回使用该 cardId 作为支付方式的循环扣款列表(若无则返回空列表) |
retData 中的每个 JSON object 包含以下循环扣款信息:
| 名称 | 必需 | 类型 | 示例 | 描述 |
|---|---|---|---|---|
| id | y | Int | 123 | 循环扣款 Id |
| amount | y | Int | 100 | 以分为单位 |
| mid | y | String | 商户 id | |
| currency | y | String | CAD | 固定为 CAD |
| start_date | y | String | 2027-01-01 | 扣款开始日期(UTC 时间,YYYY-MM-DD) |
| frequency | y | String | [w,2w,4w,m] | 当前可选配置为 w(每周)、2w(每两周)、4w(每 4 周,28 天)或 m(每月,每月固定某一日) |
| description | n | String(200) | Test recurring order. | 循环扣款交易的可选描述 |
| last_paid | y | String | 2027-01-01 | 上次成功扣款日期(UTC 时间,YYYY-MM-DD),若尚未成功扣款则默认为 "1970-01-01" |
| last_payment | y | String | 上次扣款(成功或失败)的 payorderid,若尚未发生扣款则为待处理首笔订单的 payorderid | |
| next_payment | y | String | 2027-01-08 | 下次计划扣款日期(UTC 时间,YYYY-MM-DD)。如果上次扣款失败,则保持为该次扣款的日期,且不再进行后续扣款 |
| cardId | y | String(50) | 应与请求中提供的 cardId 一致 |
取消循环扣款
用于停止循环扣款交易。后续不再进行扣款,被取消的循环扣款也不会再出现在查询接口的返回结果中
端点
https://ccapi.iotpaycloud.com/v3/recurring/cancel
方法
POST
头部
Content-Type: application/json;charset=UTF-8
请求
| 名称 | 必需 | 类型 | 示例 | 描述 |
|---|---|---|---|---|
| mchId | y | String | 10000701 | 由 IOTPay 分配 |
| loginName | y | String(12) | jack123 | 商户登录名 |
| recurringId | y | Int | 123 | 创建循环扣款接口 返回的循环扣款 id |
| sign | y | String(32) | 签名算法 |
响应
| 名称 | 必需 | 类型 | 示例 | 描述 |
|---|---|---|---|---|
| retCode | y | String | SUCCESS 或 FAIL | |
| retMsg | y | String | Successfully deleted recurring #255 | |
| retData | y | JSON | 如果 retCode 为 SUCCESS,返回循环扣款的详细信息 |
retData 包含循环扣款信息:
| 名称 | 必需 | 类型 | 示例 | 描述 |
|---|---|---|---|---|
| id | y | Int | 123 | 循环扣款 Id |
| amount | y | Int | 100 | 以分为单位 |
| mid | y | String | 商户 id | |
| currency | y | String | CAD | 固定为 CAD |
| start_date | y | String | 2027-01-01 | 扣款开始日期(UTC 时间,YYYY-MM-DD) |
| frequency | y | String | [w,2w,4w,m] | 当前可选配置为 w(每周)、2w(每两周)、4w(每 4 周,28 天)或 m(每月,每月固定某一日) |
| description | n | String(200) | Test recurring order. | 循环扣款交易的可选描述 |
| last_paid | y | String | 2027-01-01 | 上次成功扣款日期(UTC 时间,YYYY-MM-DD),若尚未成功扣款则默认为 "1970-01-01" |
| last_payment | y | String | 上次扣款(成功或失败)的 payorderid,若尚未发生扣款则为待处理首笔订单的 payorderid | |
| next_payment | y | String | 2027-01-08 | 下次计划扣款日期(UTC 时间,YYYY-MM-DD)。如果上次扣款失败,则保持为该次扣款的日期,且不再进行后续扣款 |
| cardId | y | String(50) | 与该循环扣款关联的 cardId |
循环扣款通知
循环扣款交易的每笔扣款完成后,IOTPay 会向创建请求中提供的 notifyUrl 发送通知。 这包括未提供 startDate 时的首次扣款(仅在成功时发送),以及之后的每一次计划扣款(无论成功与否)。 扣款失败会中止该循环扣款,因此 failed 通知将是该循环扣款发送的最后一次通知。
重要
收到通知后请以纯文本 SUCCESS 作出响应。 否则通知会再次发送,总共最多 3 次,每次间隔 60 秒。
方法
POST
头部
Content-Type: application/json;charset=UTF-8
请求
| 名称 | 必需 | 类型 | 示例 | 描述 |
|---|---|---|---|---|
| payOrderId | y | String | 本次扣款的支付订单 Id | |
| mchOrderId | y | String | 首次扣款为请求的 mchOrderNo,其后扣款与 payOrderId 相同 | |
| channel | y | String | PF_CC | 固定为 PF_CC |
| amount | y | Int | 1500 | 以分为单位 |
| status | y | String | success | success 表示扣款成功;failed 表示扣款未成功且该循环扣款已被中止。其他任何值(pending、paying、returned)均视为未扣款 |
| recurringId | y | Int | 123 | 本次扣款所属的循环扣款 id |
| previousOrder | y | String | 该循环扣款上一笔订单的支付订单 Id,首次扣款为空 | |
| paySuccessTime | n | String | 2021-04-07 19:44:51 | 支付成功的时间戳,仅在扣款成功时返回 |
| sign | y | String(32) | 使用您的商户密钥按签名算法进行验证 |
