# 接口调用说明
# 接口列表
接口名称 | 英文名 | 请求路径 |
---|---|---|
获取授权页ticket | getTicket | /cgi-bin/ticket/getticket |
获取授权页链接 | invoicebizgetauthurl | /card/invoice/getauthurl |
查询授权完成状态 | invoicebizgetauthdata | /card/invoice/getauthdata |
拒绝开票 | invoicebizrejectinsert | /card/invoice/rejectinsert |
设置授权页字段信息 | set_auth_field | /card/invoice/setbizattr |
查询授权页字段信息 | get_auth_field | /card/invoice/setbizattr |
关联商户号与开票平台 | set_pay_mch | /card/invoice/setbizattr |
查询商户号与开票平台关联情况 | get_pay_mch | /card/invoice/setbizattr |
设置商户联系方式 | set_contact | /card/invoice/setbizattr |
查询商户联系方式 | get_contact | /card/invoice/setbizattr |
# 接口调用顺序
开发者可参考下方接口调用顺序,依次调用接口,完成开票流程。
# 1 获取授权页ticket
接口说明
商户在调用授权页前需要先获取一个7200s过期的授权页ticket,在获取授权页接口中,该ticket作为参数传入,加强安全性。
# 2 获取授权页链接
接口说明
本接口供商户调用。商户通过本接口传入订单号、开票平台标识等参数,获取授权页的链接。在微信中向用户展示授权页,当用户点击了授权页上的“领取发票”/“申请开票”按钮后,即完成了订单号与该用户的授权关系绑定,后续开票平台可凭此订单号发起将发票卡券插入用户卡包的请求,微信也将据此授权关系校验是否放行插卡请求。
授权页包括三种样式,商户可以通过传入不同type的值进行调用。各样式授权页如下图所示:
不同样式授权页作用如下:
type=0(申请开票类型):用于商户已从其它渠道获得用户抬头,拉起授权页发起开票,开票成功后保存到用户卡包;
type=1(填写抬头申请开票类型):调用该类型时,页面会显示微信存储的用户常用抬头。用于商户未收集用户抬头,希望为用户减少填写步骤。需要留意的是,当使用支付后开票业务时,只能调用type=1类型。
type=2(领取发票类型):用于商户发票已开具成功,拉起授权页后让用户将发票归集保存到卡包。
# 3 小程序打开授权页
接口说明
小程序需要先使用小程序账号调用获取授权页链接接口,获取到授权连接,才能打开授权页。
请求方式
在小程序中调用wx.navigateToMiniProgram方法。
请求参数
请求参数使用JSON格式,字段如下:
参数 | 类型 | 是否必填 | 描述 |
---|---|---|---|
appid | string | 是 | 获取授权页链接返回的appid |
path | string | 是 | 获取授权页链接返回的auth_url |
返回结果
用户授权的结果,将通过小程序的callback通知商户。
示例代码
wx.navigateToMiniProgram({
appId: '{appid}',
path: '{auth_url}',
success(res) {
console.log('navigateToMiniProgram success:', res)
},
fail(error){
console.log('navigateToMiniProgram fail:', error)
},
complete(res){
console.log('navigateToMiniProgram complete:', res)
}
})
# 4 iOS 客户端打开授权页
接口说明
ios客户端需要先使用open账号调用获取授权页链接接口,获取到授权连接,才能打开授权页。
请求方式
调用sendReq接口
请求参数
参数 | 类型 | 是否必填 | 描述 |
---|---|---|---|
urlString | string | 是 | 获取授权页链接返回的auth_url |
返回结果
客户端接收微信发票授权返回接口,需要实现onResp方法。返回结果字段如下:
参数 | 类型 | 是否必填 | 描述 |
---|---|---|---|
errCode | int | 是 | 错误码 |
wxOrderId | string | 是 | 授权订单号 |
示例代码
发送请求
WXInvoiceAuthInsertReq *req = [[WXInvoiceAuthInsertReq alloc] init];
req.urlString = self.authUrl;
[WXApi sendReq:req];
接收返回
- (void) onResp:(BaseResp *)resp
{
if ([resp isKindOfClass:[WXInvoiceAuthInsertResp class]]) {
WXInvoiceAuthInsertResp *wxResp = (WXInvoiceAuthInsertResp *) resp;
NSString *strTitle = @"微信回跳";
NSString *strMsg = [NSString stringWithFormat:@"errcode: %d orderid:%@", wxResp.errCode, wxResp.wxOrderId];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:strTitle message:strMsg delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil];
[alert show];
}
}
备注
用户从商户客户端跳到微信客户端进行发票开票授权之后,有可能不返回商户客户端(比如用户直接杀死微信进程),所以商户不能依赖微信客户端的返回来判断用户是否有授权。微信电子发票平台提供了服务号callback机制,当用户进行发票开票授权时,微信电子发票平台会通过callback通知商户。另外,微信电子发票平台还提供了查询是否授权接口。
正确的使用方法:
1 商户使用open账号调用接口获取授权连接
2 用户在商户客户端进入开发票页面,通过微信sdk跳转到微信客户端,进行发票插卡授权
3 商户服务号接收callback,确定用户是否有授权
4 商户客户端接收到微信客户端发票插卡授权的回跳时,使用open账号调用接口查询用户是否有授权
5 用户在商户客户端再次进入开发票页面时,使用open账号调用接口查询用户是否有授权
6 如果用户有授权,就通知开票平台开发票
# 5 Android 客户端打开授权页
接口说明
android客户端需要先调用获取授权页链接接口,获取到授权连接,才能打开授权页。
请求方式
调用sendReq接口
请求参数
参数 | 类型 | 是否必填 | 描述 |
---|---|---|---|
urlString | string | 是 | 获取授权页链接返回的auth_url |
返回结果
客户端接收微信发票授权返回接口,需要实现onResp方法。返回结果字段如下:
参数 | 类型 | 是否必填 | 描述 |
---|---|---|---|
errCode | int | 是 | 错误码 |
wxOrderId | string | 是 | 授权订单号 |
示例代码
发送请求
WXInvoiceAuthInsert.Req oReq = new WXInvoiceAuthInsert.Req();
oReq.url = sJumpUrl;
api.sendReq(oReq);
接收返回
public class WXEntryActivity extends Activity implements IWXAPIEventHandler {
private static final String APP_ID = "wxxxxxxxxxxx";
private IWXAPI api;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
api = WXAPIFactory.createWXAPI(this, APP_ID, true);
api.handleIntent(getIntent(), this);
}
@Override
public void onReq(BaseReq baseReq) {
}
@Override
public void onResp(BaseResp baseResp) {
Toast.makeText(getApplicationContext(), "onResp", Toast.LENGTH_LONG).show();
if (baseResp.getClass().equals(WXInvoiceAuthInsert.Resp.class)) {
WXInvoiceAuthInsert.Resp oResp = (WXInvoiceAuthInsert.Resp) baseResp;
String sLog = "errcode:" + oResp.errCode + " wxorderid:" + oResp.wxOrderId;
System.out.print(sLog);
}
}
}
备注
用户从商户客户端跳到微信客户端进行发票开票授权之后,有可能不返回商户客户端(比如用户直接杀死微信进程),所以商户不能依赖微信客户端的返回来判断用户是否有授权。微信电子发票平台提供了服务号callback机制,当用户进行发票开票授权时,微信电子发票平台会通过callback通知商户。另外,微信电子发票平台还提供了查询是否授权接口。
正确的使用方法:
1 商户使用open账号调用接口获取授权连接
2 用户在商户客户端进入开发票页面,通过微信sdk跳转到微信客户端,进行发票插卡授权
3 商户服务号接收callback,确定用户是否有授权
4 商户客户端接收到微信客户端发票插卡授权的回跳时,使用open账号调用接口查询用户是否有授权
5 用户在商户客户端再次进入开发票页面时,使用open账号调用接口查询用户是否有授权
6 如果用户有授权,就通知开票平台开发票
# 6 收取授权完成事件推送
接口说明
在用户授权同意发票存入自己微信账户后,商户可以收到授权完成的状态推送。收到推送后,可以将order_id连同开票信息一并发送给开票平台,以便开票平台在开票成功后将电子发票插入用户卡包。
该事件将发送至开发者填写的URL(登录公众平台进入【开发者中心设置】,如果是open账号,也得用服务号账号来接,参考下图)。
微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次。关于重试的消息排重,推荐使用FromUserName + CreateTime 排重。假如服务器无法保证在五秒内处理并回复,可以直接回复空串,微信服务器不会对此作任何处理,并且不会发起重试。
返回结果
返回结果为XML格式,字段如下:
参数 | 类型 | 是否必填 | 描述 |
---|---|---|---|
ToUserName | String | 是 | 服务号标识 |
FromUserName | String | 是 | 用户openid |
CreateTime | Int | 是 | 事件时间 |
MsgType | String | 是 | 固定为event |
Event | String | 是 | 固定为user_authorize_invoice |
SuccOrderId | String | 否 | 授权成功的订单号,与失败订单号两者必显示其一 |
FailOrderId | String | 否 | 授权失败的订单号,与成功订单号两者必显示其一 |
AuthorizeAppId | String | 是 | 获取授权页链接的AppId |
Source | String | 是 | 授权来源,web:服务号开票,app:app开票,wxa:小程序开票,wap:h5开票 |
示例代码
<?xml version="1.0" encoding="utf-8"?>
<xml>
<ToUserName><![CDATA[gh_fc0a06a20993]]></ToUserName>
<FromUserName><![CDATA[oZI8Fj040-be6rlDohc6gkoPOQTQ]]></FromUserName>
<CreateTime>1475134700</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[user_authorize_invoice]]></Event>
<SuccOrderId><![CDATA[1202933957956]]></SuccOrderId>
<FailOrderId><![CDATA[]]></FailOrderId> < AuthorizeAppId ><![CDATA[]]></ AuthorizeAppId > <Source><![CDATA[]]></Source>
</xml>
# 7 查询授权完成状态
接口说明
本接口的调用场景包括两个:
一、若商户在某次向用户展示授权页后经过较长时间仍未收到授权完成状态推送,可以使用本接口主动查询用户是否实际上已完成授权,只是由于网络等原因未收到授权完成事件;
二、若商户向用户展示的授权页为type=1类型,商户在收到授权完成事件推送后需要进一步获取用户的开票信息,也可以调用本接口。
# 8 拒绝开票
接口说明
用户完成授权后,商户若发现用户提交信息错误、或者发生了退款时,可以调用该接口拒绝开票并告知用户。拒绝开票后,该订单无法向用户再次开票。已经拒绝开票的订单,无法再次使用,如果要重新开票,需使用新的order_id,获取授权链接,让用户再次授权。 调用接口后用户侧收到的通知消息如下图所示:
# 9 设置授权页字段信息
接口说明
当用户使用type=1的类型的授权页时,可以使用本接口设置授权页上需要用户填写的信息。若使用type=0或type=2类型的授权页,无需调用本接口。本接口为一次性设置,后续除非在需要调整页面字段时才需要再次调用。
注意,设置为显示状态的字段均为必填字段,用户若不填写将无法进入后续流程
# 10 查询授权页字段信息
接口说明
商户可以通过本接口查询到授权页的字段设置情况。
# 11 关联商户号与开票平台
接口说明
商户使用支付后开票,需要先将自身的商户号和开票平台的识别号进行关联,开票平台识别号由开票平台根据微信规则生成后告知商户。本接口为一次性设置,后续一般在遇到开票平台识别号变更,或者商户更换开票平台时才需要调用本接口重设对应关系。
若商户已经实现电子发票的微信卡包送达方案,调用本接口前,建议在微信支付商户平台中确认商户号所绑定的服务号和拉起授权页的服务号是同一个。若不是同一个,仍需重新使用商户号所绑定服务号去调通拉取授权页的接口。
# 12 查询商户号与开票平台关联情况
接口说明
商户可以通过本接口查询到与开票平台的绑定情况。
# 13 指定单笔交易支持支付后开票
接口说明
对于可以开具电子发票的商户,完成了微信商户号与开票平台的关联设置后,可以以单笔支付为单位,指定在支付成功消息上是否出现开发票的入口。让用户可以通过该入口发起开票。
请求方式
指定单笔交易支持支付后开票使用的接口协议、调用方式与线上 支付文档一致,本功能是在原支付接口上新增字段。
请求参数
用户确认下单后,商户在支付接口(统一下单/提交刷卡支付/委托代扣)中新增提交receipt字段作为标识需要开电子发票。字段参数说明如下:
参数 | 类型 | 是否必填 | 描述 |
---|---|---|---|
receipt | string | 否 | Y ,传入 Y 时,支付成功消息和支付详情页将出现开票入口 |
返回结果
与原支付接口返回结果相一致。
示例代码
<xml>
<appid>wx2421b1c4370ec43b </appid>
<attach>支付测试</attach>
<body>JSAPI支付测试</body>
<mch_id>10000100</mch_id>
<receipt>Y</receipt>
<nonce_str>1add1a30ac87aa2db72f57a2375d8fec</nonce_str>
<notify_url>http://wxpay.wxutil.com/pub_v2/pay/notify.v2.php</notify_url>
<openid>oUpF8uMuAJO_M2pxb1Q9zNjWeS6o</openid>
<out_trade_no>1415659990</out_trade_no>
<spbill_create_ip>14.23.150.211</spbill_create_ip>
<total_fee>1</total_fee>
<trade_type>JSAPI</trade_type>
<sign>0CB01533B8C1EF103065174F50BCA001</sign>
</xml>
# 14 设置商户联系方式
接口说明 商户获取授权链接之前,需要先设置商户的联系方式
# 15 查询商户联系方式
接口说明 商户获取授权链接之前,需要先设置商户的联系方式
# 错误码
错误码 | 错误信息 | 备注 |
---|---|---|
0 | OK | 成功 |
40097 | invalid args size | type参数值不符预期 |
72015 | unauthorized create invoice | 没有开票平台的权限,请检查是否已开通相应权限。 |
72023 | invoice has been lock | 发票已被其他服务号锁定。一般为发票已进入后续报销流程,报销企业服务号/企业号/App锁定了发票。 |
72024 | invoice status error | 发票状态错误 |
72025 | invoice token error | wx_invoice_token 无效 |
72028 | invoice never set pay mch info | 未设置微信支付商户信息 |
72030 | invalid mchid | mchid 无效 |
72031 | invalid params | 参数错误。可能为请求中包括无效的参数名称或包含不通过后台校验的参数值 |
72035 | biz reject insert | 发票已经被拒绝开票。若order_id被用作参数调用过拒绝开票接口,再使用此order_id插卡机会报此错误 |
72036 | invoice is busy | 发票正在被修改状态,请稍后再试 |
72038 | invoice order never auth | 订单没有授权,可能是开票平台 appid 、商户 appid 、订单 order_id 不匹配 |
72039 | invoice must be lock first | 订单未被锁定,需要先锁定再核销 |
72040 | invoice pdf error | Pdf 无效,请提供真实有效的 pdf |
72042 | billing_code and billing_no repeated | 发票号码和发票代码重复,该发票已经被其它用户领取 |
72043 | billing_code or billing_no size error | 发票号码和发票代码错误 |
72044 | scan text out of time | 发票抬头二维码超时 |
72063 | biz contact is empty | 商户联系方式未空,请先调用接口设置商户联系方式 |
73000 | sys error make out invoice failed | 开票平台逻辑错误 |
73001 | wxopenid error | OpenId错误 |
73002 | ddh orderid empty | 订单号为空 |
73003 | fpqqlsh empty | 发票流水号为空 |
73004 | kplx empty | 发票流水号为空 |
73007 | nsrmc empty | 纳税人名称为空 |
73008 | nsrdz empty | 纳税人地址为空 |
73009 | nsrdh empty | 纳税人电话为空 |
73010 | ghfmc empty | 购货方名称为空 |
73011 | kpr empty | 开票人为空 |
73012 | jshj empty | 计税合计为空 |
73013 | hjje empty | 合计金额为空 |
73014 | hjse empty | 合计税额为空 |
73015 | hylx empty | 行业类型为空 |
73016 | nsrsbh empty | 纳税人识别号为空 |
73100 | ka plat error | 开票平台错误 |
73101 | nsrsbh not cmp | 纳税人识别号不匹配,请求中的纳税人识别号和创建工单填写的纳税人识别号不一致 |
73102 | sys error | 微信开票平台系统错误 |
73105 | Kp plat make invoice timeout, please try again with the same fpqqlsh | 开票平台开票中,请使用相同的发票请求流水号重试开票 |
73106 | Fpqqlsh exist with different ddh | 发票请求流水号已存在,并被其他订单号占用 |
73107 | Fpqqlsh is processing, please wait and query later | 发票请求流水正在被处理,请通过查询接口获取结果 |
73108 | This ddh with other fpqqlsh already exist | 该订单已被其他发票请求流水处理 |
73110 | fpqqlsh first 6 byte not cmp | 发票请求流水号前6位不正确 |
40078 | invalid card status | card_id未授权。 若开发者使用沙箱环境报此错误,主要因为未将调用接口的微信添加到测试把名单; 若开发者使用正式环境报此错误,主要原因可能为:调用接口服务号未开通卡券权限,或创建card_id与插卡时间间隔过短。 |