准备工作:
1、获取到公众号的AppID和AppSecret(注:是公众号的,不是小程序的);
2、申请商户开票接口权限,开通电子发票开发接口权限(可去微信官方文档https://developers.weixin.qq.com/doc/offiaccount/WeChat_Invoice/E_Invoice/Choosing_Access_Mode.html查看具体开通流程)。
开发流程:
1、获取access_token
public String refreshToken(String appId, String appSecret) {
HttpRestClientImpl httpRestClient = new HttpRestClientImpl();
HttpRestResponse response = null;
String access_token = null;
Integer expires_in = null;
try {
response = httpRestClient.get("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appId + "&secret=" + appSecret, null);
LOGGER.info("微信获取token返回结果:{}", response.getData());
Map<?, ?> map = response.toObject(Map.class);
access_token = (String)map.get("access_token");
expires_in = (Integer)map.get("expires_in");//token有效期,一般为 7200 秒,可用来做缓存
} catch (Exception e) {
LOGGER.error("微信获取token异常,,返回数据:{}, e:{}", response, e.getMessage());
}
return access_token;
}
2、获取自身的开票平台识别码;
public String getCardInvoiceSeturl() {
HttpRestClientImpl httpRestClient = new HttpRestClientImpl();
String accessToken = this.refreshToken(wxAccountAppId, wxAccountAppSecret);
HttpRestRequest request = new HttpRestRequest(new JSONObject().toJSONString());
HttpRestResponse response = null;
String invoice_url = null;
try {
response = httpRestClient.postData("https://api.weixin.qq.com/card/invoice/seturl?access_token=" + accessToken, request);
LOGGER.info("微信获取自身的开票平台识别码返回结果:{}", response.getData());
Map<?, ?> responseMap = response.toObject(Map.class);
invoice_url = (String)responseMap.get("invoice_url");
} catch (Exception e) {
LOGGER.error("微信获取自身的开票平台识别码异常,,返回数据:{}, e:{}", response, e.getMessage());
}
//需从invoice_url中获取s_pappid
Map<String, String> urlSplit = TruncateUrlPageUtil.urlSplit(invoice_url);
String s_pappid = urlSplit.get("s_pappid");
return s_pappid;
}
3、校验商户联系方式是否存在;
@SuppressWarnings("unchecked")
public boolean checkCardInvoiceSetbizattrContact() {
HttpRestClientImpl httpRestClient = new HttpRestClientImpl();
String accessToken = this.refreshToken(wxAccountAppId, wxAccountAppSecret);
HttpRestRequest request = new HttpRestRequest(new JSONObject().toJSONString());
HttpRestResponse response = null;
Object contact = null;
try {
response = httpRestClient.postData("https://api.weixin.qq.com/card/invoice/setbizattr?action=get_contact&access_token=" + accessToken, request);
LOGGER.info("微信获取商户联系方式返回结果:{}", response.getData());
Map<String, String> responseMap = JSONUtil.toObject(response.getData(), Map.class);
contact = (Object)responseMap.get("contact");
} catch (Exception e) {
LOGGER.error("微信获取商户联系方式异常,,返回数据:{}, e:{}", response, e.getMessage());
}
return null != contact;
}
4、设置商户联系方式;
public void setCardInvoiceSetbizattrContact() {
HttpRestClientImpl httpRestClient = new HttpRestClientImpl();
String accessToken = this.refreshToken(wxAccountAppId, wxAccountAppSecret);
JSONObject requestDataStr = new JSONObject();
requestDataStr.put("time_out", "12345");
requestDataStr.put("phone", "18274945575");
HttpRestRequest request = new HttpRestRequest(requestDataStr.toJSONString());
HttpRestResponse response = null;
try {
response = httpRestClient.postData("https://api.weixin.qq.com/card/invoice/setbizattr?action=set_contact&access_token=" + accessToken, request);
LOGGER.info("微信设置商户联系方式返回结果:{}", response.getData());
} catch (Exception e) {
LOGGER.error("微信设置商户联系方式异常,请求参数:{},返回数据:{}, e:{}", requestDataStr.toJSONString(), response, e.getMessage());
}
}
5、商户获取授权页ticket;
public String getCgiBinTicket() {
HttpRestClientImpl httpRestClient = new HttpRestClientImpl();
String accessToken = this.refreshToken(wxAccountAppId, wxAccountAppSecret);
HttpRestRequest request = new HttpRestRequest(new JSONObject().toJSONString());
HttpRestResponse response = null;
String cgiBinTicket = null;
Integer expire = null;
try {
response = httpRestClient.postData("https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=wx_card&access_token=" + accessToken, request);
LOGGER.info("微信商户获取授权页ticket返回结果:{}", response.getData());
Map<?, ?> responseMap = response.toObject(Map.class);
cgiBinTicket = (String)responseMap.get("ticket");
expire = (Integer)responseMap.get("expires_in");//ticket 有效期,一般为 7200 秒,可用来做缓存
} catch (Exception e) {
LOGGER.error("微信商户获取授权页ticket异常,,返回数据:{}, e:{}", response, e.getMessage());
}
return cgiBinTicket;
}
6、商户获取小程序授权页链接(获取到之后返回参数给前端,给用户跳转微信授权页进行授权操作,微信官方文档里面有“小程序打开授权页”文档);
public WxCardInvoiceAuthurlVO getCardInvoiceAuthurl(String tenantId, String s_pappid, String ticket, String order_id, String money) {
HttpRestClientImpl httpRestClient = new HttpRestClientImpl();
Timestamp currentTime = DateUtil.getCurrentTime();
String accessToken = this.refreshToken(wxAccountAppId, wxAccountAppSecret);
JSONObject requestDataStr = new JSONObject();
requestDataStr.put("timestamp", String.valueOf(currentTime.getTime()));
requestDataStr.put("source", "wxa");
requestDataStr.put("type", "2");
requestDataStr.put("s_pappid", s_pappid);
requestDataStr.put("ticket", ticket);
requestDataStr.put("order_id", order_id);
requestDataStr.put("money", new BigDecimal(money).multiply(new BigDecimal(100)).setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue());
HttpRestRequest request = new HttpRestRequest(requestDataStr.toJSONString());
HttpRestResponse response = null;
String appid = null;
String auth_url = null;
try {
response = httpRestClient.postData("https://api.weixin.qq.com/card/invoice/getauthurl?access_token=" + accessToken, request);
LOGGER.info("微信商户获取小程序授权页链接返回结果:{}", response.getData());
Map<?, ?> responseMap = response.toObject(Map.class);
appid = (String)responseMap.get("appid");
auth_url = (String)responseMap.get("auth_url");
} catch (Exception e) {
LOGGER.error("微信商户获取小程序授权页链接异常,请求参数:{},返回数据:{}, e:{}", requestDataStr.toJSONString(), response, e.getMessage());
}
//添加到缓存待授权微信发票卡券集合,统一处理
Timestamp validTime = null;//设置当前时间后6分钟有效期
String wxInvoiceAuthOrderListCacheKey = null;//设置缓存key
String wxInvoiceAuthOrderListCache = redisClient.get(wxInvoiceAuthOrderListCacheKey);
if(null != wxInvoiceAuthOrderListCache) {
List<WxInvoiceAuthOrderListCacheVO> wxInvoiceAuthOrderList = JSONUtil.toList(wxInvoiceAuthOrderListCache.getBytes(), WxInvoiceAuthOrderListCacheVO.class);
wxInvoiceAuthOrderList.add(new WxInvoiceAuthOrderListCacheVO(tenantId, order_id, validTime));
redisClient.set(wxInvoiceAuthOrderListCacheKey, JSONUtil.toJson(wxInvoiceAuthOrderList));
}
return new WxCardInvoiceAuthurlVO(appid, auth_url);
}
7、定时将授权后的电子发票卡券插入用户卡包(包含查询授权完成状态,创建发票卡券模板,微信上传PDF,将电子发票卡券插入用户卡包),可使用微信回调处理插入用户卡包,我感觉麻烦就未使用了,如需使用,可以去参考微信官方文档。