黔彩收银渠道商接入规范_进件
v1.1.7
修订记录
日期 | 描述 | 作者 | 版本号 |
---|---|---|---|
2025-06-20 | 1.【商户进件结果通知】 添加{wxMerId}微信商户号和{alipayMerId}支付宝商户号 |
王松乐 | V1.1.7 |
2025-05-07 | 1.【商户进件消息主题】 补充{mccName},{provName},{cityName},{areaName}四个字段 |
王松乐 | V1.1.6 |
2025-04-29 | 1.【商户进件消息主题】 追加{busRange}经营范围字段和{stlD1Rate}D1提现手续费率字段;2. 【商户进件结果通知】 追加{reportStatus}报备状态字段; |
王松乐 | V1.1.5 |
2025-04-23 | 1.【修改结算卡消息主题】追加{materials} 图片素材字段;2.完善 【素材下载接口】 响应结构描述;3.订阅消息报文结构追加{channelIspCode}和{channelAppCode}字段 |
王松乐 | V1.1.4 |
2025-03-26 | 1.【商户进件消息主题】追加证件类型/非法人对私结算卡信息 等字段,追加{stlBank} 结算银行字段;2.【商户进件结果通知】追加 {auditType} 审核类型字段; 3.作废 协议签约开户主题 ,改用H5签约模式 |
王松乐 | V1.1.3 |
2025-02-25 | 1.【商户进件消息主题】完善{operType} 字段枚举;2.【商户进件结果通知】追加 {signH5Url} 签约地址参数;3.追加【 商户签约结果通知接口 】;4.所有异步通知接口追加 {topicBizId} 参数 |
王松乐 | V1.1.2 |
2025-02-17 | 追加消息订阅事件结果校验接口 ,”黔彩收银进件订阅接口”追加{notifyCheckUrl} 消息事件校验地址参数 |
王松乐 | V1.1.1 |
2024-11-22 | 开发版 | 王松乐 | V1.1.0 |
2024-10-22 | 初版 | 王松乐 | V1.0.0 |
背景
本文档形成的目的是明确黔彩支付结算中心与第三方聚合支付渠道商的接入规范,结算中心负责收集各个黔彩终端商户收银进件素材,形成黔彩终端商户进件素材中心,其它第三方合作渠道商通过消息订阅的方式实时获取商户进件数据,待报备/审核完成后通知黔彩结算中心进件结果。
接入规范
- 通信协议:HTTPS
- 报文格式:JSON
- 编码格式:UTF-8
- 内容类型:application/json
- SDK集成工具:该SDK封装了登录认证、请求加密、加签/验签、数据处理等能力,可简化系统集成工作,SDK下载地址(推荐最版本):
报文协议
网络传输采用SSL加密协议,双方互换RSA公钥,接口报文采用AES算法进行加密,HTTP请求方法包括POST和GET两种,报文内容由公共请求头和请求体参数两部分组成,具体格式如下描述:
公共请求头
属性 | 值 | 必传 | 备注 |
---|---|---|---|
Authorization | Bearer+空格+qcpay_token | 是 | qcpay_tken从登录接口获取 |
Session-Key | 会话密钥(RSA2加密) | 是 | SK从登录接口获取 |
Sign | 报文签名 | 是 | SHA256签名算法 |
代码示例
String secretKey = RSA256.publicKeyEncrypt(this.sessionKey,this.publicKey);
Map<String,String> header = new HashMap<>();
header.put("Session-Key", secretKey);
header.put("Authorization", "Bearer " + this.token);
header.put("Content-Type", "application/json");
POST请求体公共参数
属性 | 值 | 必传 | 备注 |
---|---|---|---|
apiUri | 接口地址 | 是 | 示例/v1.0/plus/release/coupon/bill |
pojo | Any | 业务参数,具体请看服务接入规范 |
格式包括JSON对象(需要排序)、String、Array、Number… |
timestamp | 时间戳 | 是 | System.currentTimeMillis() |
GET请求公共参数
属性 | 值 | 必传 | 备注 |
---|---|---|---|
apiUri | 接口地址 | 是 | 示例/v1.0/plus/bind/card/record/list |
equal | Any | 业务参数,具体请看服务接入规范 |
格式包括JSON对象(需要排序)、String、Array、Number… |
timestamp | 时间戳 | 是 | System.currentTimeMillis() |
注:Get请求参数为JSON格式,equal若为JSON对象请排序,同时遵循以上加密、加签规则,生成AES密文{params}后再进行URL编码,赋值给query参数,最终的请求路径示例:https://apigw.ktqcy.com/qcpay/unipay-admin/v1.0/plus/bind/card/record/list?query=encodeURI(AES128(params))
Sign签名字段
- 将报文按属性键名进行排序,格式化后生成MD5摘要,在报文摘要拼接上session_key,最后使用SHA256算法计算签名并转大写,放到公共请求头Sign标栏
代码示例
String md5str = DigestUtils.md5Hex(jsonStr);
String sign = DigestUtils.sha256Hex(this.sessionKey + md5str).toUpperCase();
header.put("Sign", sign);
请求体加密
报文格式化后使用AES128算法加密,密钥使用从登录接口返回的会话密钥sessionKey,向量IV固定为1565632248094105,加密后的结果转base64编码
代码示例
// jsonStr 排序后的Json字符串
Base64.encodeBase64String(AES128.encrypt(jsonStr,this.sessionKey,IV));
数据交互规范
身份认证&授权
/**
* appKey 应用名称
* appSecret 应用密钥
*/
public ResultVo<String> login() {
/*设置请求头*/
Map<String,String> header = new HashMap<>();
header.put("Content-Type", "application/x-www-form-urlencoded");
/*设置请求参数*/
long now = System.currentTimeMillis();
String secret = DigestUtils.md5Hex(appKey+appSecret+now);
StringBuilder params = new StringBuilder();
params.append("appKey=").append(appKey)
.append("&appSecret=").append(secret)
.append("×tamp=").append(now);
log.info("request -> {}",params);
String encrypt = RSA256.publicKeyEncrypt(params.toString(),this.publicKey);
String response = httpTemplate.postCipher(this.url, encrypt, header);
return JSON.parseObject(response, new TypeReference<ResultVo<String>>(){});
}
登录交互图
开放服务接入规范
Base URLs:
POST 身份认证&授权
POST /unipay-auth/v1.0/open-src/qcpay/auth
数据传输加密规则
请求报文使用黔彩结算平台的网关公钥进行加密,加密算法RSA256,编码UTF-8
Body 请求参数
appKey: 应用名称
appSecret: 应用密钥
timestamp: 当时毫秒时间戳
请求参数
名称 | 位置 | 类型 | 必选 | 中文名 | 说明 |
---|---|---|---|---|---|
body | body | object | 否 | none | |
» appKey | body | string | 是 | none | |
» appSecret | body | string | 是 | 需特殊处理,处理规则:MD5(appKey+appSecret+timestamp) | |
» timestamp | body | integer | 否 | none |
返回示例
返回结果
状态码 | 状态码含义 | 说明 | 数据模型 |
---|---|---|---|
200 | OK | 成功 | Inline |
返回数据结构
状态码 200
名称 | 类型 | 必选 | 约束 | 中文名 | 说明 |
---|---|---|---|---|---|
» status | boolean | true | none | none | |
» code | integer | true | none | none | |
» msg | string | true | none | none | |
» data | object | true | none | none | |
»» appId | string | true | none | 应用ID | none |
»» session_key | string | true | none | 会话密钥 | 该会话密钥是后期通信双方报文加解密的密钥,时效性与令牌qcpay_token一致,请定时刷新 |
»» qcpay_token | string | true | none | 黔彩支付令牌 | 存在时效性,建议业务系统定时刷新该令牌,以免过期,令牌无状态,可并行使用 |
»» qcpay_expire | string | true | none | 黔彩支付令牌有效时间 | none |
»» refresh_token | string | false | none | 刷新令牌 | 可选 |
»» refresh_expire | string | false | none | 刷新令牌有效时间 | 可选 |
POST APOS01 - 黔彩收银进件订阅接口
说明:同一个消息主题最多支持3个消费者同时订阅(即支持3个不同的推送地址),消息只能被一个消费者接收,若接收失败会尝试推送其它消费者
POST /unipay-juhe/v1.0/pos-entry/pos/subscribe/insert
Body 请求参数
{
"apiUri": "/v1.0/pos-entry/pos/subscribe/insert",
"pojo": {
"channelIspCode": "GT",
"channelAppCode": "QCYPOS",
"topicId": "801301",
"notifyUrl": "string",
"notifyCheckUrl": "String"
},
"timestamp": 1726223571000
}
请求参数
名称 | 位置 | 类型 | 必选 | 中文名 | 说明 |
---|---|---|---|---|---|
body | body | object | 否 | none | |
» pojo | body | object | 是 | 参数对象 | none |
»» channelIspCode | body | string | 是 | 聚合渠道商编码 | 由黔彩结算中心统一分配 |
»» channelAppCode | body | string | 是 | 聚合渠道商支付产品编码 | 由渠道商自由定义,最大长度24个字符 |
»» topicId | body | string | 是 | 订阅主题ID | 枚举: 【801301】 普通商户进件资料消息主题 【801302】 企业用户协议签约开户消息主题 【801303】 聚合渠道商短信发送消息主题 【801304】 修改结算卡消息主题 |
»» notifyUrl | body | string | 是 | 订阅通知地址 | 订阅消息会实时推送到该通知地址 |
»» notifyCheckUrl | body | string | 是 | 消息事件校验地址 | 当因网络异常导致消息推送状态未知时,通过此接口地址矫正消息同步状态 |
返回示例
返回结果
状态码 | 状态码含义 | 说明 | 数据模型 |
---|---|---|---|
200 | [OK] | 成功 | Inline |
返回数据结构
状态码 200
名称 | 类型 | 必选 | 约束 | 中文名 | 说明 |
---|---|---|---|---|---|
» status | boolean | true | none | 响应状态 | none |
» code | integer | true | none | 状态码 | 20000成功,其它均失败 |
» msg | string | true | none | 响应描述 | none |
» data | object | true | none | 响应数据 | 密文 |
»» topicId | String | true | none | 订阅主题ID | none |
»» consumerSrvId | String | true | none | 消费者服务ID | 可通过该ID可对订阅地址进行查询或删除 |
»» timestamp | Number | true | none | 交易时间 | 时间戳 |
GET APOS02 - 黔彩收银进件订阅记录查询接口
GET /unipay-juhe/v1.0/pos-entry/pos/subscribe/page?query=
query 请求参数
{
"apiUri": "/v1.0/pos-entry/pos/subscribe/page",
"equal": {
"topicId": "801301", //可选
"consumerSrvId": "123456" //可选
},
"timestamp": 1726223571000
}
请求参数
名称 | 位置 | 类型 | 必选 | 中文名 | 说明 |
---|---|---|---|---|---|
body | body | object | 否 | none | |
» equal | url | object | 是 | 参数对象 | none |
»» topicId | body | string | 否 | 订阅主题ID | 枚举: 【801301】 普通商户进件资料消息主题 【801302】 企业用户协议签约开户消息主题 【801303】 聚合渠道商短信发送消息主题 【801304】 修改结算卡消息主题 |
»» consumerSrvId | body | string | 否 | 消费者服务ID | 可查询某一条订阅记录 |
返回示例
{
"code": 20000,
"msg": "success",
"data": [
{
"consumerSrvId": '123',
"channelIspCode": 'GT',
"channelAppCode": 'QCYPOS',
"topicId": '801301',
"notifyUrl": "https",
"activeStatus": 1,
"postTime": 1726223571000
}
]
}
返回数据结构
状态码 200
名称 | 类型 | 必选 | 约束 | 中文名 | 说明 |
---|---|---|---|---|---|
» status | boolean | true | none | 响应状态 | none |
» code | integer | true | none | 状态码 | 20000成功,其它均失败 |
» msg | string | true | none | 响应描述 | none |
» data | Array | true | none | 响应数据 | 密文 |
»» consumerSrvId | string | true | none | 消费者服务ID | 可通过该ID可对订阅地址进行更新或删除 |
»» channelIspCode | string | true | none | 聚合渠道商编码 | none |
»» channelAppCode | string | true | none | 聚合渠道商支付产品编码 | none |
»» topicId | string | true | none | 订阅主题ID | none |
»» notifyUrl | string | true | none | 订阅通知地址 | none |
»» activeStatus | string | true | none | 可用状态 | 枚举: 【1】 可用 【2】 不可用 |
»» postTime | integer | true | none | 创建时间戳 | none |
POST APOS03 - 黔彩收银进件订阅批量删除接口
POST /unipay-juhe/v1.0/pos-entry/pos/subscribe/delete
Body 请求参数
{
"apiUri": "/v1.0/pos-entry/pos/subscribe/delete",
"pojo": ["100","101"],
"timestamp": 1726223571000
}
请求参数
名称 | 位置 | 类型 | 必选 | 中文名 | 说明 |
---|---|---|---|---|---|
body | body | object | 否 | none | |
» pojo | body | Array | 是 | 消费者服务ID数组 | 对应字段{consumerSrvId} |
返回示例
返回结果
状态码 | 状态码含义 | 说明 | 数据模型 |
---|---|---|---|
200 | [OK] | 成功 | Inline |
返回数据结构
状态码 200
名称 | 类型 | 必选 | 约束 | 中文名 | 说明 |
---|---|---|---|---|---|
» status | boolean | true | none | 响应状态 | none |
» code | integer | true | none | 状态码 | 20000成功,其它均失败 |
» msg | string | true | none | 响应描述 | none |
» data | object | true | none | 响应数据 | boolean值 |
POST APOS04 - 进件素材查询接口
POST /unipay-juhe/v1.0/pos-entry/pos/material/page
Body 请求参数
{
"apiUri": "/v1.0/pos-entry/pos/material/page"
"equal": {
"topicBizId": "1234567890",
"srcFlag": 1
},
"timestamp": 1726223571000
}
请求参数
名称 | 位置 | 类型 | 必选 | 中文名 | 说明 |
---|---|---|---|---|---|
body | body | object | 否 | none | |
» pojo | body | object | 是 | none | |
»» topicBizId | body | string | 是 | 商户进件业务(批次)号 | none |
»» srcFlag | body | string | 否 | 图片素材标识 | 枚举: 1:身份证正面照片 2:身份证反面照片 3:对公上传“开户许可证/印鉴卡”,法人对私和非法人对私须上传“结算卡正面照” 4:营业场所门头照 5:营业场所内景照 6:补充材料① 7:补充材料② 8:补充资料③(手持结算卡照片) 9:事业单位证明函照片 10:补充材料⑤ 12:营业执照 13:非法人对私身份证正面照 14:非法人对私身份证反面照 15:非法人对私上传的授权书 16:结算人站门头照(储备字段无需处理) 17:非法人授权结算书合影 18:收银台照 19:结算人收银台照 20:入网协议照① 21:入网协议照② 22:入网协议照③ 23:入网协议照④ 24:入网协议照⑤ 25:入网协议照⑥ 26:入网协议照⑦ 27:入网协议照⑧ 28:入网协议照⑨ 29:入网协议照⑩ 35:入网协议照⑪ |
返回示例
{
"code": 20000,
"msg": "success",
"data": [
{
"mchId": '123',
"topicBizId": '1234567890',
"merId": '60000001024626',
"srcUrl": 'https://obs***',
"srcFlag": 1,
"postTime": 1726223571000
}
]
}
返回数据结构
状态码 200
名称 | 类型 | 必选 | 约束 | 中文名 | 说明 |
---|---|---|---|---|---|
» status | boolean | true | none | 响应状态 | none |
» code | integer | true | none | 状态码 | 20000成功,其它均失败 |
» msg | string | true | none | 响应描述 | none |
» data | Array | true | none | 响应数据 | 密文,任意类型:Object/Array/String/Boolean |
»» tradeStatus | integer | true | none | 交易状态 | 1处理中,2成功,3失败 |
»» tradeMsg | string | true | none | 交易描述 | none |
»» tradeTime | integer | true | none | 交易时间 | 时间戳 |
»» mchId | string | true | none | 黔彩商户进件标识 | none |
»» topicBizId | string | true | none | 商户进件业务(批次)号 | none |
»» merId | string | true | none | 商户号 | none |
»» srcUrl | string | true | none | 图片素材下载地址 | none |
»» srcFlag | integer | true | none | 图片素材标识 | none |
»» postTime | integer | true | none | 素材上传时间戳 | none |
POST APOS05 - 素材下载接口
GET /unipay-juhe/v1.0/pos-entry/material/download?query=encodeURI(AES(素材路径))
请求参数
名称 | 位置 | 类型 | 必选 | 中文名 | 说明 |
---|---|---|---|---|---|
body | body | object | 否 | none | |
» query | body | object | 是 | 素材路径 | AES加密后再进行URL编码 |
返回示例
{
"code": 20000,
"msg": "success",
"data": {
"imageUrl": '/app/designForm/aaaimage_1745308957911.png',
"contentType": 'image/png',
"contentLength": 21500,
"base64Image": 'abc...',
}
}
返回数据结构
状态码 200
名称 | 类型 | 必选 | 约束 | 中文名 | 说明 |
---|---|---|---|---|---|
» status | boolean | true | none | 响应状态 | none |
» code | integer | true | none | 状态码 | 20000成功,其它均失败 |
» msg | string | true | none | 响应描述 | none |
» data | Object | true | none | 响应数据 | 密文,任意类型:Object/Array/String/Boolean |
»» imageUrl | string | true | none | 素材路径 | 原样返回 |
»» contentType | string | true | none | MIME类型 | 示例:image/png |
»» contentLength | integer | true | none | 素材大小 | 字节 |
»» base64Image | string | true | none | 图片base64编码 | none |
订阅主题内容
消息推送报文规范
- 通信协议:HTTPS
- HTTP方法:POST
- 内容类型:text/plain
- 报文格式:JSON
- 报文加密:RSA256
- 签名算法:SHA256withRSA
- 编码格式:UTF-8
公共请求头
属性 | 值 | 必传 | 备注 |
---|---|---|---|
Sign | 报文签名 | 是 | SHA256WithRSA签名算法 |
报文签名/加密方式
与交易类请求报文的加签加密方式有所不同,进件请求报文转JSON串并按字母排序,将该JSON串直接采用RSA加签、加密后再上送给渠道商,渠道商接收到报文后强烈建议做签名校验,以保证数据来源的真实性和完整性,否则损失由接收方负责。
POST 商户进件消息主题【801301】
推送消息内容(密文)
{
topicId: "订阅主题ID",
consumerSrvId: "消费者ID",
channelIspCode: "渠道商编码",
channelAppCode: "渠道商产品编码",
topicBizId: "商户进件业务(批次)号(每次进件批次号唯一)",
timestamp: "请求时间戳",
data: {
mchId: '黔彩商户进件标识',
operType: '1新增(首次提交),2驳回新增(驳回后再次提交),3变更',
loginMobile: '登录手机号',
merId: '商户号(首次进件时渠道商返回的商户号,在变更或驳回新增时若存在就上送)',
busName: '商户名称,与营业执照、登记许可证、事业单位法人证书名一致',
busRange: '经营范围',
refName: '商户简称(建议输入市+名称+主营)',
licenseNo: '营业执照号',
busStartDate: '营业执照有效期开始日期(格式YYYYMMDD)',
busEndDate: '营业执照有效期结束日期(格式YYYYMMDD,永久传"长期")',
busType: '主体类型(1个体工商户 2企业 3政府及事业单位 5其他机构组织)'
mccCode: '行业类别码,二级MCC目录对应行业编号',
mccName: '行业类别名称',
provId: '省编码',
provName: '省名称',
cityId: '市编码',
cityName: '市名称',
areaId: '区县编码',
areaName: '区县名称',
custAddr: '经营地址',
custName: '经营者姓名',
idCardType: '法人证件类型:0身份证,1护照,2港澳居民往来内地通行证(回乡证),3台湾居民',
idCardNo: '经营者身份证号码',
idCardValidFrom: '经营者身份证有效期开始日期(格式YYYYMMDD)',
idCardValidUntil: '经营者身份证有效期结束日期(格式YYYYMMDD,永久传"长期")',
custMobile: '经营者手机号,与协议签约手机号一致',
checkCode: '验证码(协议签约场景上送)',
terminalType: '报备产品类型(0全产品 1扫码 2刷卡)',
canRefund: '是否支持退款(0否,1是)',
longitude: '商户经营地址所在经度,小数点后保留5位',
latitude: ' 商户经营地址所在纬度,小数点后保留5位',
stlBank: {
accountType: '账户类型(01 对公 02法人对私 03非法人对私)',
accountName: '结算户名(对私默认为持卡人姓名)',
accountNo: '结算账号',
bankCode: '开户行(银行缩写)',
branchName: '支行名称',
bankNo: '开户行银行号'
stlType: '结算类型( 1为T1结算,2为D1结算)',
stlRate: '结算(提现)手续费率,单位%',
idCardType: '非法人对私结算人证件类型:0身份证,1护照,2港澳居民往来内地通行证(回乡证),3台湾居民',
idCardNo: '非法人对私结算人证件号',
idCardValidFrom: '非法人对私结算人证件有效期开始日期(格式YYYYMMDD)',
idCardValidUntil: '非法人对私结算人证件有效期结束日期(格式YYYYMMDD)',
},
entryPlus: {
wxDebitRate: '0.3%/微信借记卡费率(单位%,支持小数点后三位)',
wxCreditRate: '0.3%/微信贷记卡费率(单位%,支持小数点后三位)',
alipayRate: '0.3%/支付宝扣率(单位%,支持小数点后三位)',
unionpayDebitRate0: '0.3%/银联扫码借记卡扣率小于1000费率(单位%,支持小数点后三位)',
unionpayDebitRate1: '0.55%/银联扫码借记卡扣率大于1000费率(单位%,支持小数点后三位)',
unionpayCreditRate0: '0.3%/银联扫码贷记卡扣率小于1000费率(单位%,支持小数点后三位)',
unionpayCreditRate1: '0.55%/银联扫码贷记卡扣率大于1000费率(单位%,支持小数点后三位)',
posDebitRateY: '0.4%/借记卡优惠类结算费率(单位%,支持小数点后三位)',
posDebitRateB: '0.5%/借记卡标准类结算费率(单位%,支持小数点后三位)',
posCreditRateY: '0.5%/贷记卡优惠类结算费率(单位%,支持小数点后三位)',
posCreditRateB: '0.55%/贷记卡标准类结算费率(单位%,支持小数点后三位)',
posDebitAmtY: '1800/借记卡优惠类消费封顶值(单位分)',
posDebitAmtB: '2000/借记卡标准类消费封顶值(单位分)',
posRateM: '0.3%/免签免密结算费率( 单位%,支持小数点后三位)',
posRateS: '0.3%/刷卡闪付结算费率( 单位%,支持小数点后三位)',
stlD1Rate: '0%/D1提现手续费率(单位%,支持小数点后三位)'
},
materials: [
{
"mchId": '黔彩商户进件标识',
"topicBizId": '商户进件业务(批次)号',
"srcUrl": '进件图片下载地址',
"srcFlag": "素材标识",
}
]
}
}
同步应答内容(密文)
{
code: '响应码(000000代表成功,其余均为失败)',
msg: '响应消息'
}
POST 协议签约开户主题【801302】(已作废,请使用H5签约模式)
推送消息内容(密文)
{
topicId: "订阅主题ID",
consumerSrvId: "消费者ID",
topicBizId: "商户进件业务(批次)号",
channelIspCode: "渠道商编码",
channelAppCode: "渠道商产品编码",
timestamp: "请求时间戳",
data: {
loginMobile: '登录手机号',
busName: '商户注册名称(同进件时商户名称或营业执照主体名称)',
identType: '证件类型(8企业营业执照、B港澳居民往来内地通行证、C台湾居民来往大陆通行证、H事业单位法人证书、J社会团体登记证书、N企业统一社会信用代码)',
identNo: '证件号码',
licenseNo: '营业执照号',
custMobile: '协议签约开户手机号',
contactPhone: '企业(单位)联系电话',
custAddr: '企业(单位)地址',
custName: '法人名称',
idCardNo: '法人身份证号',
accountName: '结算户名(默认结算人姓名)',
accountNo: '结算卡号',
accIdCardNo: '结算人身份证号'
}
}
同步应答内容(密文)
{
code: '响应码(000000代表成功,其余均为失败)',
msg: '响应消息'
}
POST 发送短信消息主题【801303】
推送消息内容(密文)
{
topicId: "订阅主题ID",
consumerSrvId: "消费者ID",
topicBizId: "商户进件业务(批次)号",
channelIspCode: "渠道商编码",
channelAppCode: "渠道商产品编码",
timestamp: "请求时间戳",
data: {
smsBizType: '短信业务类型(0协议签约(开户后方可调用)、1身份认证)',
loginMobile: '登录手机号',
idCardNo: '身份证号码',
custMobile: '协议签约开户手机号',
canSmsVoice: '是否发送语音(0否,1是)'
}
}
同步应答内容(密文)
{
code: '响应码(000000代表成功,其余均为失败)',
msg: '响应消息'
}
POST 修改结算卡消息主题【801304】
推送消息内容(密文)
{
topicId: "订阅主题ID",
consumerSrvId: "消费者ID",
topicBizId: "商户进件业务(批次)号",
channelIspCode: "渠道商编码",
channelAppCode: "渠道商产品编码",
timestamp: "请求时间戳",
data: {
merId: '商户号',
mchId: '黔彩商户进件标识',
accountType: '账户类型(01 对公 02法人对私 03非法人对私)',
accountName: '结算户名(对私默认持卡人姓名)',
accountNo: '结算卡号',
bankCode: '开户行(银行缩写)',
branchName: '支行名称',
bankNo: '开户行银行号',
idCardType: '结算人证件类型:0身份证,1护照,2港澳居民往来内地通行证(回乡证),3台湾居民',
idCardNo: '结算人证件号',
idCardValidFrom: '结算人身份证有效期开始日期(格式YYYYMMDD)',
idCardValidUntil: '结算人身份证有效期结束日期(格式YYYYMMDD,永久传"长期")',
materials: [
{
"mchId": '黔彩商户进件标识',
"topicBizId": '商户进件业务(批次)号',
"srcUrl": '进件图片下载地址',
"srcFlag": "素材标识",
}
]
}
}
同步应答内容(密文)
{
code: '响应码(000000代表成功,其余均为失败)',
msg: '响应消息'
}
POST 消息事件校验接口
当消息推送异常,推送结果未知的情况下,通过此接口矫正消息通知状态,比如网络异常等因素
推送消息内容(密文)
{
topicId: "订阅主题ID",
topicBizId: "商户进件业务(批次)号",
channelIspCode: "渠道商编码",
channelAppCode: "渠道商产品编码",
consumerSrvId: "消费者ID",
timestamp: "请求时间戳"
}
同步应答内容(密文)
{
code: '响应码(000000代表业务受理成功,111111代表消息未送达,如网络异常导致消息没有推送给渠道服务商,其余均为业务受理失败)',
msg: '响应描述,失败时请说明原因'
}
商户进件结果通知
注:聚合渠道商调用黔彩通知地址,需要有失败重试机制,可参考微信支付的重试机制,不能少于3次,重试累计时间不能小于8小时
POST APOS06 - 商户进件审核/报备结果通知接口
POST /unipay-juhe/v1.0/pos-entry/pos/entry/notify
Body 请求参数示例
{
"apiUri": "/v1.0/pos-entry/pos/entry/notify",
"pojo": {
"topicBizId": "123456",
"mchId": "123456",
"merId": "60000001024626",
"wxMerId": "523234234",
"alipayMerId": "264745523",
"auditType": 0,
"auditStatus": 1,
"reportStatus": 1,
"originStatus": "000000",
"originNotes": "审核通过",
"wxAuthUrl": "wx:auth**",
"alipayAuthUrl": "aliyun:auth**",
"signH5Url": "https://(可选)",
"contractNo": '合同编号(可选)'
},
"timestamp": 1726223571000
}
请求参数
名称 | 位置 | 类型 | 必选 | 中文名 | 说明 |
---|---|---|---|---|---|
body | body | object | 否 | none | |
» pojo | body | object | 是 | 参数对象 | none |
»» topicBizId | body | string | 是 | 商户进件业务(批次)号 | 进件消息推送时会上送该字段 |
»» mchId | body | string | 是 | 黔彩商户进件标识 | 进件消息推送时会上送该字段 |
»» merId | body | string | 是 | 商户号 | 聚合渠道商分配的商户号 |
»» wxMerId | body | string | 是 | 微信商户号 | 微信原始商户号 |
»» alipayMerId | body | string | 是 | 支付宝商户号 | 支付宝原始商户号 |
»» auditType | body | integer | 是 | 审核类型 | 0首次进件,2信息变更,4结算卡修改(有独立的通知接口,二选一) |
»» auditStatus | body | integer | 是 | 进件审核状态 | 枚举: 【1】 审核成功 【2】 审核失败 |
»» reportStatus | body | integer | 是 | 报备状态 | 枚举: 【1】 报备成功 【2】 报备失败 |
»» originStatus | body | string | 是 | 聚合渠道商原审核/报备状态码 | 失败时必填 |
»» originNotes | body | string | 是 | 聚合渠道商原审核/报备结果描述 | 失败时必填 |
»» wxAuthUrl | body | string | 是 | 微信认证地址 | 申请成功时必填 |
»» alipayAuthUrl | body | string | 是 | 支付宝认证地址 | 申请成功时必填 |
»» signH5Url | body | string | 否 | H5签约地址 | 审核成功时返回,若无签约流程可不填 |
»» contractNo | body | string | 否 | 合同编号 | 可选 |
返回示例
返回结果
状态码 | 状态码含义 | 说明 | 数据模型 |
---|---|---|---|
200 | [OK] | 成功 | Inline |
返回数据结构
状态码 200
名称 | 类型 | 必选 | 约束 | 中文名 | 说明 |
---|---|---|---|---|---|
» status | boolean | true | none | 响应状态 | none |
» code | integer | true | none | 状态码 | 20000成功,其它均失败 |
» msg | string | true | none | 响应描述 | none |
POST APOS09 - 商户签约结果通知接口
POST /unipay-juhe/v1.0/pos-entry/pos/sign/notify
Body 请求参数示例
{
"apiUri": "/v1.0/pos-entry/pos/sign/notify",
"pojo": {
"topicBizId": "123456",
"mchId": "123456",
"merId": "60000001024626",
"signStatus": 1,
"originStatus": "000000",
"originNotes": "签约成功"
},
"timestamp": 1726223571000
}
请求参数
名称 | 位置 | 类型 | 必选 | 中文名 | 说明 |
---|---|---|---|---|---|
body | body | object | 否 | none | |
» pojo | body | object | 是 | 参数对象 | none |
»» topicBizId | body | string | 是 | 商户进件业务(批次)号 | 进件消息推送时会上送该字段 |
»» mchId | body | string | 是 | 黔彩商户进件标识 | 进件消息推送时会上送该字段 |
»» merId | body | string | 是 | 商户号 | 由聚合渠道商分配的商户号 |
»» signStatus | body | integer | 是 | 商户签约状态 | 枚举: 【1】 签约成功 【2】 签约失败 |
»» originStatus | body | string | 是 | 聚合渠道商原签约状态码 | 失败时必填 |
»» originNotes | body | string | 是 | 聚合渠道商原签约结果描述 | 失败时必填 |
返回示例
返回结果
状态码 | 状态码含义 | 说明 | 数据模型 |
---|---|---|---|
200 | [OK] | 成功 | Inline |
返回数据结构
状态码 200
名称 | 类型 | 必选 | 约束 | 中文名 | 说明 |
---|---|---|---|---|---|
» status | boolean | true | none | 响应状态 | none |
» code | integer | true | none | 状态码 | 20000成功,其它均失败 |
» msg | string | true | none | 响应描述 | none |
POST APOS07 - 商户认证结果通知接口
POST /unipay-juhe/v1.0/pos-entry/pos/auth/notify
Body 请求参数示例
{
"apiUri": "/v1.0/pos-entry/pos/auth/notify",
"pojo": {
"topicBizId": "123456",
"mchId": "123456",
"merId": "60000001024626",
"authType": 1
"authStatus": 1,
"originStatus": "000000",
"originNotes": "已授权"
},
"timestamp": 1726223571000
}
请求参数
名称 | 位置 | 类型 | 必选 | 中文名 | 说明 |
---|---|---|---|---|---|
body | body | object | 否 | none | |
» pojo | body | object | 是 | 参数对象 | none |
»» topicBizId | body | string | 是 | 商户进件业务(批次)号 | 进件消息推送时会上送该字段 |
»» mchId | body | string | 是 | 黔彩商户进件标识 | 进件消息推送时会上送该字段 |
»» merId | body | string | 是 | 商户号 | 由聚合渠道商分配的商户号 |
»» authType | body | integer | 是 | 认证类型 | 认证类型:1微信认证,2支付宝认证 |
»» authStatus | body | integer | 是 | 商户认证状态 | 枚举: 【1】 认证成功 【2】 认证失败 |
»» originStatus | body | string | 是 | 聚合渠道商原认证状态码 | 失败时必填 |
»» originNotes | body | string | 是 | 聚合渠道商原认证结果描述 | 失败时必填 |
返回示例
返回结果
状态码 | 状态码含义 | 说明 | 数据模型 |
---|---|---|---|
200 | [OK] | 成功 | Inline |
返回数据结构
状态码 200
名称 | 类型 | 必选 | 约束 | 中文名 | 说明 |
---|---|---|---|---|---|
» status | boolean | true | none | 响应状态 | none |
» code | integer | true | none | 状态码 | 20000成功,其它均失败 |
» msg | string | true | none | 响应描述 | none |
POST APOS08 - 修改结算卡结果通知接口
POST /unipay-juhe/v1.0/pos-entry/pos/update/bankcard/notify
Body 请求参数示例
{
"apiUri": "/v1.0/pos-entry/pos/update/bankcard/notify",
"pojo": {
"topicBizId": "123456",
"mchId": "123456",
"merId": "60000001024626",
"auditStatus": 1,
"originStatus": "000000",
"originNotes": "审核通过"
},
"timestamp": 1726223571000
}
请求参数
名称 | 位置 | 类型 | 必选 | 中文名 | 说明 |
---|---|---|---|---|---|
body | body | object | 否 | none | |
» pojo | body | object | 是 | 参数对象 | none |
»» topicBizId | body | string | 是 | 商户进件业务(批次)号 | 进件消息推送时会上送该字段 |
»» mchId | body | string | 是 | 黔彩商户进件标识 | 进件消息推送时会上送该字段 |
»» merId | body | string | 是 | 商户号 | 由聚合渠道商分配的商户号 |
»» auditStatus | body | integer | 是 | 结算卡审核状态 | 枚举: 【1】 审核成功 【2】 审核失败 |
»» originStatus | body | string | 是 | 聚合渠道商原审核状态码 | 失败时必填 |
»» originNotes | body | string | 是 | 聚合渠道商原审核结果描述 | 失败时必填 |
返回示例
返回结果
状态码 | 状态码含义 | 说明 | 数据模型 |
---|---|---|---|
200 | [OK] | 成功 | Inline |
返回数据结构
状态码 200
名称 | 类型 | 必选 | 约束 | 中文名 | 说明 |
---|---|---|---|---|---|
» status | boolean | true | none | 响应状态 | none |
» code | integer | true | none | 状态码 | 20000成功,其它均失败 |
» msg | string | true | none | 响应描述 | none |
higsoft-rpc-sdk工具
SDK工具使用方法
登录认证
- 将公钥publicKey、服务网关gateway、应用名称appKey、应用密钥appSecret替换为实际分配的内容,测试环境与生产环境的键值不一样
- 建议将qcpay_token和session_key在业务系统进行缓存,在失效前定时刷新,该token无状态,可并行使用
代码示例
注:相关业务参数在实际开发中由业务开发人员自行修改,该示例仅做参考
/**
* 获取黔彩结算中心qcpay_token
*/
public void loadQcpayToken() {
if (config.isEnable()) {
ResultVo<String> vo = HigsoftRPC.RPC(config.getPublicKey())
.builder()
.setGateway(config.getGateway())
.setService("unipay-auth")
.setApi("/v1.0/open-src/qcpay/auth")
.setAppKey(config.getAppKey())
.setAppSecret(config.getAppSecret())
.login();
if (vo == null) {
log.error("qcpay response is null");
return;
}
if (Objects.equals(vo.getCode(),20000)) {
String result = RSA256.privateKeyDecrypt(vo.getData(), config.getPrivateKey());
Map<String,Object> map = JSON.parseObject(result).getInnerMap();
log.info("login result -> {}", map);
cache.setCache("session_key", map.get("session_key"));
cache.setCache("qcpay_token", map.get("qcpay_token"));
} else {
log.error("qcpay error -> {}", vo.getMsg());
}
}
}
POST接口请求示例
注:相关业务参数在实际开发中由业务开发人员自行修改,该示例仅做参考*
public QcpayBizData requestCashDesk(QcpayOrderDto dto) {
String qcpay_token = cache.getCache("qcpay_token").toString();
String session_key = cache.getCache("session_key").toString();
if (StringUtils.isBlank(qcpay_token)) {
throw new BizException("qcpay_token is Null");
}
if (StringUtils.isBlank(session_key)) {
throw new BizException("session_key is Null");
}
dto.setNotifyUrl(config.getPayNotifyUrl());
dto.setSessionKey(session_key);
ResultVo<QcpayBizData> vo = HigsoftRPC.RPC(config.getPublicKey())
.builder(session_key,qcpay_token)
.setGateway(config.getGateway())
.setService("unipay-auth")
.setApi("/v1.0/pos/subscribe/insert")
.setPojo(dto)
.post(QcpayBizData.class);
if (vo == null) {
log.error("qcpay response is null");
throw new BizException("黔彩结算中心响应结果为空");
}
if (!Objects.equals(vo.getCode(),20000)) {
log.error("qcpay error -> {}", vo.getMsg());
throw new BizException(String.valueOf(vo.getCode()), vo.getMsg());
}
return vo.getData();
}
GET列表查询示例
注:相关业务参数在实际开发中由业务开发人员自行修改,该示例仅做参考
public void requestOrderList() {
String qcpay_token = cache.getCache("qcpay_token").toString();
String session_key = cache.getCache("session_key").toString();
if (StringUtils.isBlank(qcpay_token)) {
throw new BizException("qcpay_token is Null");
}
if (StringUtils.isBlank(session_key)) {
throw new BizException("session_key is Null");
}
ResultVo<List<QcpayOrderDto>> vo = HigsoftRPC.RPC(config.getPublicKey())
.builder(session_key,qcpay_token)
.setGateway("https://apigw.ktqcy.com/qcpay")
.setService("unipay-juhe")
.setApi("/v1.0/pos/subscribe/list")
.setQuery("channelIspCode","GT")
.setQuery("activeStatus",1)
.list(QcpayOrderDto.class);
if (Objects.equals(vo.getCode(),20000)) {
log.error("查询成功 -> {}", JSON.toJSONString(vo.getData()));
} else {
log.error("查询失败 -> {}", vo.getMsg());
}
}
GET对象查询示例
注:相关业务参数在实际开发中由业务开发人员自行修改,该示例仅做参考
public void requestOrderPage() {
String qcpay_token = cache.getCache("qcpay_token").toString();
String session_key = cache.getCache("session_key").toString();
if (StringUtils.isBlank(qcpay_token)) {
throw new BizException("qcpay_token is Null");
}
if (StringUtils.isBlank(session_key)) {
throw new BizException("session_key is Null");
}
ResultVo<QcpayOrderDto> vo = HigsoftRPC.RPC(config.getPublicKey())
.builder(session_key,qcpay_token)
.setGateway("https://apigw.ktqcy.com/qcpay")
.setService("unipay-juhe")
.setApi("/v1.0/pos/subscribe/list")
.setQuery("channelIspCode","GT")
.get(QcpayOrderDto.class);
if (Objects.equals(vo.getCode(),20000)) {
log.error("查询成功 -> {}", JSON.toJSONString(vo.getData()));
} else {
log.error("查询失败 -> {}", vo.getMsg());
}
}
ENUM 主题ID枚举{topicId}
枚举 | 说明 | 备注 |
---|---|---|
801301 | 普通商户进件资料消息主题 | 无 |
801302 | 企业用户协议签约开户消息主题 | 无 |
801303 | 聚合渠道商短信发送消息主题 | 无 |
801304 | 修改结算卡消息主题 | 无 |
ENUM 订阅事件状态码枚举{code}
枚举 | 说明 | 备注 |
---|---|---|
000000 | 成功 | 代表业务受理成功 |
111111 | 消息未送达 | 如因网络异常,导致消息没有推送给渠道服务商 |
其它 | 其它状态码均代表业务受理失败 | 无 |