1 流程介绍
1.1 业务流程时序图
2 微信非税平台提供的接口(车主服务后台)
2.1 用户状态查询
2.2 用户入场通知
2.3 申请扣款
2.4 返回码说明
3 用户授权/开通
3.1 小程序跳转接口调用请求说明
3.2 H5跳转接口调用请求说明
3.3 APP跳转接口调用请求说明
4 委办局提供的接口
4.1 车牌状态变更通知
4.2 支付结果通知
# 1 流程介绍
# 1.1 业务流程时序图
注:
步骤3:调用入场通知接口(针对先出场后扣费场景使用,如果是先扣款后出场的场景不需要调用该接口,如想获取入场车主的状态,可通过用户状态查询接口获取 ),该接口用于商户注册接收场内用户状态变化,该接口同时返回用户状态。
步骤7:代扣申请仅返回受理结果,不代表最终扣款状态。如受理返回系统异常或网络超时,则用原请求参数重试即可,一个商户订单号对应一笔支付单。
步骤10:受理成功的订单,由于用户零钱和银行卡没钱会导致最终扣款失败,这里商户侧可联系微信的运营同学去申请微信的垫资能力(针对用户零钱和银行卡没钱这种情况,微信侧先行垫资并催缴用户还款)
# 2 微信非税平台提供的接口(车主服务后台)
# 2.1 用户状态查询
应用场景
在停车场、高速、加油等场景下,商户需获取用户车主服务状态/需要关联车主服务。本接口,会查询用户是否开通、授权、有欠费或黑名单用户情况,并将对应的用户状态进行返回。
流程介绍
- 调用用户状态查询api获取当前用户车主状态,如果当前用户车主状态异常(如有欠费(OVERDUE),未授权(UNAUTHORIZED)),接口同步返回跳转路径(path字段),商户侧需根据步骤2引导用户进入车主服务进行相关操作;如果当前用户车主状态正常,不会返回path字段,不需要再引导用户进入车主服务
- --小程序,APP跳转,通过跳转路径(path)调用 ‘用户授权/开通接口api’进入车主小程序的对应页面,用户进行授权/开通的操作
--H5跳转,通过跳转路径(path)调用 ‘用户授权/开通接口api’进入车主H5对应的页面,用户进行授权/开通操作
- 返回商户小程序,APP或H5页面后再次调用用户状态查询api确认用户最新车主状态及车牌信息
https://api.weixin.qq.com/nontax/vehicle/querystate?access_token=$AccessToken
请求参数
字段名 | 类型 | 必填 | 说明 |
---|---|---|---|
appid | string | 是 | appid |
bank_id | string | 否 | 银行id(由微信非税平台分配的全局唯一id),不指定时在已配置的银行列表中随机选择;不填时默认生产环境,测试环境需填上 |
bank_account | string | 否 | 清分银行账号(不使用清分机制的不用填) |
mch_id | string | 否 | 指定资金结算到mch_id。只能结算到 bank_id 下绑定的mch_id。不填时自动从 bank_id 下绑定的 mch_id 选择一个。 |
region_code | string | 是 | 行政区划代码 |
trade_scene | string | 是 | 委托代扣的交易场景值,目前支持 : PARKING:车场停车场景 ; PARKING SPACE 车位停车场景; HIGHWAY 高速场景; BRIDGE 路桥场景;该值会向微信用户进行展示 |
jump_scene | string | 否 | 商户跳转的业务场景,不传默认是小程序,也支持APP和公众号H5跳转APP:通过APP跳转H5:通过公众号H5跳转 |
openid | string | 否 | 用户在商户appid下的唯一标识。openid和车牌号必须选传其中之一 |
plate_number | string | 否 | 车牌号。仅包括省份+车牌,不包括特殊字符。openid和车牌号必须选传其中之一 |
material_info | string | 否 | 用户通过扫码进入商户小程序时所扫的物料码信息 |
channel_type | string | 否 | 高速通道类型,目前可选:ETC、MTC。用户车牌必须具有通道标识时,才允许扣费。当场景值为 HIGHWAY 高速场景时填此字段。 |
返回结果
字段名 | 类型 | 必填 | 说明 |
---|---|---|---|
errcode | int | 是 | 返回码 |
errmsg | string | 否 | 返回码描述 |
user_state | string | 是 | NORMAL:正常用户,已开通车主服务,且已授权访问 PAUSED:已暂停车主服务 OVERDUE: 用户已开通车主服务,但欠费状态。提示用户还款,请跳转到车主服务 UNAUTHORIZED:用户未授权使用当前业务,或未开通车主服务。请跳转到授权接口 |
openid | string | 否 | 用户在商户appid下的唯一标识,当用户入驻车主平台时进行返回 |
path | string | 否 | 跳转车主小程序的页面路径,如果该参数返回不为空,商户侧需调用‘用户授权/开通接口’引导用户进入车主小程序进行授权/开通的操作,‘用户授权/开通接口’请查看下面的详细说明; H5跳转同理,需跳转的场景有: -用户状态正常,但无车牌 -用户欠费 -用户未授权 -用户未开通/暂停车主服务 |
plate_number_info | json | 否 | 车牌号列表。仅包括省份+车牌,不包括特殊字符。 注:在PARKING SPACE场景下无返回。 |
authorize_package | json | 否 | 授权参数信息,path不为空时返回,在用户授权/开通时使用 |
示例
{
"appid": "wx5f6e43071809a9dd",
"bank_id": "test_bank_id",
"bank_account": "",
"mch_id": "1900016021",
"region_code" : "440000",
"trade_scene": "PARKING",
"jump_scene": "H5",
"openid": "ont-9vjAcIdSU-LgB7ubALAVJO9U",
"plate_number": "粤B888888",
"material_info": "test_material_info",
"channel_type": "ETC"
}
返回结果
{
"errcode": 0,
"errmsg": "ok",
"user_state": "NORMAL",
"openid": "ont-9vjAcIdSU-LgB7ubALAVJO9U",
"path":
"https:\/\/payapp.weixin.qq.com\/vehicle\/plat\/indextemplate",
"plate_number_info": [
],
"authorize_package": {
"mch_id": "1800004561",
"sub_mch_id": "1900016021",
"appid": "wxc971985892358997",
"sub_appid":
"wx6cc9648de104270d",
"nonce_str": "SwwVkZWoXlIWX7AG2c3ItkklTo138PEO",
"sign_type": "HMAC-SHA256",
"sign":
"67D1B1232C9837E5885216DA349632AD9CE080BBD2D54DF13314260F4CD5D9C8",
"trade_scene": "PARKING",
"openid": "ooaLEwgrB9PRsx-IdsJxEQiKgjbQ",
"sub_openid": "oFkLxtyJswfbex9crZWHGDYG5NIw",
"plate_number": "粤B888888",
"material_info": "test_material_info",
"channel_type": "ETC"
}
}
## 2.2 用户入场通知
**应用场景**
在停车场场景下,如用户已加入车主平台,则进行入场通知;如用户已经欠费,会发送用户欠费入场通知。本接口,会查询用户是否有欠费或黑名单用户情况,并将对应的用户状态进行返回。
说明
本接口主要用于先出场后扣费场景下,微信侧实时同步用户车主状态给商户侧,用于维护车主用户白名单。如商户侧是先扣费后出场场景,不需要调用该接口,用户入场时可通过用户状态查询接口获取当前用户的车主状态即可
https://api.weixin.qq.com/nontax/vehicle/entrancenotify?access_token=$AccessToken
请求参数
字段名 | 类型 | 必填 | 说明 |
---|---|---|---|
appid | string | 是 | appid |
bank_id | string | 否 | 银行id(由微信非税平台分配的全局唯一id),不指定时在已配置的银行列表中随机选择;不填时默认生产环境,测试环境需填上 |
bank_account | string | 否 | 清分银行账号(不使用清分机制的不用填) |
mch_id | string | 否 | 指定资金结算到mch_id。只能结算到 bank_id 下绑定的mch_id。不填时自动从 bank_id 下绑定的 mch_id 选择一个。 |
region_code | string | 是 | 行政区划代码 |
trade_scene | string | 是 | 委托代扣的交易场景值,目前支持 : PARKING:车场停车场景 ; PARKING SPACE 车位停车场景; HIGHWAY 高速场景; BRIDGE 路桥场景;该值会向微信用户进行展示 |
scene_info | json | 是 | 场景信息值,格式为json,不同业务场景设置不同的值,具体如后面所列。 |
其中scene_info内部字段如下:
当trade_scene场景为:PARKING(车场停车)时,传如下值
字段名 | 类型 | 必填 | 说明 |
---|---|---|---|
start_time | int | 是 | 即用户进入停车时间(时间戳,单位是秒),该值催缴时会向微信用户进行展示 |
plate_number | string | 是 | 车牌号。仅包括省份+车牌,不包括特殊字符。 |
notify_url | string | 否 | 用于接收车牌状态变更的通知 |
car_type | string | 否 | 停车车辆的类型,可选值:大型车、小型车 |
parking_name | string | 是 | 所在停车场的名称 |
free_time | int | 是 | 免费的时间长。单位为秒 |
返回结果
字段名 | 类型 | 必填 | 说明 |
---|---|---|---|
errcode | int | 是 | 返回码 |
errmsg | string | 否 | 返回码描述 |
user_state | string | 是 | NORMAL:正常状态,用户可以使用车主服务 BLOCKED:异常状态,用户不可以使用车主服务 |
示例
请求参数
{
"appid": "wx5f6e43071809a9dd",
"bank_id": "test_bank_id",
"mch_id": "1900016021",
"region_code" : "440000",
"notify_url": "https://weixin.qq.com",
"trade_scene": "PARKING",
"start_time": 1542351485,
"car_type": "小型车",
"parking_name": "test_parking_name",
"free_time": 1200,
"plate_number": "粤B888888",
"openid": "ont-9vjAcIdSU-LgB7ubALAVJO9U"
}
返回结果
{
"errcode": 0,
"errmsg": "ok",
"user_state": "NORMAL"
}
## 2.3 申请扣款
**应用场景**
委托代扣可应用于定期扣款或需事后扣款以期提高效率的场景。例如高速,停车场等通过用户授权给商户,进行委托扣款的场景。
注:扣费请求首先按签约协议中记录的优先支付方式扣费,否则从可用扣款方式中依次选择扣款。
说明
由于目前车主服务只支持蓝牌,绿牌和黑牌。停车场和高速场景下,商户侧必须在车辆出场时识别车牌类型,非蓝牌,绿牌和黑牌的车辆不能进行车主服务的扣款
https://api.weixin.qq.com/nontax/vehicle/payapply?access_token=$AccessToken
请求参数
字段名 | 类型 | 必填 | 说明 |
---|---|---|---|
appid | string | 是 | appid |
bank_id | string | 否 | 银行id(由微信非税平台分配的全局唯一id),不指定时在已配置的银行列表中随机选择;不填时默认生产环境,测试环境需填上 |
bank_account | string | 否 | 清分银行账号(不使用清分机制的不用填) |
mch_id | string | 否 | 指定资金结算到mch_id。只能结算到 bank_id 下绑定的mch_id。不填时自动从 bank_id 下绑定的 mch_id 选择一个。 |
desc | string | 是 | 描述(服务名称) |
fee | int | 是 | 总金额(单位是分) |
payment_notice_no | string | 否 | 缴费通知书编号(缴费通知书编号和订单号必须二选一。如果没有缴费通知书编号,则填订单号) |
order_no | string | 否 | 订单号。(缴费通知书编号和订单号必须二选一。如果没有缴费通知书编号,则填订单号) |
department_code | string | 是 | 执收单位编码 |
department_name | string | 是 | 执收单位名称 |
payment_notice_type | int | 否 | 通知书类型 |
region_code | string | 否 | 行政区划代码 |
goods_tag | string | 否 | 商品标记,代金券或立减优惠功能的参数,说明详见代金券或立减优惠 |
trade_scene | string | 是 | 委托代扣的交易场景值,目前支持 : PARKING:车场停车场景 PARKING SPACE;车位停车场景 HIGHWAY |
高速场景 BRIDGE 路桥场景该值催缴时会向微信用户进行展示 |scene_info|string|是|场景信息值,格式为json,不同业务场景设置不同的值,具体如后面所列。| |order_id|string|否|订单号,若填了此字段,除appid外其它参数都不用填|
其中scene_info内部字段如下:
当trade_scene场景为:PARKING(车场停车)时,传如下值
字段名 | 类型 | 必填 | 说明 |
---|---|---|---|
start_time | int | 是 | 即用户进入停车时间(时间戳,单位是秒),该值催缴时会向微信用户进行展示 |
end_time | int | 否 | 即用户出停车场时间,(时间戳,单位是秒),该值催缴时会向微信用户进行展示 |
charging_time | int | 是 | 计费的时间长。单位为秒 |
plate_number | string | 是 | 车牌号。仅包括省份+车牌,不包括特殊字符。 |
car_type | string | 否 | 停车车辆的类型,可选值:大型车、小型车 |
parking_name | string | 是 | 所在停车场的名称 |
当trade_scene场景为:PARKING SPACE 时(车位停车),传如下值
字段名 | 类型 | 必填 | 说明 |
---|---|---|---|
start_time | int | 是 | 即用户进入停车时间(时间戳,单位是秒),该值催缴时会向微信用户进行展示 |
end_time | int | 否 | 即用户出停车场时间,(时间戳,单位是秒),该值催缴时会向微信用户进行展示 |
charging_time | int | 是 | 计费的时间长。单位为秒 |
car_type | string | 否 | 停车车辆的类型,可选值:大型车、小型车 |
parking_name | string | 否 | 所在停车位车场的名称 |
openid | string | 是 | 用户在商户appid下的唯一标识 |
space_number | string | 是 | 用户停车的车位编号,仅支持英文+数字 |
当trade_scene场景为:HIGHWAY 时,传如下值
字段名 | 类型 | 必填 | 说明 |
---|---|---|---|
start_time | int | 是 | 即用户进入高速时间(时间戳,单位是秒),该值催缴时会向微信用户进行展示 |
end_time | int | 是 | 即用户出高速时间(时间戳,单位是秒),该值催缴时会向微信用户进行展示 |
plate_number | string | 是 | 车牌号。仅包括省份+车牌,不包括特殊字符。 |
car_type | string | 是 | 车辆的类型,可选值:客车、货车 |
entrance_name | string | 是 | 高速收费入口站的名称 |
exit_name | string | 是 | 高速收费出口站的名称 |
carrying_capacity | string | 否 | 当前车辆核载人数,纯数字 |
carrying_range | string | 否 | 当前车辆核载人数区间,格式数字-数字 |
channel_type | string | 是 | 高速通道类型,目前可选:ETC、MTC。商户扣费前必须确认当前车牌的标识属性,用户车牌必须具有该通道标识时,才允许扣费。 |
当trade_scene场景为:BRIDGE 时,传如下值
字段名 | 类型 | 必填 | 说明 |
---|---|---|---|
start_time | int | 是 | 即用户通过路桥收费站时间(时间戳,单位是秒),该值催缴时会向微信用户进行展示 |
plate_number | int | 是 | 车牌号。仅包括省份+车牌,不包括特殊字符。 |
car_type | string | 否 | 车辆的类型,可选值:大型车、小型车 |
exit_name | string | 是 | 收费出口站的名称,需向用户进行展示。如虎门大桥 |
返回结果
字段名 | 类型 | 必填 | 说明 |
---|---|---|---|
errcode | int | 是 | 返回码 |
errmsg | string | 否 | 返回码描述 |
order_id | string | 是 | 订单号 |
示例
请求参数
{
"appid" : "wx5f6e43071809a9dd",
"bank_id" : "test_bank_id",
"bank_account" : "",
"mch_id" : "1900016021",
"payment_notice_no" : "1111111111",
"department_code" : "222222",
"payment_notice_type" : 1,
"region_code" : "440000",
"department_name" : "测试执收单位名称",
"desc" : "测试desc",
"fee" : 1,
"goods_tag" : "",
"trade_scene" : "PARKING SPACE",
"scene_info" :
{
"start_time": 1542351485,
"charging_time": 3600,
"car_type": "小型车",
"parking_name": "test_parking_name",
"openid": "ont-9vjAcIdSU-LgB7ubALAVJO9U",
"space_number": "D666666"
}
}
返回结果
{
"errcode": 0,
"errmsg": "ok",
"order_id": "AQAAhNw2srPiUjMKDJ7fvb4AAAAA"
}
## 2.4 返回码说明
返回码 | 说明 |
---|---|
9207028 | 当前车牌尚未绑定车主平台 |
9207029 | 用户不符合免密代扣要求,通过用户状态查询接口查询用户状态给用户相应引导 |
9207030 | 校验授权关系失败,调用授权接口完成用户对appid的授权 |
9207031 | 用户支付超出限额 |
9207032 | 支付确认失败,用户的微信号被风控拦截或者用户的微信号被紧急冻结 |
9207033 | 扣款请求超过业务规定时间, 高速场景,ETC通道需要在48小时内,将交易送达 |
9207034 | 扣款请求标识和当前车牌通道标识不一致,高速场景,车牌必须具有对应(ETC或MTC)通道标识标时才可以扣款 |
# 3 用户授权/开通
# 3.1 小程序跳转接口调用请求说明
|接口|wx.navigateToMiniProgram(OBJECT)接口|
使用用户状态查询接口返回的path和authorize_package参数填充path和extraData参数
示例:
wx.navigateToMiniProgram({
appId: 'wxbcad394b3d99dac9',
path: 'pages/route/index',
extraData: {
appid: 'wx426a3015555a46be',
sub_appid:
'wx426a3015555a46b1',
mch_id: '10000098',
sub_mch_id: '10000096',
nonce_str:
'FF1A406564EE70106445',
sign_type:
'HMAC-SHA256',
sign:'EE088059BBC9141264F8D14293AD6C4BB94CEA8C08AA98FBF93E262D445F8FF5',
trade_scene: 'PARKING',
openid:
'oUpF8uMEb4qRXf22hE3X68TekukE'
},
success(res) {
},
fail(res) {
// 未成功跳转到车主小程序
}
})
用户授权完成之后,会跳转回商户小程序。可通过onShow(OBJECT)所携带的参数判断返回结果,OBJECT返回参数请查看小程序开发文档onShow参数说明
当用户放弃操作时,referrerInfo或referrerInfo. extraData为null(或undefined),当车主平台小程序成功或失败返回商户小程序时,referrerInfo.extraData字段说明如下
用户授权结果:
true:已授权
false:授权失败
示例:
App({
onShow(res) {
if (res.scene === 1038) { // 场景值1038:从被打开的小程序返回
const { appId, extraData } = res.referrerInfo
if (appId == 'wxbcad394b3d99dac9') { // appId为wxbcad394b3d99dac9:从车主小程序跳转回来
if (typeof extraData == 'undefined'){
// TODO
// 客户端小程序不确定授权结果,需要发起‘用户状态查询接口’确认授权结果
return;
}
if(extraData.auth == 'true'){
// TODO
// 客户端小程序授权成功
return;
} else {
// TODO
// 授权失败
return;
}
}
}
}
})
## 3.2 H5跳转接口调用请求说明
使用用户状态查询接口返回的path和authorize_package参数通过GET请求的方式拼接参数(注意:参数之后需要拼接#wechat_redirect)
举例如下:
path?appid=wxcbda96de0b165486&sub_appid=wxcbda96de0b165481&mch_id=10000098&sub_mch_id=10000096&openid=oUpF8uMEb4qRXf22hE3X68TekukE&plate_number=粤B888888&sign=EE088059BBC9141264F8D14293AD6C4BB94CEA8C08AA98FBF93E262D445F8FF5&sign_type=HMAC-SHA256&nonce_str=5K8264ILTKCH16CQ2502SI8ZNMTM67VS&trade_scene=PARKING#wechat_redirect
# 3.3 APP跳转接口调用请求说明
使用用户状态查询接口返回的path和authorize_package参数拼接WXLaunchMiniProgram.Req的path参数
安卓举例如下(APP调起小程序详细说明):
String appId =
"wxcdbdf056ad5fc1fb"; // 填应用AppId
IWXAPI api = WXAPIFactory.createWXAPI(context, appId);
WXLaunchMiniProgram.Req req = new WXLaunchMiniProgram.Req();
req.userName = "gh_518c42c65952"; // 填车主小程序原始id,取固定值gh_518c42c65952
req.path = "/pages/route/index?extraData={\"appid\":\"
wxcbda96de0b165486\",\"mch_id\":\"10000098\",\"sub_appid\":\"
wxcbda96de0b165486
\",\"sub_mch_id\":\"10000096\",\"nonce_str\":\"5K8264ILTKCH16CQ2502SI8ZNMTM67VS
\",\"sign_type\":\"HMAC-SHA256\",\"trade_scene\":\"HIGHWAY\",\"sub_openid\":\"
oUpF8uMEb4qRXf22hE3X68TekukE \",\"plate_number\":\"粤Z88888A
\",\"sign\":\"C99D665499D169E97D6278868C06FB91E5DD87BCDA758FA4869669F12C27FEFC\"}";//拉起小程序页面的可带参路径,不填默认拉起小程序首页
req.miniprogramType = WXLaunchMiniProgram.Req.MINIPTOGRAM_TYPE_RELEASE;
api.sendReq(req);
用户开通/授权完成之后,会跳转回到商户的APP,暂时不返回参数。商户侧APP接收到客户端回调后再次调用用户状态查询接口获取用户的最新车主状态
# 4 委办局提供的接口
以下接口的数据都要经过加密传输,具体方法请查看《微信非税缴费文档》的数据加解密说明
# 4.1 车牌状态变更通知
请求参数
字段名 | 类型 | 必填 | 说明 |
---|---|---|---|
plate_number | string | 是 | 车牌号 |
event_type | string | 是 | 当前通知车牌的状态变化类型: NORMAL-变为可用状态 BLOCKED-变为不可用状态注意此状态是车牌状态,而非用户状态 |
event_createtime | int | 是 | 车牌状态变更的发生时间, 商户可根据该时间是否最新,来判断是否需要更新当前车牌状态。(时间戳,单位是秒) |
**返回结果**
字段名 | 类型 | 必填 | 说明 |
---|---|---|---|
errcode | int | 是 | 返回码 |
errmsg | string | 否 | 返回码描述 |
示例
请求参数
{
"plate_number":"粤B888888",
"event_type":"BLOCKED",
"event_createtime":1543497810
}
返回结果
{
"errcode":0,
"errmsg":"成功"
}
## 4.2 支付结果通知
**请求参数**
字段名 | 类型 | 必填 | 说明 |
---|---|---|---|
order_id | string | 是 | 微信非税平台的订单号 |
status | int | 是 | 状态:3或4:已支付5:已退款101:支付失败 |
pay_channel | string | 是 | 缴费渠道,微信非税平台为“wx_nontax”| |
pay_finish_time | int | 否 | 订单支付成功时间,status为已支付时才有此字段(时间戳,单位是秒) |
refund_finish_time | int | 否 | 发起退款指令时间,status为已退款时才有此字段(时间戳,单位是秒) |
refund_fee | int | 否 | 退款金额,部分退款时必填 |
refund_order_id | string | 否 | 退款单号,部分退款时必填 |
返回结果
字段名 | 类型 | 必填 | 说明 |
---|---|---|---|
errcode | int | 是 | 0– 成功210 – 数据格式错误298 – 解密失败299 – 系统错误300 – 签名错误 |
errmsg | string | 否 | 返回信息,如非空,为错误原因 |
示例
请求参数
{
"order_id":"AQCAXCfypa-dC8EKDD96k7NeiEFb",
"status":3,
"pay_channel":"wx_nontax",
"pay_finish_time":1508806792
}
返回结果
{
"errcode":0,
"errmsg":"成功"
}