Skip to content

GitLab

  • Projects
  • Groups
  • Snippets
  • Help
    • Loading...
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
  • Sign in
D documents
  • Project overview
    • Project overview
    • Details
    • Activity
    • Releases
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
  • Issues 0
    • Issues 0
    • List
    • Boards
    • Labels
    • Service Desk
    • Milestones
  • Merge requests 0
    • Merge requests 0
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
  • Operations
    • Operations
    • Incidents
    • Environments
  • Analytics
    • Analytics
    • CI/CD
    • Repository
    • Value Stream
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Members
    • Members
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • pass
  • documents
  • Wiki
    • 接口
  • 交易

交易 · Changes

Page history
yjf created page: 接口/交易 authored Dec 06, 2018 by 叶佳菲's avatar 叶佳菲
Hide whitespace changes
Inline Side-by-side
Showing with 517 additions and 0 deletions
+517 -0
  • 接口/交易.md 接口/交易.md +517 -0
  • No files found.
接口/交易.md 0 → 100644
View page @ 6c691cfa
[[_TOC_]]
写在前面
===
- 文中将${seq}定义为参数名为seq的参数,相关的表中有参数描述
- 文中将${timeout*}定义为可选的参数timeout
- 本文当中所有涉及到时间的参数都使用精确到毫秒的时间戳,例1535595007983表示Thu Aug 30 2018 10:10:07 GMT+0800 (中国标准时间)
- 本文中涉及到分页的接口使用skip、limit参数,表示跳过skip行取至多limit行,返回头X-Total-Count参数表示查询总行数
- 所有接口使用HTTP状态码200表示成功,其他状态码表示失败,如有特例将在具体接口中说明
接口描述
===
### R1.查询交易单
> - 本接口调用频率同一订单不超过1次/秒
```javascript
GET http://${domain}/sovellpay/v2/trade/${seq}
?timeout=${timeout*}
Authorization: Bearer ${token}
```
- 返回`PAYMENT`结构
```javascript
{
"id": ${id},
"status": ${status},
"status_msg": ${status_msg*},
"create_time": ${create_time},
"title": ${title},
"account_id": ${account_id*},
"notify_uri": ${notify_uri},
"seq": ${seq},
"trade_id": ${trade_id*},
"detail": [
{"tags": [${tags}...], "amount": ${amount}}
]
}
```
|参数名|类型|说明|
|:---|:---|:---|
|id|string|服务器订单号|
|seq|string|客户端订单号|
|title(128)|string|订单描述|
|status||订单状态|
||accepted|订单处理中,结果未知,需要继续查询订单状态||
||normal|正常,就是支付成功||
||refunding|退款中,结果未知,需要继续查询订单状态||
||refund|部分退款||
||closed|关闭||
|status_msg||订单信息,如果有需要输出的时候,例如错误的时候|
|create_time|int|支付时间戳(毫秒)|
|notify_uri|string|扫码支付时二维码信息|
|account_id|支付通道|见`支持的支付通道定义`|
|trade_id|string|业务订单号,如果存在|
|detail|list|明细,如果存在则输出|
| └ tags|list|明细标签组合,这是一个集合,取值不仅限于所列出值|
||wx|微信|
||ali|支付宝|
||jd|京东|
||qq|QQ|
||sh|大众闪惠|
||wing|翼支付|
||scan|刷卡支付,B扫C,商户扫用户|
||qr|扫码支付,C扫B,用户扫商户|
||h5|公众号支付|
||app|APP支付|
||card|卡支付|
||wallet|储值消费|
||helpbuy|代付优惠|
||credit|透支消费|
||subsidy|福利消费|
||coupon|券|
||settle|结算,一般不计入总金额|
| └ card|string|如果是卡支付的话则输出为卡号,非卡支付不输出|
| └ amount|int|实付金额|
| └ balance|int|交易后余额,wallet时给出该值|
### R2.事件总线
> - 查询token所授权终端的订单状态变更事件
```javascript
GET http://${domain}/sovellpay/v2/trade/event
?after=${index*}
&timeout=${timeout*}
&limit=${limit*}
Authorization: Bearer ${token}
```
|参数名|类型|说明|
|:---|:---|:---|
|limit|int|返回最大条数,默认100|
|index|int|初始是为0,之后的调用使用每次结果中的index|
|其他||见`公共请求参数说明`|
- 返回`PAYMENT`数组,返回参数定义同`R1.查询交易单`
```javascript
[{
"id": ${id},
"status": ${status},
"create_time": ${create_timestamp},
"title": ${title},
"goods": ${goods*},
"account_id": ${account_id*},
"notify_uri": ${notify_uri},
"seq": ${seq},
"index": ${index},
"trade_id": ${trade_id*}
}...]
```
### R3.查询可用账户
```javascript
GET http://${domain}/sovellpay/v2/accounts
Authorization: Bearer ${token}
```
- 返回
```javascript
[{
"name": ${name},
"account_id": ${account_id},
"id": ${mch_account},
"user_account": ${user_account},
"status": ${status},
"balance": ${balance*}
...
}...]
```
|参数名|类型|说明|
|:---|:---|:---|
|name|string|账户名|
|mch_account|string|商户账户|
|user_account|string|用户账户|
|status||账户状态||`
||normal|正常|||
||disabled|禁用|||
|account_id|支付通道|见`支持的支付通道定义`||
- 储值账户附加内容
|参数名|类型|说明|
|:---|:---|:---|
|balance|int|余额(分)|
|property||属性,可选|
| └ name||姓名,可选|
| └ corp_id||企业id,可选|
| └ depart||部门路径|
| └ no||工号|
|what||一定为wallet|
- 信用账户附加内容
|参数名|类型|说明|
|:---|:---|:---|
|balance|int|余额(分),表示剩余透支余额|
|what||一定为credit|
- 代付优惠账户附加内容
> 一般不需要体现在界面上
|参数名|类型|说明|
|:---|:---|:---|
|balance|int|优惠余额|
|what||一定为helpbuy|
- 券附加内容
|参数名|类型|说明|
|:---|:---|:---|
|balance|int|券余额(分),即券面额|
|what||一定为coupon|
- 错误返回
|参数名|类型|说明|
|:---|:---|:---|:---|
|code | |结果状态码|
||204|查询成功,但找不到|
||其他|见`公共返回参数说明 `|
### C1.单用户统一交易接口
> - 当用于刷卡支付时,即**商户扫用户的码**,调用时传入`pay_code`即可
> - 当用于扫码支付时,即**用户扫商户的码**,传入`app`参数,然后使用返回的`notify_uri`生成二维码
> - 当用于公众号支付时,页面直接跳转至`notify_uri`,交易完成后会跳转至`redirect_uri`
> - 当用于支付订单部分退款时,将原订单的`id`传入`original_id`
```javascript
POST http://${domain}/sovellpay/v2/trade?sign=${sign}
Authorization: Bearer ${token}
{
"intent": ${intent},
"title": ${title*},
"seq": ${seq},
"sub": ${sub},
"expire": ${expire*},
"attach": ${attach*},
"device": {
"id": ${device_id},
"name": ${device_name},
},
"goods": [{
"id": ${id},
"wechat_id": ${wechat_id},
"alipay_id": ${alipay_id},
"name": ${name},
"quantity": ${quantity},
"price": ${price}
}*...],
"pay_code": ${pay_code*},
"redirect_uri": ${redirect_uri*},
"app": ${app*},
"amount_due": ${amount_due*},
"original_id": ${original_id*},
"tags": [${tags}...]
}
```
|参数名|类型|说明|
|:---|:---|:---|
|title|string(128)|订单描述|
|intent|string|交易意图,参数说明见下文|
|original_id|string|原单据ID,退款时该参数必须提供|
|pay_code|string|支付码,支持微信反扫、支付宝反扫|
|redirect_uri|string|交易完成后的重定向地址|
|app|||
||wechat|微信扫码支付|
||alipay|支付宝扫码支付|
|goods||商品,如果有|
| └ id||商品id||
| └ wechat_id||微信支付定义的统一商品编号(如果有)||
| └ alipay_id||支付宝支付定义的统一商品编号(如果有)||
| └ name||商品名称||
| └ quantity||商品数量||
| └ price||商品单价(分)||
|operator|string|操作员,可空||
|attach|string|附加字段,可空,支付宝赋值store_id,微信赋值device_info||
|device|object|设备附加属性||
| └ device_id|string|设备id,统计时会使用这个id作为拆分凭据||
| └ device_name|string|设备名||
|amount_due|int|整单的应付金额,仅用作记录,为空是则自动计算|
|expire|string|预交易过期时间,没有单位时默认毫秒,格式为xxxs,默认300s,最大600s|
|tags||交易描述标签,用于策略消费|
||breakfast|早餐|
||lunch|午餐|
||dinner|晚餐|
||snack|夜宵|
|其他||见`公共请求参数说明`|
- 关于intent字符串的说明
|格式|说明|
|:---|:---|
|pay ${amount}|支付指定金额(分)|
|charge ${amount}|充值指定金额(分)(例如 charge 1)|
|refund ${amount}|退款指定金额(分)(例如 refund 1)|
|refund *|全额退款|
> 注:
1. 使用半角冒号分隔
3. 退款接口会根据外部请求号seq幂等返回,因此同一笔需要多次部分退款时,必须使用不同的seq。
- 返回同 `R1.查询交易单`
### D1.全额撤单
> - 必须由发起交易所在终端发起撤单
```javascript
DELETE http://${domain}/sovellpay/v2/trade/${seq}?sign=${sign}
Authorization: Bearer ${token}
```
- 返回同 `R1.查询交易单`
支持的支付通道定义
===
|定义名|说明|
|:---|:---|
|wechat|微信|
|alipay|支付宝|
|xqpos|享钱|
|idish|智盘本地卡|
|icbc|工商银行|
|jsb|江苏银行|
|third|本地第三方系统|
公共请求参数说明
===
|参数名|类型|说明|
|:---|:---|:---|
|domain|string|接口域名|
|token|string|访问令牌|
|timeout|string|阻塞查询时用,传0则立即返回结果,否则在timeout时间内若交易单状态发生变化时返回结果,格式为xxxs,默认10s|
|seq|string|客户端订单号,商户订单号,下位订单号|
|sign|string|签名,请看`如何签名`|
公共返回参数说明
===
### 错误返回
|参数名|类型|说明|
|:---|:---|:---|:---|
|code |int |结果状态码|
| |204 |不存在指定订单|
| |400 |请求参数错误|
| |402 |余额不足|
| |404 |不存在指定订单|
| |406 |支付异常|
| |408 |请求已接受但未及时完成,需要重新查询订单状态|
| |409 |订单已创建,需要查询订单状态|
| |其他 |未知状态|
|msg |string |结果消息|
```
注:
1. 所有错误还将以HTTP协议错误的形式返回
```
### 订单状态status的流转说明
```mermaid
graph LR
accepted
accepted --> |支付失败| closed
closed --> |退款请求| refunding(refunding)
accepted --> |发起了撤单| refunding
accepted --> |支付成功| normal
normal --> |退款请求| refunding(refunding)
refunding --> |退款成功| closed
refunding --> |退款失败| normal
refunding --> |部分退款成功| refund
refund --> |退款请求| refunding4(refunding)
refunding4 --> |部分退款成功| refund
refunding4 --> |部分退款失败| refund
```
推荐的支付流程
===
### H5支付流程
- 需要从前端页面跳转至*notify_uri*,用户在该页面完成相关业务操作后再回跳到商户指定页面。
```mermaid
sequenceDiagram
用户->>商户系统: 下单
商户系统->>PasS: 调用交易接口C1
note right of PasS: 填写商户单号seq <br/>填写支付金额to <br/>填写回调地址redirect_uri
PasS->>商户系统: 返回结果,取到notify_uri
opt 失败重试
商户系统->>PasS: 检查参数并重新发起交易C1
PasS->>商户系统: 返回结果
end
商户系统->>用户: 跳转至notify_uri
用户->>PasS: 进入支付页面
PasS->>商户系统: 完成支付,进入redirect_uri
商户系统-->>用户: 结果展示页面
用户-->>商户系统: 查询支付结果
loop status!=accepted
商户系统->>PasS: 查询交易单状态R1
PasS->>商户系统: 返回结果
end
商户系统-->>用户: 结果展示页面
opt 如果需要撤单
商户系统->>PasS: 发起撤单D1
PasS->>商户系统: 返回结果
loop status!=refudning
商户系统->>PasS: 查询交易单状态R1
PasS->>商户系统: 返回结果
end
end
```
如何签名
===
1. 设所有发送或者接收到的数据为集合M,将集合M内非空参数值的参数按照参数名ASCII码从小到大排序(字典序),使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串。
特别注意以下重要规则:
1. 参数名ASCII码从小到大排序(字典序);
2. 如果参数的值为空不参与签名;
3. 参数名区分大小写;
4. 验证时,传送的sign参数不参与签名,将生成的签名与该sign值作校验。
5. 接口可能增加字段,验证签名时必须支持增加的扩展字段
2. 最后拼接上key得到stringSignTemp字符串,并对stringSignTemp进行MD5运算,再将得到的字符串所有字符转换为大写,得到sign值signValue。
举例:
假设传送的参数如下:
```javascript
{
"title": "这是演习",
"seq": "15",
"to": "alipay:1",
"expire": "60s",
"app": "alipay",
"goods": [
{
"name": "hello",
"id": "123",
"quantity": 1,
"price": 1
}
]
}
```
第一步:对参数按照key=value的格式,并按照参数名ASCII字典序排序如下:
```
app=alipay&expire=60s&goods=[{"name":"hello","id":"123","quantity":1,"price":1}]&seq=15&title=这是演习&to=alipay:1
```
第二步:拼接API密钥,key为终端密钥(即client_secret):
```
app=alipay&expire=60s&goods=[{"name":"hello","id":"123","quantity":1,"price":1}]&seq=15&title=这是演习&to=alipay:1&key=3AjtoC3NpW
```
第三步:计算签名
```javascript
//注:MD5签名方式
sign = MD5(stringSignTemp)="8b8c383ad3c10bc3e22cdd1aff4e86f2"
```
最终得到最终发送的数据:
```javascript
{
"title": "这是演习",
"seq": "15",
"to": "alipay:1",
"expire": "60s",
"app": "alipay",
"goods": [
{
"name": "hello",
"id": "123",
"quantity": 1,
"price": 1
}
],
"sign": "8b8c383ad3c10bc3e22cdd1aff4e86f2"
}
```
调用示例
===
### 支付码反扫成功示例
```javascript
POST http://dev.sovell.com/sovellpay/v1/trade HTTP/1.1
Authorization: Bearer ee3ddf8ef03fa549028ff18a7d314116
Content-Type: application/json; charset=utf-8
Host: dev.sovell.com
Content-Length: 75
Connection: Keep-Alive
{
"pay_code": "280978609094625751",
"seq": 636207894193718264,
"to": "cmbcpay:1"
}
```
```javascript
HTTP/1.1 200 OK
Server: nginx/1.6.3
Date: Mon, 23 Jan 2017 09:31:08 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 12
Connection: keep-alive
{
"id": "203b4954eeb949b183c94f859397de2a",
"status": "normal",
"create_timestamp": 1487908305815,
"title": "这是演习",
"seq": "636207894193718264"
}
```
\ No newline at end of file
Clone repository
  • Home
  • 接口
    • 交易
    • 消息
    • 用户
    • 通用券
  • 渠道
    • 微信 1基本参数
    • 微信 2商户平台配置
    • 微信 3公众号参数
    • 微信 4公众平台配置
    • 微信(服务商方式)
    • 支付宝 1基本参数
    • 支付宝 2公钥上传
    • 支付宝(服务商方式)