wwl 3 роки тому
батько
коміт
60cc9d24ed

+ 1 - 1
twzd-admin/src/main/java/com/miaxis/system/controller/wx/WxgzhController.java

@@ -31,7 +31,7 @@ import javax.servlet.http.HttpServletResponse;
 @RestController
 @RequiredArgsConstructor
 @RequestMapping(Constants.OPEN_PREFIX + "/wx/gzh")
-@Api(tags={"微信公众号相关"})
+@Api(tags={"wx微信公众号相关"})
 @Slf4j
 public class WxgzhController {
 

+ 6 - 0
twzd-admin/src/main/resources/application-dev.yml

@@ -107,5 +107,11 @@ cos:
     preffix: twzd-test
 
 
+# 分销二维码生成路径
+file:
+    ticketPath: C:\Users\wwl\Desktop\二维码\
 
 
+# 公众号上传永久素材url
+wxgzh:
+    materialUrl: https://api.weixin.qq.com/cgi-bin/material/add_material?access_token=

+ 11 - 1
twzd-admin/src/main/resources/application-prod.yml

@@ -101,4 +101,14 @@ cos:
     bucket: ap-shanghai
     bucketName: twzd-1305573081
     path: https://twzd-1305573081.cos.ap-shanghai.myqcloud.com
-    preffix: twzd-prod
+    preffix: twzd-prod
+
+
+# 带参数的二维码生成路径
+file:
+    ticketPath: /data/test/
+
+
+# 公众号上传永久素材url
+wxgzh:
+    materialUrl: https://api.weixin.qq.com/cgi-bin/material/add_material?access_token=

+ 73 - 4
twzd-common/src/main/java/com/miaxis/common/utils/http/HttpUtils.java

@@ -6,10 +6,7 @@ import org.slf4j.LoggerFactory;
 
 import javax.net.ssl.*;
 import java.io.*;
-import java.net.ConnectException;
-import java.net.SocketTimeoutException;
-import java.net.URL;
-import java.net.URLConnection;
+import java.net.*;
 import java.security.cert.X509Certificate;
 
 /**
@@ -251,4 +248,76 @@ public class HttpUtils
             return true;
         }
     }
+
+    public static  String connectHttpsByPost(String path, File file) throws Exception{
+        URL urlObj = new URL(path);
+        //连接
+        HttpURLConnection con = (HttpURLConnection) urlObj.openConnection();
+        String result = null;
+        con.setDoInput(true);
+        con.setDoOutput(true);
+        con.setUseCaches(false); // post方式不能使用缓存
+
+        // 设置请求头信息
+        con.setRequestProperty("Connection", "Keep-Alive");
+        con.setRequestProperty("Charset", "UTF-8");
+        // 设置边界
+        String BOUNDARY = "----------" + System.currentTimeMillis();
+        con.setRequestProperty("Content-Type",
+                "multipart/form-data; boundary="
+                        + BOUNDARY);
+
+        // 请求正文信息
+        // 第一部分:
+        StringBuilder sb = new StringBuilder();
+        sb.append("--"); // 必须多两道线
+        sb.append(BOUNDARY);
+        sb.append("\r\n");
+        sb.append("Content-Disposition: form-data;name=\"media\";filelength=\"" + file.length() + "\";filename=\""
+                + file.getName() + "\"\r\n");
+        sb.append("Content-Type:application/octet-stream\r\n\r\n");
+        byte[] head = sb.toString().getBytes("utf-8");
+        // 获得输出流
+        OutputStream out = new DataOutputStream(con.getOutputStream());
+        // 输出表头
+        out.write(head);
+
+        // 文件正文部分
+        // 把文件已流文件的方式 推入到url中
+        DataInputStream in = new DataInputStream(new FileInputStream(file));
+        int bytes = 0;
+        byte[] bufferOut = new byte[1024];
+        while ((bytes = in.read(bufferOut)) != -1) {
+            out.write(bufferOut, 0, bytes);
+        }
+        in.close();
+        // 结尾部分
+        byte[] foot = ("\r\n--" + BOUNDARY + "--\r\n").getBytes("utf-8");// 定义最后数据分隔线
+        out.write(foot);
+        out.flush();
+        out.close();
+        StringBuffer buffer = new StringBuffer();
+        BufferedReader reader = null;
+        try {
+            // 定义BufferedReader输入流来读取URL的响应
+            reader = new BufferedReader(new InputStreamReader(con.getInputStream()));
+            String line = null;
+            while ((line = reader.readLine()) != null) {
+                buffer.append(line);
+            }
+            if (result == null) {
+                result = buffer.toString();
+            }
+        } catch (IOException e) {
+            System.out.println("发送POST请求出现异常!" + e);
+            e.printStackTrace();
+        } finally {
+            if (reader != null) {
+                reader.close();
+            }
+        }
+        return result;
+    }
+
+
 }

+ 0 - 8
twzd-common/src/main/java/com/miaxis/common/utils/wx/MessageUtil.java

@@ -2,14 +2,6 @@ package com.miaxis.common.utils.wx;
 
 import com.miaxis.common.utils.XmlUtil;
 
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.transform.OutputKeys;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
-import java.io.StringWriter;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.Map;

+ 11 - 0
twzd-service/pom.xml

@@ -49,6 +49,17 @@
             <version>0.2.1</version>
         </dependency>
 
+        <!--谷歌二维码生成-->
+        <dependency>
+            <groupId>com.google.zxing</groupId>
+            <artifactId>core</artifactId>
+        </dependency>
+
+        <!--hutool工具包-->
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-all</artifactId>
+        </dependency>
 
     </dependencies>
 

+ 0 - 2
twzd-service/src/main/java/com/miaxis/feign/service/IWxMpService.java

@@ -5,8 +5,6 @@ import org.springframework.cloud.openfeign.FeignClient;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestParam;
 
-import javax.servlet.annotation.HandlesTypes;
-
 /**
  * @author wwl
  * @version 1.0

+ 21 - 4
twzd-service/src/main/java/com/miaxis/feign/service/IWxSendService.java

@@ -3,11 +3,13 @@ package com.miaxis.feign.service;
 import com.alibaba.fastjson.JSONObject;
 import com.miaxis.common.config.FeignConfig;
 import com.miaxis.feign.dto.WxTicket;
+import feign.Headers;
+
+import feign.Param;
+import feign.form.FormData;
 import org.springframework.cloud.openfeign.FeignClient;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.*;
+
 
 /**
  * 微信公众号接口
@@ -68,4 +70,19 @@ public interface IWxSendService {
     String materialAddNews(@RequestParam("access_token")String accessToken, JSONObject jsonObject);
 
 
+    /**
+     * 新增其他类型永久素材
+     *      -文档链接:https://developers.weixin.qq.com/doc/offiaccount/Asset_Management/Adding_Permanent_Assets.html
+     * @param accessToken
+     * @param type 媒体文件类型,分别有图片(image)、语音(voice)、视频(video)和缩略图(thumb)
+     * @param media form-data中媒体文件标识,有filename、filelength、content-type等信息
+     * @return
+     */
+    @PostMapping(value = "/material/add_material")
+    @Headers("Content-Type: multipart/form-data")
+    String materialAddByType(@RequestParam("access_token")String accessToken, @RequestParam("type")String type, @Param("photo") FormData media);
+
+
+
+
 }

+ 1 - 0
twzd-service/src/main/java/com/miaxis/wx/service/IWxGzhService.java

@@ -5,6 +5,7 @@ import com.alibaba.fastjson.JSONObject;
 import javax.servlet.http.HttpServletRequest;
 
 /**
+ * 微信公众号服务
  * @author wwl
  * @version 1.0
  * @date 2021/10/20 14:56

+ 33 - 0
twzd-service/src/main/java/com/miaxis/wx/service/IWxMessageEvenService.java

@@ -0,0 +1,33 @@
+package com.miaxis.wx.service;
+
+/**
+ * 微信消息事件处理
+ * @author wwl
+ * @version 1.0
+ * @date 2021/10/27 14:33
+ */
+public interface IWxMessageEvenService {
+
+    //关注事件
+//    String subscribeEvent();
+
+    /**
+     * 扫码关注事件
+     * @param fromUserName 发送方帐号(一个OpenID)
+     * @param toUserName 开发者微信号
+     * @param Ticket 二维码的ticket
+     * @return
+     */
+    String scanSubscribeEvent(String fromUserName,String toUserName,String Ticket);
+
+    /**
+     * click获取分销二维码事件
+     * @param fromUserName 发送方帐号(一个OpenID)
+     * @param toUserName 开发者微信号
+     * @param token 凭证
+     * @return
+     */
+    String gainTicketEvent(String fromUserName,String toUserName,String token);
+
+
+}

+ 5 - 17
twzd-service/src/main/java/com/miaxis/wx/service/impl/WxGzhServiceImpl.java

@@ -12,6 +12,7 @@ import com.miaxis.feign.service.IWxSendService;
 import com.miaxis.wx.domain.WxMenu;
 import com.miaxis.wx.mapper.WxMenuMapper;
 import com.miaxis.wx.service.IWxGzhService;
+import com.miaxis.wx.service.IWxMessageEvenService;
 import com.qcloud.cos.COSClient;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -21,18 +22,8 @@ import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Service;
 
 import javax.servlet.http.HttpServletRequest;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.transform.OutputKeys;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
-import java.io.StringWriter;
-import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -54,7 +45,7 @@ public class WxGzhServiceImpl implements IWxGzhService {
 
     private final COSClient cosClient;
 
-    private final IWxMpService wxMpService;
+    private final IWxMessageEvenService wxMessageEvenService;
 
     @Value("${app.appid}")
     private String appid;
@@ -188,18 +179,15 @@ public class WxGzhServiceImpl implements IWxGzhService {
                 String event = jsonObjectData.getStr("Event");
                 if (MessageUtil.MESSAGE_SUBSCRIBE.equals(event)) { // 关注事件 或 扫描二维码关注事件
                     log.info("3.1...");
-                    String content = "";
-
                     //存在Ticket为扫码关注
                     if (org.apache.commons.lang3.StringUtils.isNotEmpty(jsonObjectData.getStr("Ticket"))){
                         log.info("3.1.2..");
-                        content = "扫描二维码关注事件";
                         //根据Ticket  推送绑定信息到上级用户
                         //从缓存中获取Ticket用户信息
+
                     }else {
-                        content = "关注事件";
+                        return MessageUtil.initText(fromUserName, toUserName, "关注事件");
                     }
-                    return MessageUtil.initText(fromUserName, toUserName, content);
 
                 }  else if (MessageUtil.MESSAGE_UNSUBSCRIBE.equals(event)) { // 取消订阅事件
                     // todo 处理取消订阅事件
@@ -215,7 +203,7 @@ public class WxGzhServiceImpl implements IWxGzhService {
                     log.info("3.3.....click:" + jsonObjectData.get("EventKey"));
                     //判断事件KEY值,与自定义菜单接口中KEY值对应
                     if ("generateTicket".equals(jsonObjectData.get("EventKey"))){ //获取分销二维码
-                        return MessageUtil.initText(fromUserName, toUserName, "key: "+jsonObjectData.get("EventKey").toString());
+                        return wxMessageEvenService.gainTicketEvent(fromUserName,toUserName,this.getGzhToken());
                     }
 
                 } else if (MessageUtil.MESSAGE_VIEW.equals(event)) { // 点击菜单跳转链接时的事件推送

+ 145 - 0
twzd-service/src/main/java/com/miaxis/wx/service/impl/WxMessageEvenServiceImpl.java

@@ -0,0 +1,145 @@
+package com.miaxis.wx.service.impl;
+
+import cn.hutool.core.img.ImgUtil;
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.extra.qrcode.QrCodeUtil;
+import com.alibaba.fastjson.JSONObject;
+import com.miaxis.common.utils.http.HttpUtils;
+import com.miaxis.common.utils.wx.MessageUtil;
+import com.miaxis.feign.dto.WxTicket;
+import com.miaxis.feign.service.IWxMpService;
+import com.miaxis.feign.service.IWxSendService;
+import com.miaxis.wx.service.IWxMessageEvenService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Service;
+
+import java.awt.*;
+import java.io.File;
+
+/**
+ * @author wwl
+ * @version 1.0
+ * @date 2021/10/27 14:35
+ */
+@Service
+@Slf4j
+@RequiredArgsConstructor
+public class WxMessageEvenServiceImpl implements IWxMessageEvenService {
+
+    private final RedisTemplate redisTemplate;
+
+    private final IWxMpService wxMpService;
+
+    private final IWxSendService wxSendService;
+
+    @Value("${file.ticketPath}")
+    private String ticketPath;
+
+    @Value("${wxgzh.materialUrl}")
+    private String materialUrl;
+
+
+    /**
+     * 扫码关注事件
+     * @param fromUserName 发送方帐号(一个OpenID)
+     * @param toUserName 开发者微信号
+     * @param Ticket 二维码的ticket
+     * @return
+     */
+    @Override
+    public String scanSubscribeEvent(String fromUserName,String toUserName, String Ticket) {
+        return null;
+    }
+
+
+    /**
+     * click获取分销二维码事件
+     * @param fromUserName 发送方帐号(一个OpenID)
+     * @param toUserName 开发者微信号
+     * @param token 凭证
+     * @return
+     */
+    @Override
+    public String gainTicketEvent(String fromUserName,String toUserName,String token) {
+
+        //生成带参数二维码ticket
+        WxTicket wxTicket = new WxTicket();
+        wxTicket.setExpire_seconds(2592000);//30天
+        wxTicket.setAction_name("QR_SCENE");
+        JSONObject jsonObject1 = new JSONObject();
+        JSONObject jsonObject2 = new JSONObject();
+        jsonObject1.put("scene_id","123");
+        jsonObject2.put("scene",jsonObject1);
+        wxTicket.setAction_info(jsonObject2);
+        String wxTicketResult = wxSendService.generateTicket(token,wxTicket);
+        JSONObject jsonStr = JSONObject.parseObject(wxTicketResult);
+        log.info("---------ticket-------" + wxTicketResult);
+
+        //根据ticket生成二维码图片存储
+        File ticketFile = QrCodeUtil.generate(
+                jsonStr.getString("url"), //二维码内容
+                300, 300,
+                FileUtil.file(ticketPath + fromUserName + ".jpg")//写出到的文件
+        );
+
+        ImgUtil.pressImage(
+                FileUtil.file(ticketPath+"jinpai.jpg"),
+                FileUtil.file(ticketPath+fromUserName+"_img.jpg"),
+                ImgUtil.read(FileUtil.file(ticketPath+fromUserName+".jpg")), //水印图片
+                0, //x坐标修正值。 默认在中间,偏移量相对于中间偏移
+                -360, //y坐标修正值。 默认在中间,偏移量相对于中间偏移
+                1.0f
+        );
+
+        ImgUtil.pressText(
+                FileUtil.file(ticketPath+fromUserName+"_img.jpg"),
+                FileUtil.file(ticketPath+fromUserName+"_text.jpg"),
+                "openid:"+fromUserName, Color.red, //文字
+                new Font("黑体", Font.BOLD, 60), //字体
+                0, //x坐标修正值。 默认在中间,偏移量相对于中间偏移
+                400, //y坐标修正值。 默认在中间,偏移量相对于中间偏移
+                0.8f//透明度:alpha 必须是范围 [0.0, 1.0] 之内(包含边界值)的一个浮点数字
+        );
+
+
+        try {
+            File textFile = new File(ticketPath + fromUserName+"_text.jpg");
+            //上传素材
+            String path = materialUrl + token + "&type=image";
+            String result = HttpUtils.connectHttpsByPost(path,textFile);
+            result = result.replaceAll("[\\\\]", "");
+            JSONObject resultJSON = JSONObject.parseObject(result);
+            log.info("------result:" + resultJSON);
+
+            //上传完成删除服务器文件
+            File imgFile = new File(ticketPath + fromUserName+"_img.jpg");
+            if (ticketFile.exists() && imgFile.exists() && textFile.exists()) {
+                if (ticketFile.delete()) {
+                    log.info("删除:" + ticketFile.getName() + "成功!");
+                } else {
+                    log.info("删除:" + ticketFile.getName() + "失败!");
+                }
+                if (imgFile.delete()) {
+                    log.info("删除:" + imgFile.getName() + "成功!");
+                } else {
+                    log.info("删除:" + imgFile.getName() + "失败!");
+                }
+                if (textFile.delete()) {
+                    log.info("删除:" + textFile.getName() + "成功!");
+                } else {
+                    log.info("删除:" + textFile.getName() + "失败!");
+                }
+            }
+
+            return MessageUtil.initImage(fromUserName,toUserName,resultJSON.getString("media_id"));
+        } catch (Exception e) {
+            log.info("-----异常------click获取分销二维码事件");
+        }
+        return null;
+    }
+
+
+}