# 概述
## 目的
本文档定义了如下接口:商户网站与 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¤cy=BTC&deviceIp=10.10.10.10&mchOrderId=73649d7a8e4811e8a879001a7dda7111&nonce=73649d7b8e4811e89c11001a7dda7111¬ifyUrl=http://hello×tamp=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 | 商户订单不存在 |