Browse Source

优化微信模版消息通知

Menethil 7 years ago
parent
commit
c839091837

+ 30 - 28
litemall-core/src/main/java/org/linlinjava/litemall/core/notify/NotifyService.java

@@ -71,38 +71,40 @@ public class NotifyService {
     }
 
     /**
-     * 微信模版消息通知
+     * 微信模版消息通知,不跳转
+     * <p>
+     * 该方法会尝试从数据库获取缓存的FormId去发送消息
      *
      * @param touser     接收者openId
-     * @param formId     表单ID或者 prepayId
      * @param notifyType 通知类别,通过该枚举值在配置文件中获取相应的模版ID
      * @param params     通知模版内容里的参数,类似"您的验证码为{1}"中{1}的值
      */
     @Async
-    public void notifyWxTemplate(String touser, String formId, NotifyType notifyType, String[] params) {
+    public void notifyWxTemplate(String touser, NotifyType notifyType, String[] params) {
         if (wxTemplateSender == null)
             return;
 
         String templateId = getTemplateId(notifyType, wxTemplate);
-        wxTemplateSender.sendWechatMsg(touser, templateId, formId, "", "", params);
+        wxTemplateSender.sendWechatMsg(touser, templateId, params);
     }
 
     /**
-     * 微信模版消息通知
+     * 微信模版消息通知,带跳转
      * <p>
      * 该方法会尝试从数据库获取缓存的FormId去发送消息
      *
      * @param touser     接收者openId
      * @param notifyType 通知类别,通过该枚举值在配置文件中获取相应的模版ID
      * @param params     通知模版内容里的参数,类似"您的验证码为{1}"中{1}的值
+     * @param page       点击消息跳转的页面
      */
     @Async
-    public void notifyWxTemplate(String touser, NotifyType notifyType, String[] params) {
+    public void notifyWxTemplate(String touser, NotifyType notifyType, String[] params, String page) {
         if (wxTemplateSender == null)
             return;
 
         String templateId = getTemplateId(notifyType, wxTemplate);
-        wxTemplateSender.sendWechatMsg(touser, templateId, params);
+        wxTemplateSender.sendWechatMsg(touser, templateId, params, page);
     }
 
     /**
@@ -135,57 +137,57 @@ public class NotifyService {
         return null;
     }
 
-    public MailSender getMailSender() {
-        return mailSender;
-    }
+//    public MailSender getMailSender() {
+//        return mailSender;
+//    }
 
     public void setMailSender(MailSender mailSender) {
         this.mailSender = mailSender;
     }
 
-    public String getSendFrom() {
-        return sendFrom;
-    }
+//    public String getSendFrom() {
+//        return sendFrom;
+//    }
 
     public void setSendFrom(String sendFrom) {
         this.sendFrom = sendFrom;
     }
 
-    public String getSendTo() {
-        return sendTo;
-    }
+//    public String getSendTo() {
+//        return sendTo;
+//    }
 
     public void setSendTo(String sendTo) {
         this.sendTo = sendTo;
     }
 
-    public SmsSender getSmsSender() {
-        return smsSender;
-    }
+//    public SmsSender getSmsSender() {
+//        return smsSender;
+//    }
 
     public void setSmsSender(SmsSender smsSender) {
         this.smsSender = smsSender;
     }
 
-    public List<Map<String, String>> getSmsTemplate() {
-        return smsTemplate;
-    }
+//    public List<Map<String, String>> getSmsTemplate() {
+//        return smsTemplate;
+//    }
 
     public void setSmsTemplate(List<Map<String, String>> smsTemplate) {
         this.smsTemplate = smsTemplate;
     }
 
-    public WxTemplateSender getWxTemplateSender() {
-        return wxTemplateSender;
-    }
+//    public WxTemplateSender getWxTemplateSender() {
+//        return wxTemplateSender;
+//    }
 
     public void setWxTemplateSender(WxTemplateSender wxTemplateSender) {
         this.wxTemplateSender = wxTemplateSender;
     }
 
-    public List<Map<String, String>> getWxTemplate() {
-        return wxTemplate;
-    }
+//    public List<Map<String, String>> getWxTemplate() {
+//        return wxTemplate;
+//    }
 
     public void setWxTemplate(List<Map<String, String>> wxTemplate) {
         this.wxTemplate = wxTemplate;

+ 31 - 126
litemall-core/src/main/java/org/linlinjava/litemall/core/notify/WxTemplateSender.java

@@ -1,21 +1,14 @@
 package org.linlinjava.litemall.core.notify;
 
 import cn.binarywang.wx.miniapp.api.WxMaService;
-import org.json.JSONObject;
+import cn.binarywang.wx.miniapp.bean.WxMaTemplateMessage;
+import me.chanjar.weixin.common.exception.WxErrorException;
 import org.linlinjava.litemall.db.domain.LitemallUserFormid;
 import org.linlinjava.litemall.db.service.LitemallUserFormIdService;
 import org.springframework.beans.factory.annotation.Autowired;
 
-import javax.net.ssl.*;
-import java.io.BufferedReader;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.net.ConnectException;
-import java.net.URL;
-import java.security.SecureRandom;
-import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * 微信模版消息通知
@@ -28,145 +21,57 @@ public class WxTemplateSender {
     LitemallUserFormIdService formIdService;
 
     /**
-     * 发送微信消息(模板消息)
+     * 发送微信消息(模板消息),不带跳转
      *
      * @param touser    用户 OpenID
      * @param templatId 模板消息ID
      * @param parms     详细内容
      */
     public void sendWechatMsg(String touser, String templatId, String[] parms) {
-        LitemallUserFormid userFormid = formIdService.queryByOpenId(touser);
-        if (userFormid == null)
-            return;
-        sendWechatMsg(touser, templatId, userFormid.getFormid(), "", "", parms);
-
-        formIdService.delUserFormid(userFormid.getId());
+        sendMsg(touser, templatId, parms, "", "", "");
     }
 
     /**
-     * 发送微信消息(模板消息)
+     * 发送微信消息(模板消息),带跳转
      *
      * @param touser    用户 OpenID
      * @param templatId 模板消息ID
-     * @param formId    payId或者表单ID
-     * @param clickurl  URL置空,则在发送后,点击模板消息会进入一个空白页面(ios),或无法点击(android)。
-     * @param topcolor  标题颜色
      * @param parms     详细内容
-     * @return
+     * @param page      跳转页面
      */
-    public String sendWechatMsg(String touser, String templatId, String formId, String clickurl, String topcolor, String[] parms) {
-        try {
-            String tmpurl = "https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token=" + wxMaService.getAccessToken();
-            JSONObject json = new JSONObject();
-            json.put("touser", touser);
-            json.put("template_id", templatId);
-            json.put("form_id", formId);
-            json.put("url", clickurl);
-            json.put("topcolor", topcolor);
-            json.put("data", createParmData(parms));
-
-            JSONObject result = httpsRequest(tmpurl, "POST", json.toString());
-//            log.info("发送微信消息返回信息:" + resultJson.get("errcode"));
-            String errmsg = (String) result.get("errmsg");
-            if (!"ok".equals(errmsg)) {  //如果为errmsg为ok,则代表发送成功,公众号推送信息给用户了。
-                return "error";
-            }
-        } catch (Exception e) {
-            e.printStackTrace();
-            return "error";
-        }
-        return "success";
+    public void sendWechatMsg(String touser, String templatId, String[] parms, String page) {
+        sendMsg(touser, templatId, parms, page, "", "");
     }
 
-    /**
-     * 根据参数生成对应的 json 数据
-     *
-     * @param parms
-     * @return
-     */
-    private JSONObject createParmData(String[] parms) {
-        JSONObject json = new JSONObject();
-        for (int i = 1; i <= parms.length; i++) {
-            JSONObject json2 = new JSONObject();
-            json2.put("value", parms[i - 1]);
+    private void sendMsg(String touser, String templatId, String[] parms, String page, String color, String emphasisKeyword) {
+        LitemallUserFormid userFormid = formIdService.queryByOpenId(touser);
+        if (userFormid == null)
+            return;
 
-            json.put("keyword" + i, json2);
-        }
 
-        return json;
-    }
+        WxMaTemplateMessage msg = new WxMaTemplateMessage();
+        msg.setTemplateId(templatId);
+        msg.setToUser(touser);
+        msg.setFormId(userFormid.getFormid());
+        msg.setPage(page);
+        msg.setColor(color);
+        msg.setEmphasisKeyword(emphasisKeyword);
+        msg.setData(createMsgData(parms));
 
-    /**
-     * 发送https请求
-     *
-     * @param requestUrl    请求地址
-     * @param requestMethod 请求方式(GET、POST)
-     * @param outputStr     提交的数据
-     * @return JSONObject(通过JSONObject.get ( key)的方式获取json对象的属性值)
-     */
-    private JSONObject httpsRequest(String requestUrl, String requestMethod, String outputStr) {
-        JSONObject jsonObject = null;
         try {
-            // 创建SSLContext对象,并使用我们指定的信任管理器初始化
-            TrustManager[] tm = {new MyX509TrustManager()};
-            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
-            sslContext.init(null, tm, new SecureRandom());
-            // 从上述SSLContext对象中得到SSLSocketFactory对象
-            SSLSocketFactory ssf = sslContext.getSocketFactory();
-            URL url = new URL(requestUrl);
-            HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
-            conn.setSSLSocketFactory(ssf);
-            conn.setDoOutput(true);
-            conn.setDoInput(true);
-            conn.setUseCaches(false);
-            // 设置请求方式(GET/POST)
-            conn.setRequestMethod(requestMethod);
-            // 当outputStr不为null时向输出流写数据
-            if (null != outputStr) {
-                OutputStream outputStream = conn.getOutputStream();
-                // 注意编码格式
-                outputStream.write(outputStr.getBytes("UTF-8"));
-                outputStream.close();
-            }
-            // 从输入流读取返回内容
-            InputStream inputStream = conn.getInputStream();
-            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
-            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
-            String str = null;
-            StringBuffer buffer = new StringBuffer();
-            while ((str = bufferedReader.readLine()) != null) {
-                buffer.append(str);
-            }
-            // 释放资源
-            bufferedReader.close();
-            inputStreamReader.close();
-            inputStream.close();
-            inputStream = null;
-            conn.disconnect();
-            jsonObject = new JSONObject(buffer.toString());
-        } catch (ConnectException ce) {
-//            log.error("连接超时:{}", ce);
-        } catch (Exception e) {
-//            log.error("https请求异常:{}", e);
+            wxMaService.getMsgService().sendTemplateMsg(msg);
+            formIdService.updateUserFormId(userFormid);
+        } catch (WxErrorException e) {
+            e.printStackTrace();
         }
-        return jsonObject;
     }
 
-    /**
-     * 微信请求 - 信任管理器
-     */
-    private class MyX509TrustManager implements X509TrustManager {
-        @Override
-        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
-        }
-
-        @Override
-        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
+    private List<WxMaTemplateMessage.Data> createMsgData(String[] parms) {
+        List<WxMaTemplateMessage.Data> dataList = new ArrayList<>();
+        for (int i = 1; i <= parms.length; i++) {
+            dataList.add(new WxMaTemplateMessage.Data("keyword" + i, parms[i - 1]));
         }
 
-        @Override
-        public X509Certificate[] getAcceptedIssuers() {
-            return null;
-        }
+        return dataList;
     }
 }

+ 1 - 2
litemall-core/src/test/java/org/linlinjava/litemall/core/WxTemplateTest.java

@@ -22,9 +22,8 @@ public class WxTemplateTest {
     @Test
     public void testPaySucceed() {
         String touser = "xx";
-        String formId = "";
         String[] params = new String[]{"xxx"};
-        notifyService.notifyWxTemplate(touser, formId, NotifyType.PAY_SUCCEED, params);
+        notifyService.notifyWxTemplate(touser, NotifyType.PAY_SUCCEED, params);
         try {
             Thread.sleep(5000);
         } catch (InterruptedException e) {

+ 13 - 7
litemall-db/src/main/java/org/linlinjava/litemall/db/service/LitemallUserFormIdService.java

@@ -27,20 +27,26 @@ public class LitemallUserFormIdService {
     }
 
     /**
-     * 添加一个 FormId
+     * 更新或删除FormId
      *
      * @param userFormid
      */
-    public void addUserFormid(LitemallUserFormid userFormid) {
-        formidMapper.insertSelective(userFormid);
+    public void updateUserFormId(LitemallUserFormid userFormid) {
+        //更新或者删除缓存
+        if (userFormid.getIsprepay() && userFormid.getUseamount() > 1) {
+            userFormid.setUseamount(userFormid.getUseamount() - 1);
+            formidMapper.updateByPrimaryKey(userFormid);
+        } else {
+            formidMapper.deleteByPrimaryKey(userFormid.getId());
+        }
     }
 
     /**
-     * 删除一个 FormId
+     * 添加一个 FormId
      *
-     * @param userFormidId
+     * @param userFormid
      */
-    public void delUserFormid(Integer userFormidId) {
-        formidMapper.deleteByPrimaryKey(userFormidId);
+    public void addUserFormid(LitemallUserFormid userFormid) {
+        formidMapper.insertSelective(userFormid);
     }
 }

+ 29 - 0
litemall-wx-api/src/main/java/org/linlinjava/litemall/wx/web/WxOrderController.java

@@ -85,6 +85,9 @@ public class WxOrderController {
     @Autowired
     private NotifyService notifyService;
 
+    @Autowired
+    LitemallUserFormIdService formIdService;
+
     public WxOrderController() {
     }
 
@@ -500,6 +503,18 @@ public class WxOrderController {
             orderRequest.setSpbillCreateIp(IpUtil.getIpAddr(request));
 
             result = wxPayService.createOrder(orderRequest);
+
+            //缓存prepayID用于后续模版通知
+            String prepayId = result.getPackageValue();
+            prepayId = prepayId.replace("prepay_id=", "");
+            LitemallUserFormid userFormid = new LitemallUserFormid();
+            userFormid.setOpenid(user.getWeixinOpenid());
+            userFormid.setFormid(prepayId);
+            userFormid.setIsprepay(true);
+            userFormid.setUseamount(3);
+            userFormid.setExpireTime(LocalDateTime.now().plusDays(7));
+            formIdService.addUserFormid(userFormid);
+
         } catch (Exception e) {
             e.printStackTrace();
             return ResponseUtil.fail(403, "订单不能支付");
@@ -563,6 +578,20 @@ public class WxOrderController {
              */
             notifyService.notifySmsTemplateSync(order.getMobile(), NotifyType.PAY_SUCCEED, new String[]{orderSn.substring(8, 14)});
 
+            /**
+             * 请依据自己的模版消息配置更改参数
+             */
+            String[] parms = new String[]{
+                    order.getOrderSn(),
+                    order.getOrderPrice().toString(),
+                    order.getAddTime().toString(),
+                    order.getMobile(),
+                    order.getAddress(),
+                    order.getConsignee()
+            };
+
+            notifyService.notifyWxTemplate(result.getOpenid(), NotifyType.PAY_SUCCEED, parms, "/pages/index/index?orderId=" + order.getId());
+
             return WxPayNotifyResponse.success("处理成功!");
         } catch (Exception e) {
             logger.error("微信回调结果异常,异常原因 " + e.getMessage());

+ 1 - 0
litemall-wx-api/src/main/java/org/linlinjava/litemall/wx/web/WxUserFormId.java

@@ -40,6 +40,7 @@ public class WxUserFormId {
         userFormid.setUseamount(1);
         userFormid.setExpireTime(LocalDateTime.now().plusDays(7));
         formIdService.addUserFormid(userFormid);
+
         return ResponseUtil.ok();
     }
 }