文档类型:调用文档 ## 接口列表 ### 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 | 上报账号 | - **请求示例**: - 明文业务参数:`{"out_biz_no": "order_001", "activity_no": "ACT20260622001", "account": "18666666666", "notify_url": "https://notify.example.com/openapi"}` - 请求体:`{"ciphertext": "加密后的业务报文"}` - **响应示例**: - 异常:`{"code": 401, "message": "Signature verification failed", "reason": "INVALID_SIGNATURE"}` - 成功:`{"code": 200, "data": {"ciphertext": "加密后的响应报文"}, "message": "成功"}` - 解密后:`{"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 | - **响应示例**: - 成功:`{"code": 200, "data": {"ciphertext": "加密后的响应报文"}, "message": "成功"}` - 解密后:`{"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 | 批量任务成功后返回压缩包密码 | - **响应示例**: - 成功:`{"code": 200, "data": {"ciphertext": "加密后的响应报文"}, "message": "成功"}` - 解密后:`{"out_biz_no": "batch_001", "trade_no": "7251449503000383499", "status": "success", "download_url": "https://oss.example.com/openapi_7251449503000383499.zip", "zip_password": "123456"}` ## 认证/加密/签名细节 ### 环境配置 - 测试环境地址:`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" ### 业务参数加密(v1版本) 1. 将业务参数去掉“零”值的参数再由小到大按照字母排序再转成json字符串得到plaintext。 2. 使用应用key将plaintext字符串加密(aes(ECB模式)/sm4(CBC模式))得到加密业务参数ciphertext。 ### 签名规则(请求) 1. 拼接签名字符串:分配给开发者的应用ID + 发送请求的时间 + 加密业务参数。 2. 使用私钥将拼接待签名字符串生成签名字符串。 ### 回调验签 1. 获取header头里面的签名信息。 2. 获取body里面的业务参数data。 3. 将业务参数data去掉“零”值的参数再由小到大按照字母排序再转成json字符串得到plaintext。 4. 使用应用key将plaintext字符串加密(aes/sm4)得到ciphertext。 5. 拼接签名字符串:分配给开发者的应用ID + 发送请求的时间 + ciphertext。 6. 使用应用公钥验签。 ### 请求模式(v1) - Header传:Appid、Timestamp、Sign - Body传:ciphertext ### 响应说明(v1) - 统一采用严格密文响应模式,业务响应数据通过ciphertext返回。 ### 时间戳规则 - 时间格式:yyyy-MM-dd HH:mm:ss - 请求时间与服务端时间误差不能超过3分钟。 ### 公共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 | ### 公共请求参数 | 字段名称 | 类型 | 描述 | 示例值 | | --- | --- | --- | --- | | ciphertext | string | 请求业务参数加密串 | 详见SDK示例 | ### 公共响应参数 | 字段名称 | 类型 | 描述 | | --- | --- | --- | | 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 | 明文参数格式错误 | 请检查密文解密后的业务报文 |