# 概述 ## 目的 本文档定义了如下接口:商户网站与 ptpay 支付平台间的支付接口、商户网站与 ptpay 支付平台间 的支付结果通知接口(包括:服务器后台异步通知接口)、商户网站与 ptpay 支付平台间的单笔交易查 询接口。 ## 术语与缩略语 appId : 商户在商户平台创建应用的唯一标识 appKey : 商户在商户平台创建应用时自动生成的密钥 BTC:数字货币比特币 ETH:数字货币以太币 LTC:数字货币莱特币 BCH:数字货币比特币现金 USDT:数字货币泰达币 EOS:数字货币 EOS TATO:数字货币 TATO POC:数字货币POC * 目前 appId 以及 appKey 由商户申请,由商户平台生成并分发至商户。 ## 适用范围 本文档适用的支付币种包括:BTC、EOS、ETH、LTC、BCH、USDT、TATO、POC ## 接口清单 | 序号 | 接口名称 | 接口描述 | | --- | --- | --- | | 1 | 支付接口 | 定义商户网站与 ptpay 支付平台间支付交易接口。 | | 2 | 支付结果通知接口 | 定义商户网站与 ptpay 支付平台间的支付结果通知接口,包括:服务器后台异步通知接口. | | 3 | 交易查询接口 | 定义商户网站与 ptpay 支付平台间的单笔交易查询接口。 | ## 报文格式 为保证安全,使用 https 协议传输,使用 post 提交数据,content-type 必须为 application/json,请求参数以 json 格式放置于 body 内传输。接口返回统一为 json: { code : int , //错误码(0 为成功,其他为失败) message : string , //错误原因 data : object //请求成功的结果 } ## 签名方式 ### 签名按如下步骤生成 1. 设所有发送的数据为集合 M , 将集合 M 内非空参数值的参数按照参数名 ASCII 码从小到大排序 (字典序 , 使用 URL 键值对的格式(即 key1=value1&key2=value2…)拼接成字符串 stringA . 注意以下重要规则 : * 参数名 ASCII 码从小到大排序(字典序). * 如果参数的值为空不参与签名 . * 参数名区分大小写 . * 验证调用返回或主动通知签名时 , 传送的 sign 参数不参与签名 , 将生成的签名与该 sign 值作校验 . * 接口可能增加字段 , 验证签名时必须支持增加的扩展字段 . 2. 在 stringA 赋值得到 stringSignTemp 字符串 , 并对 stringSignTemp 进行 HMAC\_SHA256 算法运算,再将得到的字符串所有字符转换为小写,得到 sign 值 signValue. 示例: 假设传送的参数如下 : { "appId":"pt2d485db1ee8a4beeab761c883faa73c2", "title":" Texas Hold'em Diamond Purchase ", "mchOrderId":"73649d7a8e4811e8a879001a7dda7111", "currency":"BTC", "amount":"0.00001", "deviceIp":"10.10.10.10", "notifyUrl": "[http://hello](http://hello/)", "nonce": "73649d7b8e4811e89c11001a7dda7111", "timestamp": 1562499372 } 第一步 、对参数按照 key=value 的格式 , 并按照参数名 ASCII 字典序排序如下 : stringA = `"amount=0.00001&appId=pt2d485db1ee8a4beeab761c883faa73c2&currency=BTC&deviceIp=10.10.10.10&mchOrderId=73649d7a8e4811e8a879001a7dda7111&nonce=73649d7b8e4811e89c11001a7dda7111&notifyUrl=http://hello&timestamp=1532330245&title=Texas Hold'em Diamond Purchase "` 第二步、使用 HMAC\_SHA256 算法签名 : stringSignTemp=stringA sign=HMAC\_SHA256(stringSignTemp, key) //HMAC\_SHA256 算法签名,key 为商户应用密钥 最终得到最终发送的数据 : { "appId": "pt2d485db1ee8a4beeab761c883faa73c2", "title": " Texas Hold'em Diamond Purchase ", "mchOrderId": "73649d7a8e4811e8a879001a7dda7111", "currency":"BTC", "amount":"0.00001", "deviceIp":"10.10.10.10", "notifyUrl": "[http://hello](http://hello/)", "nonce": "73649d7b8e4811e89c11001a7dda7111", "timestamp": 1562499372, "sign": "6e1b8019e0c132bb6b215c1c250b49a0a6f3fb6b17b0285b4ce385f0835a529b" } ## 接口定义 ### 支付交易接口 #### 描述 定义商户网站与 ptpay 支付平台间的支付交易接口 , 商户网站按照接口规范定义将交易订单数据提交到 ptpay api 支付网关 , 以 HTTPS POST 方式提交数据. #### 接口参数定义 * 交易请求地址: https://waltapi.ptwlt.me/ptpay/order 请求参数中的参数编码仅限于UTF-8 . 请求参数: | 参数 | 参数名称 | 类型(长度) | 必填 | 说明 | | --- | --- | --- | --- | --- | | appId | 商户应用 ID | string(34) | 是 | 商户在商户后台创建应用的 appId . 例 : 1ce78f96ed4748eebd63d6cc97a74839 | | nonce | 随机字符串 | string(32) | 是 | 防止重复随机字符串 . 例 :73649d7b8e4811e89c11001a7dda7111 | | timestamp | 时间戳 | int(64) | 是 | 服务器当前时间戳(单位秒) . 例:1532330245 | | title | 商品描述 | string(64) | 是 | 用于 ptpay 支付界面显示商品名称 . 例 : 德州扑克钻石购买 | | mchOrderId | 商户订单 ID | string(32) | 是 | 要求 32 个字符内 , 只能是数字 、 大小写字母且在同一个商户号下唯一 . 例 :73649d7a8e4811e8a879001a7dda7111 | | openId | 授权ID | string(32) | 否 | 用户授权成功后返回的openId . 例 :SEC7syJ6TuG90Iawd9ea2A== | | currency | 币种 | string(8) | 是 | 渠道所支持的币种 . 例 :BTC | | amount | 订单金额 | string(32) | 是 | 订单金额 , 数字货币个数为单位 . 例 :0.0001 | | deviceType | 设备类型 | string(32) | 否 | 用户设备终端类型 . 例:IOS | | deviceId | 设备 ID | string(32) | 否 | 用户设备 ID . 例:device-01 | | deviceIp | 设备 IP | string(64) | 是 | 用户设备 IP , 例:10.10.10.10 | | notifyUrl | 通知地址 | string(255) | 是 | 支付异步通知回调地址 , 通知地址必须为直接可访问的地址 , 不能携带参数 . 例 :[http://hello.notify.com](http://hello.notify.com/) | | redirectUrl | 支付成功后跳转地址 | string(255) | 否 | 客户支付成功后 , 页面跳转商户地址 . 例(APP 端): yyyyyy://paid yyyyy :商户自定义短域名然后会根据商户提供进行拼接 , 返回三方APP yyyyyy://paid?order=xxxxxx&errno=norder 为订单 ID , 从商户下单接口返回参数中获取 errno 为本次支付状态 , 0 成功/1 用户取消/2 其他错误 | | sign | 签名 | string(64) | 是 | 参数签名 , 详见章节 6 签名算法 .例: 6e1b8019e0c132bb6b215c1c250b49a0a6f3fb6b17b0285b4ce385f0835a529b . | 响应参数: | 参数 | 参数名称 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | --- | | code | 返回状态码 | int | 是 | 返回状态码 :0 为成功,其他非成功状态 , 具体异常参见状态码说明 . | | message | 返回信息描述 | string | 否 | 返回信息描述 , 非成功状态不为空 . | | data | 返回结果 | json | 否 | 返回结果 , 成功状态不为空 . | 当交易处理成功时 , 返回 data 数据格式如下 : | 参数 | 参数名称 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | --- | | url | 支付地址 | string | 是 | 商户跳转至 ptpay 的支付地址 . 例 :pt://pay?order=xxxxxx [BS:如果是小程序,请按照《小程序开发说明》拉起支付的方法](https://developer.potato.im/#/docs/applet#payment) | | orderId | ptpay 订单号 | string | 是 | ptpay 订单号 | ### 商户支付通知 #### 描述 支付完成后 , ptpay 会把相关支付结果和用户信息发送给商户 , 商户需要接收处理 , 并返回应答.对后台通知交互时 , 如果 ptpay 收到商户的应答不是成功或超时 , ptpay 认为通知失败 , ptpay 会通过一定的策略定期重新发起通知 , 尽可能提高通知的成功率 , 但 ptpay 不保证通知最终能成功 . * 注意 :同样的通知可能会多次发送给商户系统 . 商户系统必须能够正确处理重复的通知 . 推荐的做法是 , 当收到通知进行处理时 , 首先检查对应业务数据的状态 , 判断该通知是否已经处理过 , 如果没有处理过再进行处理 , 如果处理过直接返回结果成功 . 在对业务数据进参数签名行状态检查和处理之前 , 要采用数据锁进行并发控制 , 以避免函数重入造成的数据混乱 . 特别提醒 :商户系统对于支付结果通知的内容一定要做签名验证 , 并校验返回的订单金额是否与商户侧的订单金额一致 , 防止数据泄漏导致出现 " 假通知 " , 造成资金损失 . 请求地址 :该链接是通过下单接口中提交的参数 notifyUrl 设置 , 如果链接无法访问 , 商户将无法接收到通知. #### 接口参数定义 通知参数 : | 参数 | 参数名称 | 类型(长度) | 必填 | 说明 | | --- | --- | --- | --- | --- | | appId | 商户应用 ID | string(34) | 是 | 商户在商户后台创建应用的 appId .例: 1ce78f96ed4748eebd63d6cc97a74839 | | mchOrderId | 商户订单号 | string(32) | 是 | 要求 32 个字符内 , 只能是数字、大小写字母且在同一个商户号下唯一 . 例 :73649d7a8e4811e8a879001a7dda7111 | | currency | 币种 | string(8) | 是 | 渠道所支持的币种 . 例:BTC | | amount | 订单金额 | string(32) | 是 | 订单金额 , 数字货币个数字符串 . 例:0.00001 | | nonce | 随机字符串 | string(32) | 是 | 防止重复随机字符串 . 例 :73649d7b8e4811e89c11001a7dda7111 | | timestamp | 时间戳 | int(64) | 是 | 服务器当前时间戳(单位秒) . 例:1532330245 | | orderId | ptpay 订单号 | string(32) | Yes | ptpay 支付页面显示的订单号 . 例 :2019062910737174223 | | time | 下单时间 | int(32) | 是 | 商户下单时间(时间戳秒). 例:1532330245 | | finishTime | 支付完成时间 | int(32) | 是 | 支付完成时间 ( 时间戳秒 ) . 例:1562553723 | | status | 订单状态 | int(8) | 是 | 订单支付状态 . 例:1 | | sign | 签名 | string(64) | Yes | 参数签名,详见章节 6 签名算法 . 例 :6e1b8019e0c132bb6b215c1c250b49a0a6f3fb6b17b0285b4ce385f0835a529b | * 响应参数: 商户成功处理后必须返回字符串 " success " , 否则 ptpay 认为通知失败,根据重试的策略重新发送通知 . ## 商户查单接口 ### 描述 定义商户网站与 ptpay 支付平台间的单笔交易查询接口 . 注意:该接口用于商户的异常订单对账,有访问频次限制,请不要用于用户交易时的订单状态轮询 . ### 接口参数定义 * 交易请求地址 :https://waltapi.ptwlt.me/ptpay/order/query 请求参数中的参数编码仅限于 UTF-8 . 请求参数: | 参数 | 参数名称 | 类型(长度) | 必填 | 说明 | | --- | --- | --- | --- | --- | | appId | 商户应用 ID | string(34) | 是 | 商户在商户后台创建应用的 appId . 例 : 1ce78f96ed4748eebd63d6cc97a74839 | | nonce | 随机字符串 | string(32) | 是 | 防止重复随机字符串 . 例 :73649d7b8e4811e89c11001a7dda7111 | | timestamp | 时间戳 | int(64) | 是 | 服务器当前时间戳 ( 单位秒 ) . 例 : 1532330245 | | mchOrderId | 商户订单号 | string(32) | 是 | 要求 32 个字符内 , 只能是数字、大小写字母且在同一个商户号下唯一 . 例 :73649d7a8e4811e8a879001a7dda7111 | | sign | 签名 | string(64) | 是 | 参数签名 , 详见章节 6 签名算法 . 例: 6e1b8019e0c132bb6b215c11c250b49a0a6f3fb6b17b0285b4ce385f0835a529b | 响应参数 : | 参数 | 参数名称 | 类型(长度) | 必填 | 说明 | | --- | --- | --- | --- | --- | | code | 返回状态码 | int(32) | 是 | 返回状态码 :0 为成功 , 其他非成功状态 , 具体异常参见状态码说明 | | message | 返回信息描述 | string | 否 | Return message , unsuccessful status is not empty. | | data | 返回结果 | json | 否 | 返回结果 , 成功状态不为空 . | 当交易处理成功时 , 返回 data 数据格式如下: | 参数 | 参数名称 | 类型(长度) | 必填 | 说明 | | --- | --- | --- | --- | --- | | appId | 商户应用 ID | string(34) | 是 | 商户在商户后台创建应用的 appId . 例: 1ce78f96ed4748eebd63d6cc97a74839 | | mchOrderId | 商户订单号 | string(32) | 是 | 要求 32 个字符内 , 只能是数字、大小写字母且在同一个商户号下唯一 . 例 :73649d7a8e4811e8a879001a7dda7111 | | orderId | ptpay 订单号 | string(32) | 是 | ptpay 支付页面显示的订单号 . 例 :2019062910737174223 | | currency | 币种 | string(8) | 是 | 渠道所支持的币种 . 例:BTC | | amount | 订单金额 | string(32) | 是 | 订单金额 , 数字货币个数字符串 . 例:0.00001 | | time | 下单时间 | int(64) | 是 | 商户下单时间(时间戳秒). 例:1532330245 | | finishTime | 支付完成时间 | int(64) | 否 | 支付完成时间(时间戳秒). 例:1562553723 | | status | 订单状态 | int(8) | 是 | 订单状态 ( 0 : 待支付 、1 :已支付、2:支付取消) 例:1 | ## 附录 响应码说明 | code | 含义 | | --- | --- | | 0 | 调用成功 | | 1 | 未知错误 | | 2 | 参数非法 | | 3 | 服务器错误 | | 4 | 请求频繁 | | 7 | 无效的 APPID | | 8 | 支付功能未开通 | | 9 | 无效的openId | | 32 | 商户该币种暂不支持 | | 33 | 签名错误 | | 34 | 商户订单已存在 | | 35 | 商户订单不存在 |