添加文件: ymt_v3_2/refine.md
This commit is contained in:
parent
287cdd5d6d
commit
cd6feb1ef1
|
|
@ -0,0 +1,351 @@
|
||||||
|
文档类型:调用文档
|
||||||
|
|
||||||
|
## 环境地址
|
||||||
|
- 测试环境:https://gateway.dev.cdlsxd.cn
|
||||||
|
- 正式环境:https://market.api.86698.cn
|
||||||
|
|
||||||
|
## 测试参数
|
||||||
|
- app_id: "xxx"
|
||||||
|
- private_key: "xxx"(应用客户私钥,用于请求签名)
|
||||||
|
- public_key: "xxx"(应用平台公钥,用于响应或回调验签)
|
||||||
|
- key: "xxxx"(业务参数加密key)
|
||||||
|
- activity_no: "xxxx"
|
||||||
|
- sign_type: "RSA"
|
||||||
|
|
||||||
|
## 认证、加密、签名
|
||||||
|
|
||||||
|
### 业务参数加密
|
||||||
|
1. 将业务参数去掉值为“零”的参数(零值判断规则未明确,通常指空字符串、0等),按字母升序排序后转为JSON字符串,得到 `plaintext`。
|
||||||
|
2. 使用应用 `key` 对 `plaintext` 进行加密,加密方式为 AES(ECB模式) 或 SM4(CBC模式),得到 `ciphertext`。
|
||||||
|
|
||||||
|
### 签名规则
|
||||||
|
- 签名字符串拼接:`appid` + `timestamp` + `ciphertext`
|
||||||
|
- 使用应用私钥(`private_key`)对签名字符串进行签名,生成 `Sign`。
|
||||||
|
|
||||||
|
### 请求模式
|
||||||
|
- Header 传递:`Appid`、`Timestamp`、`Sign`、`Content-Type: application/json`
|
||||||
|
- Body 传递:`{"ciphertext": "加密后的业务报文"}`
|
||||||
|
|
||||||
|
### 响应说明
|
||||||
|
- 业务响应数据通过 `data.ciphertext` 返回,需使用应用 `key` 解密,解密方式与加密一致(AES ECB / SM4 CBC)。
|
||||||
|
- 解密后得到业务响应 JSON。
|
||||||
|
|
||||||
|
### 回调验签
|
||||||
|
1. 获取 Header 中的签名信息。
|
||||||
|
2. 获取 Body 中的业务参数 `data`。
|
||||||
|
3. 将 `data` 去掉“零”值参数,按字母升序排序后转 JSON 字符串得到 `plaintext`。
|
||||||
|
4. 使用应用 `key` 加密 `plaintext` 得到 `ciphertext`。
|
||||||
|
5. 拼接签名字符串:`appid` + `timestamp` + `ciphertext`。
|
||||||
|
6. 使用应用公钥(`public_key`)验签。
|
||||||
|
|
||||||
|
### 时间戳规则
|
||||||
|
- 格式:`yyyy-MM-dd HH:mm:ss`
|
||||||
|
- 请求时间与服务端时间误差不能超过 3 分钟。
|
||||||
|
|
||||||
|
### SDK
|
||||||
|
- Go: https://gitee.com/chengdu_blue_brothers/ymt-openapi-go-sdk.git
|
||||||
|
- Java: https://codeup.aliyun.com/lsxd/marketing/ymt-openapi-java-sdk.git
|
||||||
|
|
||||||
|
## 公共参数
|
||||||
|
|
||||||
|
### 公共 Header 请求参数
|
||||||
|
| 字段名称 | 类型 | 描述 | 示例值 |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| Appid | string | 分配给开发者的应用 ID | 123456 |
|
||||||
|
| Timestamp | string | 发送请求的时间,格式 yyyy-MM-dd HH:mm:ss | 2026-06-22 15:30:00 |
|
||||||
|
| Sign | string | 请求签名串 | 详见 SDK 示例 |
|
||||||
|
| Content-Type | string | 请求数据格式 | application/json |
|
||||||
|
|
||||||
|
示例:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"Sign": ["签名字符串"],
|
||||||
|
"Appid": ["应用ID"],
|
||||||
|
"Timestamp": ["请求时间"],
|
||||||
|
"Content-Type": ["application/json"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 公共请求参数(Body)
|
||||||
|
| 字段名称 | 类型 | 描述 | 示例值 |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| ciphertext | string | 请求业务参数加密串 | 详见 SDK 示例 |
|
||||||
|
|
||||||
|
示例:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"ciphertext": "加密后的业务报文"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 公共响应参数
|
||||||
|
| 字段名称 | 类型 | 描述 |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| code | int32 | 200 成功 |
|
||||||
|
| message | string | 请求描述 |
|
||||||
|
| reason | string | 错误原因,错误时返回 |
|
||||||
|
| data.ciphertext | string | 业务响应加密串 |
|
||||||
|
|
||||||
|
## 错误码
|
||||||
|
|
||||||
|
### 公共错误码
|
||||||
|
| code | reason | 错误原因 | 解决 |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| 500 | PANIC/其它 | 系统错误 | 联系平台处理 |
|
||||||
|
| 400 | INVALID_PAYLOAD | 请求外壳格式错误 | 请检查请求 JSON 结构 |
|
||||||
|
| 400 | MISSING_PARAM | 缺少必要参数 | 请检查 app_id、timestamp、sign、ciphertext |
|
||||||
|
| 400 | INVALID_TIMESTAMP | 时间格式错误 | 请检查时间格式 |
|
||||||
|
| 400 | DECRYPT_FAILED | 业务参数解密失败 | 请检查加密方式与密钥 |
|
||||||
|
| 401 | APP_NOT_FOUND | 应用不存在 | 请检查应用 ID |
|
||||||
|
| 401 | INVALID_SIGNATURE | 签名错误 | 请检查签名串与私钥 |
|
||||||
|
| 401 | EXPIRED_TIMESTAMP | 请求已过期 | 请检查客户端时间 |
|
||||||
|
| 429 | DUPLICATE_REQUEST | 重复请求,请稍后重试 | 请避免短时间内重复提交同一业务号 |
|
||||||
|
|
||||||
|
### 业务错误码
|
||||||
|
| code | reason | 错误原因 | 解决 |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| 401 | ACTIVITY_NOT_AUTH | 活动未授权 | 请检查活动授权状态 |
|
||||||
|
| 401 | MERCHANT_NOT_EXIST | 客户不存在 | 请检查客户是否存在 |
|
||||||
|
| 401 | MERCHANT_NOT_AUTH | 客户冻结 | 请检查客户授权状态 |
|
||||||
|
| 401 | MERCHANT_APP_INCOMPLETE | 客户应用配置未完善 | 请检查客户应用配置 |
|
||||||
|
| 401 | MERCHANT_APP_NOT_AUTH | 应用不存在或未授权 | 请检查客户应用授权状态 |
|
||||||
|
| 403 | ACTIVITY_EXPIRE | 活动已结束 | 请检查活动是否有效 |
|
||||||
|
| 403 | ACTIVITY_OUT_OF_STOCK | 活动剩余量不足 | 请检查活动库存 |
|
||||||
|
| 404 | ACTIVITY_NOT_EXIST | 活动不存在 | 请检查活动编号 |
|
||||||
|
| 404 | MERCHANT_ORDER_NOT_EXIST | 订单不存在 | 请检查交易号或外部业务号 |
|
||||||
|
| 404 | KEY_NOT_EXIST | key码不存在 | 请检查订单信息 |
|
||||||
|
| 400 | PARAM_FAIL | 参数错误 | 请检查业务参数 |
|
||||||
|
| 400 | PARAM_DECRYPT_FAIL | 明文参数格式错误 | 请检查密文解密后的业务报文 |
|
||||||
|
|
||||||
|
## 接口列表
|
||||||
|
|
||||||
|
### 1. 获取券码
|
||||||
|
- **请求方式**:POST
|
||||||
|
- **Content-Type**:application/json
|
||||||
|
- **请求路由**:`/openapi/v1/key/order`
|
||||||
|
|
||||||
|
#### 业务请求参数(加密前明文)
|
||||||
|
| 字段名称 | 类型 | 描述 | 是否必填 | 示例值 |
|
||||||
|
| --- | --- | --- | --- | --- |
|
||||||
|
| out_biz_no | string | 外部业务号,幂等 | M | 123456 |
|
||||||
|
| activity_no | string | 活动编号 | M | ACT20260622001 |
|
||||||
|
| account | string | 账号,按活动类型透传 | N | 18666666666 |
|
||||||
|
| notify_url | string | 回调通知地址 | N | https://notify.example.com/openapi |
|
||||||
|
|
||||||
|
#### 业务响应参数(解密后)
|
||||||
|
| 字段名称 | 类型 | 是否必填 | 描述 |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| out_biz_no | string | M | 外部业务号 |
|
||||||
|
| trade_no | string | M | 交易号 |
|
||||||
|
| key | string | N | 卡密 |
|
||||||
|
| url | string | N | 链接型活动返回短链接,key/url 不会同时为空 |
|
||||||
|
| valid_begin_time | string | N | 生效时间 |
|
||||||
|
| valid_end_time | string | N | 失效时间 |
|
||||||
|
| usable_num | uint32 | M | 可用次数 |
|
||||||
|
| usage_num | uint32 | M | 已使用次数 |
|
||||||
|
| status | uint32 | M | 状态:1 正常,2 已核销,3 已作废 |
|
||||||
|
| settlement_price | float | N | 结算价 |
|
||||||
|
| account | string | N | 上报账号 |
|
||||||
|
|
||||||
|
#### 请求示例
|
||||||
|
明文业务参数:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"out_biz_no": "order_001",
|
||||||
|
"activity_no": "ACT20260622001",
|
||||||
|
"account": "18666666666",
|
||||||
|
"notify_url": "https://notify.example.com/openapi"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
请求体:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"ciphertext": "加密后的业务报文"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 响应示例
|
||||||
|
异常:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 401,
|
||||||
|
"message": "Signature verification failed",
|
||||||
|
"reason": "INVALID_SIGNATURE"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
成功:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"data": {
|
||||||
|
"ciphertext": "加密后的响应报文"
|
||||||
|
},
|
||||||
|
"message": "成功"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
解密后示例:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"out_biz_no": "order_001",
|
||||||
|
"trade_no": "7251449503000383488",
|
||||||
|
"key": "aZKdU9BymzR6qGRzJM",
|
||||||
|
"url": "",
|
||||||
|
"valid_begin_time": "2026-06-22 15:30:00",
|
||||||
|
"valid_end_time": "2026-12-31 23:59:59",
|
||||||
|
"usable_num": 1,
|
||||||
|
"usage_num": 0,
|
||||||
|
"status": 1,
|
||||||
|
"settlement_price": 9.9,
|
||||||
|
"account": "18666666666"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 券码查询
|
||||||
|
- **请求方式**:POST
|
||||||
|
- **Content-Type**:application/json
|
||||||
|
- **请求路由**:`/openapi/v1/key/query`
|
||||||
|
|
||||||
|
#### 业务请求参数(加密前明文)
|
||||||
|
| 字段名称 | 类型 | 描述 | 是否必填 | 示例值 |
|
||||||
|
| --- | --- | --- | --- | --- |
|
||||||
|
| out_biz_no | string | 外部业务号,与 trade_no 二选一 | N | order_001 |
|
||||||
|
| trade_no | string | 交易号,与 out_biz_no 二选一 | N | 7251449503000383488 |
|
||||||
|
|
||||||
|
#### 业务响应参数
|
||||||
|
与“获取券码”响应参数一致。
|
||||||
|
|
||||||
|
#### 响应示例
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"data": {
|
||||||
|
"out_biz_no": "order_001",
|
||||||
|
"trade_no": "7251449503000383488",
|
||||||
|
"key": "aZKdU9BymzR6qGRzJM",
|
||||||
|
"url": "",
|
||||||
|
"valid_begin_time": "2026-06-22 15:30:00",
|
||||||
|
"valid_end_time": "2026-12-31 23:59:59",
|
||||||
|
"usable_num": 1,
|
||||||
|
"usage_num": 0,
|
||||||
|
"status": 1,
|
||||||
|
"settlement_price": 9.9,
|
||||||
|
"account": "18666666666",
|
||||||
|
"ciphertext": ""
|
||||||
|
},
|
||||||
|
"message": "成功"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 券码作废
|
||||||
|
- **请求方式**:POST
|
||||||
|
- **Content-Type**:application/json
|
||||||
|
- **请求路由**:`/openapi/v1/key/discard`
|
||||||
|
|
||||||
|
#### 业务请求参数(加密前明文)
|
||||||
|
| 字段名称 | 类型 | 描述 | 是否必填 | 示例值 |
|
||||||
|
| --- | --- | --- | --- | --- |
|
||||||
|
| out_biz_no | string | 外部业务号,与 trade_no 二选一 | N | order_001 |
|
||||||
|
| trade_no | string | 交易号,与 out_biz_no 二选一 | N | 7251449503000383488 |
|
||||||
|
|
||||||
|
#### 业务响应参数(解密后)
|
||||||
|
| 字段名称 | 类型 | 是否必填 | 描述 |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| out_biz_no | string | M | 外部业务号 |
|
||||||
|
| trade_no | string | M | 交易号 |
|
||||||
|
| status | uint32 | M | 3 表示已作废 |
|
||||||
|
|
||||||
|
#### 响应示例
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"data": {
|
||||||
|
"out_biz_no": "order_001",
|
||||||
|
"trade_no": "7251449503000383488",
|
||||||
|
"status": 3,
|
||||||
|
"ciphertext": ""
|
||||||
|
},
|
||||||
|
"message": "成功"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. 批量发卡
|
||||||
|
- **请求方式**:POST
|
||||||
|
- **Content-Type**:application/json
|
||||||
|
- **请求路由**:`/openapi/v1/key/batch_order`
|
||||||
|
|
||||||
|
#### 业务请求参数(加密前明文)
|
||||||
|
| 字段名称 | 类型 | 描述 | 是否必填 | 示例值 |
|
||||||
|
| --- | --- | --- | --- | --- |
|
||||||
|
| out_biz_no | string | 外部业务号,幂等 | M | batch_001 |
|
||||||
|
| activity_no | string | 活动编号 | M | ACT20260622001 |
|
||||||
|
| number | int32 | 发卡数量 | M | 100 |
|
||||||
|
| notify_url | string | 回调通知地址 | N | https://notify.example.com/openapi |
|
||||||
|
|
||||||
|
#### 业务响应参数(解密后)
|
||||||
|
| 字段名称 | 类型 | 是否必填 | 描述 |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| out_biz_no | string | M | 外部业务号 |
|
||||||
|
| trade_no | string | M | 交易号 |
|
||||||
|
| status | string | M | 任务状态,初始返回 processing |
|
||||||
|
|
||||||
|
#### 响应示例
|
||||||
|
成功:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"data": {
|
||||||
|
"ciphertext": "加密后的响应报文"
|
||||||
|
},
|
||||||
|
"message": "成功"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
解密后示例:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"out_biz_no": "batch_001",
|
||||||
|
"trade_no": "7251449503000383499",
|
||||||
|
"status": "processing"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. 批量查询
|
||||||
|
- **请求方式**:POST
|
||||||
|
- **Content-Type**:application/json
|
||||||
|
- **请求路由**:`/openapi/v1/key/batch_query`
|
||||||
|
|
||||||
|
#### 业务请求参数(加密前明文)
|
||||||
|
| 字段名称 | 类型 | 描述 | 是否必填 | 示例值 |
|
||||||
|
| --- | --- | --- | --- | --- |
|
||||||
|
| out_biz_no | string | 外部业务号,与 trade_no 二选一 | N | batch_001 |
|
||||||
|
| trade_no | string | 交易号,与 out_biz_no 二选一 | N | 7251449503000383499 |
|
||||||
|
|
||||||
|
#### 业务响应参数(解密后)
|
||||||
|
| 字段名称 | 类型 | 是否必填 | 描述 |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| out_biz_no | string | M | 外部业务号 |
|
||||||
|
| trade_no | string | M | 交易号 |
|
||||||
|
| status | string | M | processing / success / failed |
|
||||||
|
| download_url | string | N | 批量任务成功后返回下载地址 |
|
||||||
|
| zip_password | string | N | 批量任务成功后返回压缩包密码 |
|
||||||
|
|
||||||
|
#### 响应示例
|
||||||
|
成功:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"data": {
|
||||||
|
"ciphertext": "加密后的响应报文"
|
||||||
|
},
|
||||||
|
"message": "成功"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
解密后示例:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"out_biz_no": "batch_001",
|
||||||
|
"trade_no": "7251449503000383499",
|
||||||
|
"status": "success",
|
||||||
|
"download_url": "https://oss.example.com/openapi_7251449503000383499.zip",
|
||||||
|
"zip_password": "123456"
|
||||||
|
}
|
||||||
|
```
|
||||||
Loading…
Reference in New Issue