diff --git a/src/main/java/com/yxt/yythmall/api/ordorder/OrdOrderQuery.java b/src/main/java/com/yxt/yythmall/api/ordorder/OrdOrderQuery.java index 356339a..eaaced4 100644 --- a/src/main/java/com/yxt/yythmall/api/ordorder/OrdOrderQuery.java +++ b/src/main/java/com/yxt/yythmall/api/ordorder/OrdOrderQuery.java @@ -15,4 +15,6 @@ public class OrdOrderQuery implements Query { private String state; private String mainSid; private String payTime; + private String totalTee; + private String outTradeNo; } diff --git a/src/main/java/com/yxt/yythmall/biz/ordorder/OrdOrderRest.java b/src/main/java/com/yxt/yythmall/biz/ordorder/OrdOrderRest.java index 24efd81..075ff30 100644 --- a/src/main/java/com/yxt/yythmall/biz/ordorder/OrdOrderRest.java +++ b/src/main/java/com/yxt/yythmall/biz/ordorder/OrdOrderRest.java @@ -76,4 +76,9 @@ public class OrdOrderRest { public ResultBean electronicInvoice(@RequestBody String mainSid) { return ordOrderService.electronicInvoice(mainSid); } + @PostMapping("/wxElectronicInvoice") + @ApiOperation(value = "微信电子发票") + public ResultBean wxElectronicInvoice(@RequestBody OrdOrderQuery query) { + return ordOrderService.wxElectronicInvoice(query); + } } diff --git a/src/main/java/com/yxt/yythmall/biz/ordorder/OrdOrderService.java b/src/main/java/com/yxt/yythmall/biz/ordorder/OrdOrderService.java index 13325be..0a41f85 100644 --- a/src/main/java/com/yxt/yythmall/biz/ordorder/OrdOrderService.java +++ b/src/main/java/com/yxt/yythmall/biz/ordorder/OrdOrderService.java @@ -15,13 +15,10 @@ import com.yxt.yythmall.api.appletgiftbag.GiftBagGoodss; import com.yxt.yythmall.api.lpkcustomer.LpkCustomer; import com.yxt.yythmall.api.lpkcustomer.LpkCustomerVo; import com.yxt.yythmall.api.lpkgoods.LpkGoods; -import com.yxt.yythmall.api.lpkstore.LpkStore; -import com.yxt.yythmall.api.lpkstore.LpkStoreQuery; import com.yxt.yythmall.api.lpkstore.LpkStoreVo; import com.yxt.yythmall.api.ordorder.*; import com.yxt.yythmall.api.ordorderdetails.OrdOrderDetail; import com.yxt.yythmall.api.ordorderdetails.OrdOrderDetailVo; -import com.yxt.yythmall.api.shoppingcart.ShoppingCart; import com.yxt.yythmall.api.shoppingcart.ShoppingCartQuery; import com.yxt.yythmall.api.shoppingcart.ShoppingCartVo; import com.yxt.yythmall.api.vegetablecellar.VegetableCellar; @@ -31,6 +28,8 @@ import com.yxt.yythmall.biz.lpkgoods.LpkGoodsService; import com.yxt.yythmall.biz.ordorderdetails.OrdOrderDetailService; import com.yxt.yythmall.biz.shoppingcart.ShoppingCartService; import com.yxt.yythmall.biz.vegetablecellar.VegetableCellarService; +import com.yxt.yythmall.biz.wx.WxConfig; +import com.yxt.yythmall.biz.wx.RequestMes; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.ResponseEntity; @@ -647,6 +646,26 @@ public class OrdOrderService extends MybatisBaseService().eq("sid",sid)); + String url = WxConfig.AUTHORIZATION_PAGE.replace("ACCESS_TOKEN", WxConfig.wxAccessToken()); + Map map = new HashMap<>(); + long timestamp = System.currentTimeMillis() / 1000; + map.put("s_pappid",WxConfig.getSPAppId()); + map.put("order_id",query.getOutTradeNo()); + map.put("money",query.getTotalTee()); + map.put("timestamp",String.valueOf(timestamp)); + map.put("source","wxa"); + map.put("redirect_url",""); + map.put("ticket",WxConfig.wxTicket()); + map.put("type","1"); + RequestMes res = new RestTemplate().postForObject(url,map,RequestMes.class); + if(!res.getErrcode().equals("0")){ + return rb.setCode(res.getErrcode()).setMsg(res.getErrmsg()); + } + return rb.success().setData(res); + } /** * 去除多余.0 diff --git a/src/main/java/com/yxt/yythmall/biz/wx/invoice/RequestMes.java b/src/main/java/com/yxt/yythmall/biz/wx/RequestMes.java similarity index 68% rename from src/main/java/com/yxt/yythmall/biz/wx/invoice/RequestMes.java rename to src/main/java/com/yxt/yythmall/biz/wx/RequestMes.java index cadb056..63c8c13 100644 --- a/src/main/java/com/yxt/yythmall/biz/wx/invoice/RequestMes.java +++ b/src/main/java/com/yxt/yythmall/biz/wx/RequestMes.java @@ -1,4 +1,4 @@ -package com.yxt.yythmall.biz.wx.invoice; +package com.yxt.yythmall.biz.wx; import lombok.Data; @@ -11,5 +11,6 @@ public class RequestMes { private String errcode; private String errmsg; private String auth_url; - private String appid; + private String appid; + private String invoice_url; } diff --git a/src/main/java/com/yxt/yythmall/biz/wx/WxConfig.java b/src/main/java/com/yxt/yythmall/biz/wx/WxConfig.java index bf1bc2d..3856ad1 100644 --- a/src/main/java/com/yxt/yythmall/biz/wx/WxConfig.java +++ b/src/main/java/com/yxt/yythmall/biz/wx/WxConfig.java @@ -6,12 +6,22 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.client.RestTemplate; +import java.util.HashMap; +import java.util.Map; + public class WxConfig { private static final Logger L = LoggerFactory.getLogger(WxConfig.class); private static final long token_expires_in = 5400 * 1000; + //获取token private static final String WX_URL_ACCESS_TOKEN = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET"; + //获取s_pappid + private static final String SETURL="https://api.weixin.qq.com/card/invoice/seturl?access_token=ACCESS_TOKEN"; + //授权页 + public static final String AUTHORIZATION_PAGE="https://api.weixin.qq.com/card/invoice/getauthurl?access_token=ACCESS_TOKEN"; + //设置商户联系信息 + public static final String merchant_contact="https://api.weixin.qq.com/card/invoice/setbizattr?action=set_contact&access_token=ACCESS_TOKEN"; //获取 ticket private static final String ticket = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=wx_card"; @@ -26,8 +36,8 @@ public class WxConfig { private static String mp_access_token; private static long mp_token_create_timestamp; - public static final String WX_APPID = "wxc64c6cf0a06880e5"; - private static final String WX_APPSECRET = "eb3a0794da05f12a94c92134030246f1"; + public static final String WX_APPID = "wx1d44e0fcd110351a"; + private static final String WX_APPSECRET = "e1ec3a9f542aa8bf2ffdf8248bdb69b1"; public static final String MP_APPID = "wx05604ce2a8bede05"; private static final String MP_APPSECRET = "3d36e8a61212cf773a2fa4e6c9a83334"; @@ -79,7 +89,7 @@ public class WxConfig { * @param secret * @return */ - public static String getTicket(String appid, String secret) { + public static String getTicket() { String url = ticket.replace("ACCESS_TOKEN",wxAccessToken()); String res = new RestTemplate().getForObject(url, String.class); JSONObject jsonObject = JSONObject.parseObject(res); @@ -94,9 +104,68 @@ public class WxConfig { */ public static String wxTicket() { if (StringUtils.isBlank(wx_ticket) || System.currentTimeMillis() > (wx_ticket_create_timestamp + ticket_expires_in)) { - wx_ticket = getTicket(WX_APPID, WX_APPSECRET); + wx_ticket = getTicket(); wx_ticket_create_timestamp = System.currentTimeMillis(); } return wx_ticket; } + + + public static String getSPAppId(){ + String url = SETURL.replace("ACCESS_TOKEN", WxConfig.wxAccessToken()); + Map map = new HashMap<>(); + RequestMes res = new RestTemplate().postForObject(url,map,RequestMes.class); + String s_pappid=res.getInvoice_url().substring(res.getInvoice_url().indexOf("&")+10); + return s_pappid; + } + public static String merchantContact(){ + String url = merchant_contact.replace("ACCESS_TOKEN", WxConfig.wxAccessToken()); + Map m=new HashMap<>(); + m.put("phone","15932270269"); + m.put("time_out","12345"); + Map> map = new HashMap<>(); + map.put("contact",m); + RequestMes res = new RestTemplate().postForObject(url,map,RequestMes.class); + + return "1"; + } + + public static void main(String[] args) { + String url = merchant_contact.replace("ACCESS_TOKEN", WxConfig.wxAccessToken()); + Map m=new HashMap<>(); + m.put("phone","15932270269"); + m.put("time_out","12345"); + Map> map = new HashMap<>(); + map.put("contact",m); + RequestMes res = new RestTemplate().postForObject(url,map,RequestMes.class); + System.out.println(res); + } + + + + + /** + * @param $appId + * @param $uid + * @param $order_no + * @param $ticket_no + * @return bool|mixed + * @throws LocalServiceException + * @throws RemoteServiceException + * + * @desc 小程序开具电子发票的步骤如下: + 1 提前获取开票平台标识s_pappid,因为同一个开票平台的s_pappid都相同,所以获取s_pappid的操作只需要进行一次。不同接入模式获取s_pappid的方法略有不同: + 如果商户接入模式为“自建平台模式”:s_pappid通过调用调用获取自身开票平台识别码接口获得 + 2 商户获取获取access_token。调用方法见获取access_token; + 3 设置商户联系方式。调用方法见设置商户联系方式。注意,本步骤不能忽略,否则将造成下一步获取授权页报错; + 4 商户获取授权页ticket。调用方法见获取授权页ticket; + 5 商户获取授权页url,上一步获取的授权页ticket将作为参数传入。另外,本环节里面作为参数传入的order_id要注意保留,传递给开票平台作为向用户提供电子发票的依据。调用方法见获取授权页链接; + 6 在小程序开票按钮的点击事件上部署跳转到小程序授权页的逻辑。上一步获得的auth_url和开票小程序appid要作为参数传入。调用方法见小程序打开授权页; + 7 商户在后台等待接收用户的授权完成事件,获取授权事件方法见收取授权完成事件推送; + 8 创建发票卡券模板。发票卡券模板应和背后的开票主体构成一一对应关系,便于后续若开票主体发生变化时,可以便捷修改。调用方法见创建发票卡券模板; + 9 在自建发票平台开具电子发票; + 10 上传发票PDF文件。此步骤获得的s_media_id起到关联PDF和发票卡券的作用,将作为参数在下一步的插卡接口中传入。调用方法见上传PDF; + 11 将电子发票添加到用户微信卡包。调用方法见将电子发票卡券插入用户卡包。 + */ + } diff --git a/src/main/java/com/yxt/yythmall/biz/wx/invoice/ElectronicInvoice.java b/src/main/java/com/yxt/yythmall/biz/wx/invoice/ElectronicInvoice.java deleted file mode 100644 index ad549e0..0000000 --- a/src/main/java/com/yxt/yythmall/biz/wx/invoice/ElectronicInvoice.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.yxt.yythmall.biz.wx.invoice; - -import com.alibaba.fastjson.JSONObject; -import com.yxt.common.core.result.ResultBean; -import com.yxt.yythmall.biz.wx.WxConfig; -import org.springframework.web.client.RestTemplate; - -import java.util.HashMap; -import java.util.Map; - -/** - * @author wangpengfei - * @date 2024/3/15 16:09 - */ -public class ElectronicInvoice { - private static final String AUTHORIZATION_PAGE="https://api.weixin.qq.com/card/invoice/getauthurl?access_token=ACCESS_TOKEN"; - - public ResultBean getAuthorizationPage(String appid, String secret) { - ResultBean rb= ResultBean.fireFail(); - String url = AUTHORIZATION_PAGE.replace("ACCESS_TOKEN", WxConfig.wxAccessToken()); - Map map = new HashMap<>(); - RequestMes res = new RestTemplate().postForObject(url,map,RequestMes.class); - if(!res.getErrcode().equals("0")){ - return rb; - } - return rb; - } -} diff --git a/src/main/java/com/yxt/yythmall/biz/wx/invoice/ElectronicInvoiceService.java b/src/main/java/com/yxt/yythmall/biz/wx/invoice/ElectronicInvoiceService.java new file mode 100644 index 0000000..b659c87 --- /dev/null +++ b/src/main/java/com/yxt/yythmall/biz/wx/invoice/ElectronicInvoiceService.java @@ -0,0 +1,47 @@ +package com.yxt.yythmall.biz.wx.invoice; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.yxt.common.core.result.ResultBean; +import com.yxt.yythmall.api.ordorder.OrdOrder; +import com.yxt.yythmall.biz.ordorder.OrdOrderService; +import com.yxt.yythmall.biz.wx.RequestMes; +import com.yxt.yythmall.biz.wx.WxConfig; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author wangpengfei + * @date 2024/3/15 16:09 + */ +@Service +public class ElectronicInvoiceService { + @Autowired + OrdOrderService ordOrderService; + private static final String AUTHORIZATION_PAGE="https://api.weixin.qq.com/card/invoice/getauthurl?access_token=ACCESS_TOKEN"; + + + public ResultBean getAuthorizationPage(String sid) { + ResultBean rb= ResultBean.fireFail(); + OrdOrder order=ordOrderService.getOne(new QueryWrapper().eq("sid",sid)); + String url = AUTHORIZATION_PAGE.replace("ACCESS_TOKEN", WxConfig.wxAccessToken()); + Map map = new HashMap<>(); + long timestamp = System.currentTimeMillis() / 1000; + map.put("s_pappid",WxConfig.getSPAppId()); + map.put("order_id",order.getOutTradeNo()); + map.put("money",order.getTotalTee()); + map.put("timestamp",String.valueOf(timestamp)); + map.put("source","wxa"); + map.put("redirect_url",""); + map.put("ticket",WxConfig.wxTicket()); + map.put("type","1"); + RequestMes res = new RestTemplate().postForObject(url,map,RequestMes.class); + if(!res.getErrcode().equals("0")){ + return rb.setCode(res.getErrcode()).setMsg(res.getErrmsg()); + } + return rb.success().setData(res); + } +}