瀏覽代碼

微信通知API

qxp192083 5 年之前
父節點
當前提交
7a4cdd80b5
共有 21 個文件被更改,包括 968 次插入152 次删除
  1. 3 0
      suishenbang-api/src/main/resources/application-dev.yml
  2. 2 0
      suishenbang-api/src/main/resources/application-test.yml
  3. 0 125
      suishenbang-apiframework/src/main/java/com/dgtly/apiframework/util/QyWeixinUtil.java
  4. 0 22
      suishenbang-common/src/main/java/com/dgtly/common/exception/api/QyWeixinException.java
  5. 156 0
      suishenbang-common/src/main/java/com/dgtly/common/utils/http/HttpUtils.java
  6. 71 5
      suishenbang-wxportal/suishenbang-wxportal-api/src/main/java/com/dgtly/wxportal/controller/WxController.java
  7. 14 0
      suishenbang-wxportal/suishenbang-wxportal-common/src/main/java/com/dgtly/wxportal/exception/QyWeixinException.java
  8. 2 0
      suishenbang-wxportal/suishenbang-wxportal-common/src/main/java/com/dgtly/wxportal/mapper/WxQyUserMapper.java
  9. 2 0
      suishenbang-wxportal/suishenbang-wxportal-common/src/main/java/com/dgtly/wxportal/service/IWxQyUserService.java
  10. 5 0
      suishenbang-wxportal/suishenbang-wxportal-common/src/main/java/com/dgtly/wxportal/service/impl/WxQyUserServiceImpl.java
  11. 139 0
      suishenbang-wxportal/suishenbang-wxportal-common/src/main/java/com/dgtly/wxportal/utils/qywxutils/ErrCode.java
  12. 99 0
      suishenbang-wxportal/suishenbang-wxportal-common/src/main/java/com/dgtly/wxportal/utils/qywxutils/QyWxAccessTokenUtil.java
  13. 36 0
      suishenbang-wxportal/suishenbang-wxportal-common/src/main/java/com/dgtly/wxportal/utils/qywxutils/QyWxSendMessageUtil.java
  14. 71 0
      suishenbang-wxportal/suishenbang-wxportal-common/src/main/java/com/dgtly/wxportal/utils/qywxutils/QyWxServiceUrl.java
  15. 85 0
      suishenbang-wxportal/suishenbang-wxportal-common/src/main/java/com/dgtly/wxportal/utils/qywxutils/QyWxUserUtil.java
  16. 118 0
      suishenbang-wxportal/suishenbang-wxportal-common/src/main/java/com/dgtly/wxportal/utils/qywxutils/messageModel/QyWxBaseMessage.java
  17. 43 0
      suishenbang-wxportal/suishenbang-wxportal-common/src/main/java/com/dgtly/wxportal/utils/qywxutils/messageModel/QyWxTextCard.java
  18. 26 0
      suishenbang-wxportal/suishenbang-wxportal-common/src/main/java/com/dgtly/wxportal/utils/qywxutils/messageModel/QyWxTextCardMessage.java
  19. 13 0
      suishenbang-wxportal/suishenbang-wxportal-common/src/main/java/com/dgtly/wxportal/utils/qywxutils/messageModel/QyWxTextContent.java
  20. 78 0
      suishenbang-wxportal/suishenbang-wxportal-common/src/main/java/com/dgtly/wxportal/utils/qywxutils/messageModel/QyWxTextMessage.java
  21. 5 0
      suishenbang-wxportal/suishenbang-wxportal-common/src/main/resources/mapper/wxportal/WxQyUserMapper.xml

+ 3 - 0
suishenbang-api/src/main/resources/application-dev.yml

@@ -98,4 +98,7 @@ qiyeweixin:
   #企业微信id
   corpid: wx5fd543ad17678381
   #企业应用的凭证密钥
+  #Cs9omiMVyz3cLm2D5T51i4bCDarHhIdl5uTaj__E-38  随身邦
   corpsecret: Cs9omiMVyz3cLm2D5T51i4bCDarHhIdl5uTaj__E-38
+  #应用id
+  agentId: 1000038

+ 2 - 0
suishenbang-api/src/main/resources/application-test.yml

@@ -99,3 +99,5 @@ qiyeweixin:
   corpid: wx5fd543ad17678381
   #企业应用的凭证密钥
   corpsecret: Cs9omiMVyz3cLm2D5T51i4bCDarHhIdl5uTaj__E-38
+  #应用id
+  agentId: 1000038

+ 0 - 125
suishenbang-apiframework/src/main/java/com/dgtly/apiframework/util/QyWeixinUtil.java

@@ -1,125 +0,0 @@
-package com.dgtly.apiframework.util;
-
-import com.alibaba.fastjson.JSONObject;
-import com.dgtly.common.exception.api.QyWeixinException;
-import com.dgtly.common.utils.RedisUtil;
-import com.dgtly.common.utils.http.HttpUtils;
-import com.dgtly.wxportal.domain.WxQyUser;
-import com.dgtly.wxportal.service.IWxQyUserService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Component;
-
-
-/**
- * 企业微信工具类
- */
-@Component
-public class QyWeixinUtil {
-
-    @Autowired
-    private RedisUtil redisUtil;
-
-    @Autowired
-    private IWxQyUserService wxQyUserService;
-
-    private String redis_qywxtoken_key="QYWX_ACCESS_TOKEN";
-
-    //获取access_token的接口地址(GET) 限200(次/天)
-    private String access_token_url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=%s&corpsecret=%s";
-
-    //获取用户信息url
-    private String getuserinfo_url = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?access_token=%s&code=%s";
-
-    //网页授权链接
-    private String oauth2_url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=snsapi_base&state=%s#wechat_redirect";
-
-
-    //获取用户详细信息
-    private String getUser_url = "https://qyapi.weixin.qq.com/cgi-bin/user/get?access_token=%s&userid=%s";
-
-
-    @Value(value = "${qiyeweixin.corpid}")
-    private String corpid;
-
-
-
-    @Value(value = "${qiyeweixin.corpsecret}")
-    private String corpsecret;
-
-    /**
-     * 获取access_token
-     * @return
-     */
-    public String getAccessToken() {
-        if(redisUtil.hasKey(redis_qywxtoken_key)){
-            return redisUtil.get(redis_qywxtoken_key).toString();
-        }
-        String url = String.format(access_token_url,corpid,corpsecret );
-        JSONObject json = JSONObject.parseObject(HttpUtils.sendGet(url));
-        Integer errcode = json.getInteger("errcode");
-        if(errcode!=0){
-            throw new QyWeixinException(errcode,json.getString("errmsg"),url);
-        }
-        String token = json.getString("access_token");
-        redisUtil.set(redis_qywxtoken_key,token,json.getLong("expires_in"));
-
-        return token;
-    }
-
-    /**
-     * 获取企业微信用户的userId
-     * @return
-     */
-    public JSONObject getUserId(String code) {
-        String url = String.format(getuserinfo_url,getAccessToken(),code );
-
-        JSONObject json  = JSONObject.parseObject(HttpUtils.sendGet(url));
-        Integer errcode = json.getInteger("errcode");
-        if(errcode!=0){
-            throw new QyWeixinException(errcode,json.getString("errmsg"),url);
-        }
-        /*
-        * 当用户为企业成员时返回示例如下:
-        * {
-        *   "errcode": 0,
-        *   "errmsg": "ok",
-        *   "UserId":"USERID",
-        *   "DeviceId":"DEVICEID"
-        *   }
-        *
-        * 非企业成员授权时返回示例如下:
-        * {
-        *   "errcode": 0,
-        *   "errmsg": "ok",
-        *   "OpenId":"OPENID",
-        *   "DeviceId":"DEVICEID"
-        *   }
-        *
-        * */
-
-        return json;
-    }
-
-    public String getOauth2Url(String redirect,String state){
-        return String.format(oauth2_url,corpid,redirect,state);
-    }
-
-    public WxQyUser gerUserDetail(String userId){
-        String url =  String.format(getUser_url,getAccessToken(),userId);
-
-        String result = HttpUtils.sendGet(url);
-
-        JSONObject json = JSONObject.parseObject(result);
-
-        Integer errcode = json.getInteger("errcode");
-        if(errcode!=0){
-            throw new QyWeixinException(errcode,json.getString("errmsg"),url);
-        }
-        WxQyUser wxQyUser = JSONObject.parseObject(result,WxQyUser.class);
-        wxQyUser.setJson(result);
-        return wxQyUser;
-
-    }
-
-}

+ 0 - 22
suishenbang-common/src/main/java/com/dgtly/common/exception/api/QyWeixinException.java

@@ -1,22 +0,0 @@
-package com.dgtly.common.exception.api;
-
-import com.dgtly.common.exception.BusinessException;
-
-public class QyWeixinException extends RuntimeException {
-
-    private Integer errcode;
-
-    private String errmsg;
-
-    private String message;
-
-    public QyWeixinException(Integer errcode,String errmsg,String url) {
-
-        super("企业微信API访问返回异常,请求地址为:"+url+"异常代码errcode:"+errcode+"---errmsg:"+errmsg,new Throwable());
-
-        this.errcode = errcode;
-        this.errmsg =errmsg;
-    }
-
-
-}

+ 156 - 0
suishenbang-common/src/main/java/com/dgtly/common/utils/http/HttpUtils.java

@@ -10,14 +10,18 @@ import java.net.SocketTimeoutException;
 import java.net.URL;
 import java.net.URLConnection;
 import java.security.cert.X509Certificate;
+import java.text.ParseException;
 import javax.net.ssl.HostnameVerifier;
 import javax.net.ssl.HttpsURLConnection;
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLSession;
 import javax.net.ssl.TrustManager;
 import javax.net.ssl.X509TrustManager;
+
+import com.alibaba.fastjson.JSONObject;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpEntity;
 
 /**
  * 通用http发送方法
@@ -169,6 +173,80 @@ public class HttpUtils
         return result.toString();
     }
 
+    /**
+     * 向指定 URL 发送POST方法的请求
+     *
+     * @param url 发送请求的 URL
+     * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
+     * @return 所代表远程资源的响应结果
+     */
+    public static String sendPost(String url, Object param)
+    {
+        PrintWriter out = null;
+        BufferedReader in = null;
+        StringBuilder result = new StringBuilder();
+        try
+        {
+            log.info("sendPost - {}", url);
+            URL realUrl = new URL(url);
+            URLConnection conn = realUrl.openConnection();
+            conn.setRequestProperty("accept", "*/*");
+            conn.setRequestProperty("connection", "Keep-Alive");
+            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
+            conn.setRequestProperty("Accept-Charset", "utf-8");
+            conn.setRequestProperty("contentType", "utf-8");
+            conn.setDoOutput(true);
+            conn.setDoInput(true);
+            out = new PrintWriter(conn.getOutputStream());
+            out.print(param);
+            out.flush();
+            in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));
+            String line;
+            while ((line = in.readLine()) != null)
+            {
+                result.append(line);
+            }
+            log.info("recv - {}", result);
+        }
+        catch (ConnectException e)
+        {
+            log.error("调用HttpUtils.sendPost ConnectException, url=" + url + ",param=" + param, e);
+        }
+        catch (SocketTimeoutException e)
+        {
+            log.error("调用HttpUtils.sendPost SocketTimeoutException, url=" + url + ",param=" + param, e);
+        }
+        catch (IOException e)
+        {
+            log.error("调用HttpUtils.sendPost IOException, url=" + url + ",param=" + param, e);
+        }
+        catch (Exception e)
+        {
+            log.error("调用HttpsUtil.sendPost Exception, url=" + url + ",param=" + param, e);
+        }
+        finally
+        {
+            try
+            {
+                if (out != null)
+                {
+                    out.close();
+                }
+                if (in != null)
+                {
+                    in.close();
+                }
+            }
+            catch (IOException ex)
+            {
+                log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);
+            }
+        }
+        return result.toString();
+    }
+
+
+
     public static String sendSSLPost(String url, String param)
     {
         StringBuilder result = new StringBuilder();
@@ -251,4 +329,82 @@ public class HttpUtils
             return true;
         }
     }
+
+    /**
+     * 向指定 URL 发送POST方法的请求
+     *
+     * @param url 发送请求的 URL
+     * @param param 请求参数,
+     * @return 所代表远程资源的响应结果
+     */
+    public static String sendJsonPost(String url, Object param)
+    {
+        String json = JSONObject.toJSONString(param);
+        PrintWriter out = null;
+        BufferedReader in = null;
+        StringBuilder result = new StringBuilder();
+        try
+        {
+            log.info("sendPost - {}", url);
+            URL realUrl = new URL(url);
+            URLConnection conn = realUrl.openConnection();
+            conn.setRequestProperty("accept", "*/*");
+            conn.setRequestProperty("connection", "Keep-Alive");
+            conn.setRequestProperty("Content-Type", "application/json");
+            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
+            conn.setRequestProperty("Accept-Charset", "utf-8");
+            conn.setRequestProperty("contentType", "utf-8");
+            conn.setUseCaches(false);//设置不要缓存
+            conn.setDoOutput(true);
+            conn.setDoInput(true);
+            out = new PrintWriter(conn.getOutputStream());
+            out.write(json);
+            out.flush();
+            in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));
+            String line;
+            while ((line = in.readLine()) != null)
+            {
+                result.append(line);
+            }
+            log.info("recv - {}", result);
+        }
+        catch (ConnectException e)
+        {
+            log.error("调用HttpUtils.sendJsonPost ConnectException, url=" + url + ",param=" + param, e);
+        }
+        catch (SocketTimeoutException e)
+        {
+            log.error("调用HttpUtils.sendJsonPost SocketTimeoutException, url=" + url + ",param=" + param, e);
+        }
+        catch (IOException e)
+        {
+            log.error("调用HttpUtils.sendJsonPost IOException, url=" + url + ",param=" + param, e);
+        }
+        catch (Exception e)
+        {
+            log.error("调用HttpsUtil.sendJsonPost Exception, url=" + url + ",param=" + param, e);
+        }
+        finally
+        {
+            try
+            {
+                if (out != null)
+                {
+                    out.close();
+                }
+                if (in != null)
+                {
+                    in.close();
+                }
+            }
+            catch (IOException ex)
+            {
+                log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);
+            }
+        }
+        return result.toString();
+    }
+
+
+
 }

+ 71 - 5
suishenbang-wxportal/suishenbang-wxportal-api/src/main/java/com/dgtly/wxportal/controller/WxController.java

@@ -5,12 +5,16 @@ import com.dgtly.common.annotation.ApiPassToken;
 import com.dgtly.common.core.controller.ApiBaseController;
 import com.dgtly.common.core.domain.AjaxResult;
 import com.dgtly.common.core.domain.ParameterObject;
-import com.dgtly.apiframework.util.QyWeixinUtil;
+import com.dgtly.wxportal.utils.qywxutils.QyWxSendMessageUtil;
+import com.dgtly.wxportal.utils.qywxutils.QyWxUserUtil;
 import com.dgtly.common.utils.RedisUtil;
 import com.dgtly.system.domain.SysUser;
 import com.dgtly.wxportal.domain.WxQyUser;
 import com.dgtly.system.service.ISysUserService;
 import com.dgtly.wxportal.service.IWxQyUserService;
+import com.dgtly.wxportal.utils.qywxutils.messageModel.QyWxTextCard;
+import com.dgtly.wxportal.utils.qywxutils.messageModel.QyWxTextCardMessage;
+import com.dgtly.wxportal.utils.qywxutils.messageModel.QyWxTextMessage;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiImplicitParams;
@@ -32,13 +36,17 @@ public class WxController extends ApiBaseController {
     private RedisUtil redisUtil;
 
     @Autowired
-    private QyWeixinUtil qyWeixinUtil;
+    private QyWxUserUtil qyWxUserUtil;
 
     @Autowired
     private IWxQyUserService wxQyUserService;
     @Autowired
     private ISysUserService sysUserService;
 
+    @Autowired
+    private QyWxSendMessageUtil qyWxSendMessageUtil;
+
+
 
     @ApiOperation(value = "获取微信授权跳转url",notes = "参数:{url:www.baidu.com}")
     @ApiImplicitParams({
@@ -48,7 +56,7 @@ public class WxController extends ApiBaseController {
     public Object getOauthUrl(){
         ParameterObject obj =  getParameterObject();
         obj.checkParameterNotNull("url");
-        String oauth2Url =  qyWeixinUtil.getOauth2Url(obj.getString("url"),null);
+        String oauth2Url =  qyWxUserUtil.getOauth2Url(obj.getString("url"),null);
         return AjaxResult.success().putKV("oauth2Url",oauth2Url);
     }
 
@@ -64,13 +72,13 @@ public class WxController extends ApiBaseController {
         ParameterObject obj =  getParameterObject();
         obj.checkParameterNotNull("code");
         String code = obj.getString("code");
-        JSONObject json =  qyWeixinUtil.getUserId(code);
+        JSONObject json =  qyWxUserUtil.getUserId(code);
         String userId ="";
         if(!json.containsKey("UserId")){
             return AjaxResult.error(301,"当前用户不是企业成员");
         }
         userId = json.getString("UserId");
-        WxQyUser wxQyUser = qyWeixinUtil.gerUserDetail(userId);
+        WxQyUser wxQyUser = qyWxUserUtil.gerUserDetail(userId);
         WxQyUser resWxQyUser = wxQyUserService.selectWxQyUserById(wxQyUser.getUserid());
         if(resWxQyUser==null){
             int i = wxQyUserService.insertWxQyUser(wxQyUser);
@@ -98,5 +106,63 @@ public class WxController extends ApiBaseController {
 
 
 
+    @ApiOperation(value = "根据用户userId发送文本",
+            notes = "参数:{userId:123," +
+                    "content:\"XXXXXXXXXXXXXXXXXX\"} " +
+                    "错误:301 当前用户未绑定企业微信")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "params" , paramType = "body")
+    })
+    @PostMapping("sendTextMessage")
+    public Object sendTextMessage(){
+        ParameterObject obj =  getParameterObject();
+        obj.checkParameterNotNull("userId,content");
+        String userId = obj.getString("userId");
+        WxQyUser wxQyUser = wxQyUserService.selectWxQyUserBySysUserId(userId);
+        if(wxQyUser==null){
+            logger.error("发送企业微信细信息对象为空");
+            return AjaxResult.error(301,"发送对象位绑定企业微信");
+        }
+        QyWxTextMessage qyWxTextMessage = new QyWxTextMessage();
+        qyWxTextMessage.setTouser(wxQyUser.getUserid());
+        qyWxTextMessage.setText(obj.getString("content"));
+
+        qyWxSendMessageUtil.sendMessage(qyWxTextMessage);
+        return AjaxResult.success();
+    }
+
+    @ApiOperation(value = "根据用户userId发送文本card",
+            notes = "参数:{userId:123," +
+                    "title:\"标题,不超过128个字节\"," +
+                    "description:\"描述,不超过512个字节\"" +
+                    "url:\"点击后跳转的链接。\"," +
+                    "btntxt:\"按钮文字。 默认为“详情”, 不超过4个文字\"} " +
+                    "错误:301 当前用户未绑定企业微信")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "params" , paramType = "body")
+    })
+    @PostMapping("sendTextCardMessage")
+    public Object sendTextCardMessage(){
+        ParameterObject obj =  getParameterObject();
+        obj.checkParameterNotNull("userId,title,description,url");
+        String userId = obj.getString("userId");
+
+        QyWxTextCard tc = obj.parseBean(QyWxTextCard.class);
+
+        WxQyUser wxQyUser = wxQyUserService.selectWxQyUserBySysUserId(userId);
+        if(wxQyUser==null){
+            logger.error("发送企业微信细信息对象为空");
+            return AjaxResult.error(301,"发送对象位绑定企业微信");
+        }
+        QyWxTextCardMessage q = new QyWxTextCardMessage();
+
+        q.setTouser(wxQyUser.getUserid());
+        q.setTextcard(tc);
+        qyWxSendMessageUtil.sendMessage(q);
+        return AjaxResult.success();
+    }
+
+
+
 
 }

+ 14 - 0
suishenbang-wxportal/suishenbang-wxportal-common/src/main/java/com/dgtly/wxportal/exception/QyWeixinException.java

@@ -0,0 +1,14 @@
+package com.dgtly.wxportal.exception;
+
+import com.dgtly.common.exception.BusinessException;
+import com.dgtly.wxportal.utils.qywxutils.ErrCode;
+
+public class QyWeixinException extends BusinessException{
+
+    public QyWeixinException(String errcode,String url) {
+        super("企业微信API访问返回异常,请求地址为:"+url+"异常代码errcode:"+errcode+"---errmsg:"+ErrCode.errMsg(errcode),new Throwable());
+    }
+    public QyWeixinException(Integer errcode,String url) {
+        super("企业微信API访问返回异常,请求地址为:"+url+"异常代码errcode:"+errcode+"---errmsg:"+ErrCode.errMsg(errcode),new Throwable());
+    }
+}

+ 2 - 0
suishenbang-wxportal/suishenbang-wxportal-common/src/main/java/com/dgtly/wxportal/mapper/WxQyUserMapper.java

@@ -27,6 +27,8 @@ public interface WxQyUserMapper
      */
     public WxQyUser selectWxQyUserById(String userid);
 
+    public WxQyUser selectWxQyUserBySysUserId(String sysUserId);
+
     /**
      * 查询企业微信用户信息列表
      * 

+ 2 - 0
suishenbang-wxportal/suishenbang-wxportal-common/src/main/java/com/dgtly/wxportal/service/IWxQyUserService.java

@@ -26,6 +26,8 @@ public interface IWxQyUserService
      */
     public WxQyUser selectWxQyUserById(String userid);
 
+    public WxQyUser selectWxQyUserBySysUserId(String userId);
+
     /**
      * 查询企业微信用户信息列表
      * 

+ 5 - 0
suishenbang-wxportal/suishenbang-wxportal-common/src/main/java/com/dgtly/wxportal/service/impl/WxQyUserServiceImpl.java

@@ -43,6 +43,11 @@ public class WxQyUserServiceImpl implements IWxQyUserService
         return wxQyUserMapper.selectWxQyUserById(userid);
     }
 
+    @Override
+    public WxQyUser selectWxQyUserBySysUserId(String sysUserId) {
+        return wxQyUserMapper.selectWxQyUserBySysUserId(sysUserId);
+    }
+
     /**
      * 查询企业微信用户信息列表
      * 

+ 139 - 0
suishenbang-wxportal/suishenbang-wxportal-common/src/main/java/com/dgtly/wxportal/utils/qywxutils/ErrCode.java

@@ -0,0 +1,139 @@
+/*
+ * FileName:ErrCode.java 
+ * <p>
+ * Copyright (c) 2017-2020 <a href="https://www.smartwx.info">hermit(1154808491@qq.com)</a>.
+ * <p>
+ * Licensed under the GNU General Public License, Version 3 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * <p>
+ * http://www.gnu.org/licenses/gpl-3.0.html
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ */
+package com.dgtly.wxportal.utils.qywxutils;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 微信公众平台全局返回码说明
+ */
+public class ErrCode {
+	
+	private static Map<String,String> codeMap = new HashMap<String,String>();
+	
+	static {
+		codeMap.put("-1","系统繁忙");
+		codeMap.put("0","请求成功");
+		codeMap.put("40001","获取access_token时AppSecret错误,或者access_token无效");
+		codeMap.put("40002","不合法的凭证类型");
+		codeMap.put("40003","不合法的OpenID");
+		codeMap.put("40004","不合法的媒体文件类型");
+		codeMap.put("40005","不合法的文件类型");
+		codeMap.put("40006","不合法的文件大小");
+		codeMap.put("40007","不合法的媒体文件id");
+		codeMap.put("40008","不合法的消息类型");
+		codeMap.put("40009","不合法的图片文件大小");
+		codeMap.put("40010","不合法的语音文件大小");
+		codeMap.put("40011","不合法的视频文件大小");
+		codeMap.put("40012","不合法的缩略图文件大小");
+		codeMap.put("40013","不合法的APPID");
+		codeMap.put("40014","不合法的access_token");
+		codeMap.put("40015","不合法的菜单类型");
+		codeMap.put("40016","不合法的按钮个数");
+		codeMap.put("40017","不合法的按钮个数");
+		codeMap.put("40018","不合法的按钮名字长度");
+		codeMap.put("40019","不合法的按钮KEY长度");
+		codeMap.put("40020","不合法的按钮URL长度");
+		codeMap.put("40021","不合法的菜单版本号");
+		codeMap.put("40022","不合法的子菜单级数");
+		codeMap.put("40023","不合法的子菜单按钮个数");
+		codeMap.put("40024","不合法的子菜单按钮类型");
+		codeMap.put("40025","不合法的子菜单按钮名字长度");
+		codeMap.put("40026","不合法的子菜单按钮KEY长度");
+		codeMap.put("40027","不合法的子菜单按钮URL长度");
+		codeMap.put("40028","不合法的自定义菜单使用用户");
+		codeMap.put("40029","不合法的oauth_code");
+		codeMap.put("40030","不合法的refresh_token");
+		codeMap.put("40031","不合法的openid列表");
+		codeMap.put("40032","不合法的openid列表长度");
+		codeMap.put("40033","不合法的请求字符,不能包含\\uxxxx格式的字符");
+		codeMap.put("40035","不合法的参数");
+		codeMap.put("40038","不合法的请求格式");
+		codeMap.put("40039","不合法的URL长度");
+		codeMap.put("40050","不合法的分组id");
+		codeMap.put("40051","分组名字不合法");
+		codeMap.put("41001","缺少access_token参数");
+		codeMap.put("41002","缺少appid参数");
+		codeMap.put("41003","缺少refresh_token参数");
+		codeMap.put("41004","缺少secret参数");
+		codeMap.put("41005","缺少多媒体文件数据");
+		codeMap.put("41006","缺少media_id参数");
+		codeMap.put("41007","缺少子菜单数据");
+		codeMap.put("41008","缺少oauth code");
+		codeMap.put("41009","缺少openid");
+		codeMap.put("42001","access_token超时");
+		codeMap.put("42002","refresh_token超时");
+		codeMap.put("42003","oauth_code超时");
+		codeMap.put("43001","需要GET请求");
+		codeMap.put("43002","需要POST请求");
+		codeMap.put("43003","需要HTTPS请求");
+		codeMap.put("43004","需要接收者关注");
+		codeMap.put("43005","需要好友关系");
+		codeMap.put("44001","多媒体文件为空");
+		codeMap.put("44002","POST的数据包为空");
+		codeMap.put("44003","图文消息内容为空");
+		codeMap.put("44004","文本消息内容为空");
+		codeMap.put("45001","多媒体文件大小超过限制");
+		codeMap.put("45002","消息内容超过限制");
+		codeMap.put("45003","标题字段超过限制");
+		codeMap.put("45004","描述字段超过限制");
+		codeMap.put("45005","链接字段超过限制");
+		codeMap.put("45006","图片链接字段超过限制");
+		codeMap.put("45007","语音播放时间超过限制");
+		codeMap.put("45008","图文消息超过限制");
+		codeMap.put("45009","接口调用超过限制");
+		codeMap.put("45010","创建菜单个数超过限制");
+		codeMap.put("45015","回复时间超过限制");
+		codeMap.put("45016","系统分组,不允许修改");
+		codeMap.put("45017","分组名字过长");
+		codeMap.put("45018","分组数量超过上限");
+		codeMap.put("46001","不存在媒体数据");
+		codeMap.put("46002","不存在的菜单版本");
+		codeMap.put("46003","不存在的菜单数据");
+		codeMap.put("46004","不存在的用户");
+		codeMap.put("47001","解析JSON/XML内容错误");
+		codeMap.put("48001","api功能未授权");
+		codeMap.put("50001","用户未授权该api");
+		codeMap.put("61451","参数错误(invalid parameter)");
+		codeMap.put("61452","无效客服账号(invalid kf_account)");
+		codeMap.put("61453","客服帐号已存在(kf_account exsited)");
+		codeMap.put("61454","客服帐号名长度超过限制(仅允许10个英文字符,不包括@及@后的公众号的微信号)(invalid kf_acount length)");
+		codeMap.put("61455","客服帐号名包含非法字符(仅允许英文+数字)(illegal character in kf_account)");
+		codeMap.put("61456","客服帐号个数超过限制(10个客服账号)(kf_account count exceeded)");
+		codeMap.put("61457","无效头像文件类型(invalid file type)");
+		codeMap.put("61450","系统错误(system error)");
+		codeMap.put("61500","日期格式错误");
+		codeMap.put("61501","日期范围错误");
+	}
+	
+	public static String errMsg(Integer errCode){
+		if(errCode != null && codeMap.containsKey(errCode+"")){
+			return codeMap.get(errCode+"");
+		}
+		return null;
+	}
+    public static String errMsg(String errCode){
+        if(errCode != null && codeMap.containsKey(errCode)){
+            return codeMap.get(errCode+"");
+        }
+        return null;
+    }
+	
+}

+ 99 - 0
suishenbang-wxportal/suishenbang-wxportal-common/src/main/java/com/dgtly/wxportal/utils/qywxutils/QyWxAccessTokenUtil.java

@@ -0,0 +1,99 @@
+package com.dgtly.wxportal.utils.qywxutils;
+
+import com.alibaba.fastjson.JSONObject;
+import com.dgtly.common.exception.BusinessException;
+import com.dgtly.wxportal.exception.QyWeixinException;
+import com.dgtly.common.utils.http.HttpUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import java.util.Date;
+
+/**
+ * 企业微信 accessToken相关
+ */
+@Component
+public class QyWxAccessTokenUtil {
+
+    private static final Logger log = LoggerFactory.getLogger(QyWxAccessTokenUtil.class);
+
+    private String accessToken;
+    /**
+     * 创建时间
+     */
+    private long createTime;
+
+    /**
+     * 过期时间
+     */
+    private long expires;
+
+
+    @Value(value = "${qiyeweixin.corpid:none}")
+    private String corpid;
+
+
+
+    @Value(value = "${qiyeweixin.corpsecret:none}")
+    private String corpsecret;
+
+    @Value(value = "${qiyeweixin.agentId:none}")
+    private String agentId;
+
+
+
+    /**
+     * 获取access_token
+     * @return
+     */
+    public String getAccessToken() {
+        JSONObject json;
+        String url;
+
+        try {
+            //token未过期使用缓存的token
+            long currentTiem = new Date().getTime();
+            if(this.accessToken!=null &&(currentTiem-createTime)<(expires*1000)){
+                return this.accessToken;
+            }
+            //获取请求地址
+            url = QyWxServiceUrl.ACCESS_TOKEN_URL.getformatUrl(corpid, corpsecret);
+            json = JSONObject.parseObject(HttpUtils.sendGet(url));
+        }catch (Exception e){
+            this.accessToken=null;
+            log.error("获取企业微信accesstoken错误",e);
+            throw new BusinessException("获取企业微信accesstoken错误",e);
+        }
+        Integer errcode = json.getInteger("errcode");
+        if(errcode!=0){
+            this.accessToken=null;
+            throw new QyWeixinException(errcode,url);
+        }
+        String token = json.getString("access_token");
+        long expires = json.getLong("expires_in");
+        this.createTime = new Date().getTime();
+        this.accessToken = token;
+        this.expires = expires;
+        return token;
+    }
+
+    public String getCorpid() {
+        return corpid;
+    }
+
+
+    public String getCorpsecret() {
+        return corpsecret;
+    }
+
+    public String getAgentId() {
+        return agentId;
+    }
+
+    public void setAgentId(String agentId) {
+        this.agentId = agentId;
+    }
+
+}

+ 36 - 0
suishenbang-wxportal/suishenbang-wxportal-common/src/main/java/com/dgtly/wxportal/utils/qywxutils/QyWxSendMessageUtil.java

@@ -0,0 +1,36 @@
+package com.dgtly.wxportal.utils.qywxutils;
+
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.dgtly.common.utils.http.HttpUtils;
+import com.dgtly.wxportal.exception.QyWeixinException;
+import com.dgtly.wxportal.utils.qywxutils.messageModel.QyWxBaseMessage;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * 企业微信发送信息工具类
+ */
+@Component
+public class QyWxSendMessageUtil {
+
+    @Autowired
+    private QyWxAccessTokenUtil qyWxAccessTokenUtil;
+
+
+    public boolean sendMessage(QyWxBaseMessage message){
+
+        message.setAgentid(qyWxAccessTokenUtil.getAgentId());
+        String url = QyWxServiceUrl.SEND_MESSAGE_URL.getformatUrl(qyWxAccessTokenUtil.getAccessToken());
+        String result =  HttpUtils.sendJsonPost(url,message);
+        JSONObject json = JSONObject.parseObject(result);
+
+        Integer errcode = json.getInteger("errcode");
+        if(errcode!=0){
+            throw new QyWeixinException(errcode,url);
+        }
+        return true;
+
+    }
+}

+ 71 - 0
suishenbang-wxportal/suishenbang-wxportal-common/src/main/java/com/dgtly/wxportal/utils/qywxutils/QyWxServiceUrl.java

@@ -0,0 +1,71 @@
+package com.dgtly.wxportal.utils.qywxutils;
+
+import java.util.Formatter;
+
+/**
+ * 企业微信 接口地址枚举类
+ */
+public enum QyWxServiceUrl {
+
+    /**
+     * 获取企业微信accessTokenurl
+     * 参数corpid,corpsecret
+     * (GET) 限200(次/天)
+     */
+    ACCESS_TOKEN_URL("https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=%s&corpsecret=%s")
+
+    /**
+     *获取Oauth2 验证链接url
+     * 参数appid,redirect_uri(编码后),state
+     */
+    ,OAUTH2_URL("https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=snsapi_base&state=%s#wechat_redirect")
+
+    /**
+     * 获取用户信息URL
+     * 参数access_token,code
+     */
+    ,USERINFO_URL("https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?access_token=%s&code=%s")
+
+    /**
+     * 获取用户详细信息URL
+     * 参数access_token,userid
+     */
+    ,USERDETAILINFO_URL("https://qyapi.weixin.qq.com/cgi-bin/user/get?access_token=%s&userid=%s")
+
+    /**
+     * 企业微信推送信息
+     * 参数access_token
+     */
+    ,SEND_MESSAGE_URL("https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=%s")
+
+
+
+
+    ;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+    private String url ;
+    private QyWxServiceUrl(String url){
+        this.url = url;
+    }
+
+    public String getformatUrl(Object... args) {
+        return new Formatter().format(this.url, args).toString();
+    }
+    public String getUrl() {
+        return this.url;
+    }
+
+}

+ 85 - 0
suishenbang-wxportal/suishenbang-wxportal-common/src/main/java/com/dgtly/wxportal/utils/qywxutils/QyWxUserUtil.java

@@ -0,0 +1,85 @@
+package com.dgtly.wxportal.utils.qywxutils;
+
+import com.alibaba.fastjson.JSONObject;
+import com.dgtly.wxportal.exception.QyWeixinException;
+import com.dgtly.common.utils.RedisUtil;
+import com.dgtly.common.utils.http.HttpUtils;
+import com.dgtly.wxportal.domain.WxQyUser;
+import com.dgtly.wxportal.service.IWxQyUserService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+
+/**
+ * 企业微信工具类
+ */
+@Component
+public class QyWxUserUtil {
+
+
+    @Autowired
+    private IWxQyUserService wxQyUserService;
+
+    @Autowired
+    private QyWxAccessTokenUtil qyWxAccessTokenUtil;
+
+    private String redis_qywxtoken_key="QYWX_ACCESS_TOKEN";
+
+
+    /**
+     * 获取企业微信用户的userId
+     * @return
+     */
+    public JSONObject getUserId(String code) {
+        String url = QyWxServiceUrl.USERINFO_URL.getformatUrl(qyWxAccessTokenUtil.getAccessToken(),code );
+
+        JSONObject json  = JSONObject.parseObject(HttpUtils.sendGet(url));
+        Integer errcode = json.getInteger("errcode");
+        if(errcode!=0){
+            throw new QyWeixinException(errcode,url);
+        }
+        /*
+        * 当用户为企业成员时返回示例如下:
+        * {
+        *   "errcode": 0,
+        *   "errmsg": "ok",
+        *   "UserId":"USERID",
+        *   "DeviceId":"DEVICEID"
+        *   }
+        *
+        * 非企业成员授权时返回示例如下:
+        * {
+        *   "errcode": 0,
+        *   "errmsg": "ok",
+        *   "OpenId":"OPENID",
+        *   "DeviceId":"DEVICEID"
+        *   }
+        *
+        * */
+
+        return json;
+    }
+
+    public String getOauth2Url(String redirect,String state){
+        return QyWxServiceUrl.OAUTH2_URL.getformatUrl(qyWxAccessTokenUtil.getCorpid(),redirect,state);
+    }
+
+    public WxQyUser gerUserDetail(String userId){
+        String url =  QyWxServiceUrl.USERDETAILINFO_URL.getformatUrl(qyWxAccessTokenUtil.getAccessToken(),userId);
+
+        String result = HttpUtils.sendGet(url);
+
+        JSONObject json = JSONObject.parseObject(result);
+
+        Integer errcode = json.getInteger("errcode");
+        if(errcode!=0){
+            throw new QyWeixinException(errcode,url);
+        }
+        WxQyUser wxQyUser = JSONObject.parseObject(result,WxQyUser.class);
+        wxQyUser.setJson(result);
+        return wxQyUser;
+
+    }
+
+}

+ 118 - 0
suishenbang-wxportal/suishenbang-wxportal-common/src/main/java/com/dgtly/wxportal/utils/qywxutils/messageModel/QyWxBaseMessage.java

@@ -0,0 +1,118 @@
+package com.dgtly.wxportal.utils.qywxutils.messageModel;
+
+import org.springframework.beans.factory.annotation.Value;
+
+/**
+ * 企业微信信息  基础类
+ *
+ * {
+ *    "touser" : "UserID1|UserID2|UserID3",
+ *    "toparty" : "PartyID1|PartyID2",
+ *    "totag" : "TagID1 | TagID2",
+ *    "msgtype" : "text",
+ *    "agentid" : 1,
+
+ * }
+ * touser	否	指定接收消息的成员,成员ID列表(多个接收者用‘|’分隔,最多支持1000个)。
+ * 特殊情况:指定为”@all”,则向该企业应用的全部成员发送
+ * toparty	否	指定接收消息的部门,部门ID列表,多个接收者用‘|’分隔,最多支持100个。
+ * 当touser为”@all”时忽略本参数
+ * totag	否	指定接收消息的标签,标签ID列表,多个接收者用‘|’分隔,最多支持100个。
+ * 当touser为”@all”时忽略本参数
+ * msgtype	是	消息类型,此时固定为:text
+ * agentid	是	企业应用的id,整型。企业内部开发,可在应用的设置页面查看;第三方服务商,可通过接口 获取企业授权信息 获取该参数值
+ */
+public class QyWxBaseMessage {
+
+    private String touser;
+    private String toparty;
+    private String totag;
+
+    private String agentid;
+
+    private String enable_id_trans="0";
+    private String enable_duplicate_check = "0";
+    private String duplicate_check_interval="1800";
+
+    public String getTouser() {
+        return touser;
+    }
+
+    public void setTouser(String... wxUserIds) {
+        String temp ="";
+        for(int i =0;i<wxUserIds.length;i++){
+            temp+=wxUserIds[i];
+            temp+="|";
+        }
+        if(temp.length()>0){
+            temp =  temp.substring(0,temp.length()-1);
+        }
+        this.touser = temp;
+    }
+
+    public String getToparty() {
+        return toparty;
+    }
+
+    public void setToparty(String... topartys) {
+        String temp ="";
+        for(int i =0;i<topartys.length;i++){
+            temp+=topartys[i];
+            temp+="|";
+        }
+        if(temp.length()>0){
+            temp =  temp.substring(0,temp.length()-1);
+        }
+        this.toparty = temp;
+    }
+
+    public String getTotag() {
+        return totag;
+    }
+
+    public void setTotag(String... totags) {
+        String temp ="";
+        for(int i =0;i<totags.length;i++){
+            temp+=totags[i];
+            temp+="|";
+        }
+        if(temp.length()>0){
+            temp =  temp.substring(0,temp.length()-1);
+        }
+        this.totag = temp;
+    }
+
+
+
+    public String getAgentid() {
+        return agentid;
+    }
+
+    public void setAgentid(String agentid) {
+        this.agentid = agentid;
+    }
+
+    public String getEnable_id_trans() {
+        return enable_id_trans;
+    }
+
+    public void setEnable_id_trans(String enable_id_trans) {
+        this.enable_id_trans = enable_id_trans;
+    }
+
+    public String getEnable_duplicate_check() {
+        return enable_duplicate_check;
+    }
+
+    public void setEnable_duplicate_check(String enable_duplicate_check) {
+        this.enable_duplicate_check = enable_duplicate_check;
+    }
+
+    public String getDuplicate_check_interval() {
+        return duplicate_check_interval;
+    }
+
+    public void setDuplicate_check_interval(String duplicate_check_interval) {
+        this.duplicate_check_interval = duplicate_check_interval;
+    }
+}

+ 43 - 0
suishenbang-wxportal/suishenbang-wxportal-common/src/main/java/com/dgtly/wxportal/utils/qywxutils/messageModel/QyWxTextCard.java

@@ -0,0 +1,43 @@
+package com.dgtly.wxportal.utils.qywxutils.messageModel;
+
+public class QyWxTextCard {
+    private String title;
+
+    private String description;
+
+    private String url;
+
+    private String btntxt;
+
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(String title) {
+        this.title = title;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public String getUrl() {
+        return url;
+    }
+
+    public void setUrl(String url) {
+        this.url = url;
+    }
+
+    public String getBtntxt() {
+        return btntxt;
+    }
+
+    public void setBtntxt(String btntxt) {
+        this.btntxt = btntxt;
+    }
+}

+ 26 - 0
suishenbang-wxportal/suishenbang-wxportal-common/src/main/java/com/dgtly/wxportal/utils/qywxutils/messageModel/QyWxTextCardMessage.java

@@ -0,0 +1,26 @@
+package com.dgtly.wxportal.utils.qywxutils.messageModel;
+
+/**
+ * 企业微信文本卡片 信息
+ */
+public class QyWxTextCardMessage extends QyWxBaseMessage {
+    private QyWxTextCard textcard;
+
+    private String msgtype="textcard";
+
+    public QyWxTextCard getTextcard() {
+        return textcard;
+    }
+
+    public void setTextcard(QyWxTextCard textcard) {
+        this.textcard = textcard;
+    }
+
+    public String getMsgtype() {
+        return msgtype;
+    }
+
+    public void setMsgtype(String msgtype) {
+        this.msgtype = msgtype;
+    }
+}

+ 13 - 0
suishenbang-wxportal/suishenbang-wxportal-common/src/main/java/com/dgtly/wxportal/utils/qywxutils/messageModel/QyWxTextContent.java

@@ -0,0 +1,13 @@
+package com.dgtly.wxportal.utils.qywxutils.messageModel;
+
+public class QyWxTextContent {
+    private String content;
+
+    public String getContent() {
+        return content;
+    }
+
+    public void setContent(String content) {
+        this.content = content;
+    }
+}

+ 78 - 0
suishenbang-wxportal/suishenbang-wxportal-common/src/main/java/com/dgtly/wxportal/utils/qywxutils/messageModel/QyWxTextMessage.java

@@ -0,0 +1,78 @@
+package com.dgtly.wxportal.utils.qywxutils.messageModel;
+
+/**
+ * 企业微信文本信息
+ *
+ * {
+ *    "touser" : "UserID1|UserID2|UserID3",
+ *    "toparty" : "PartyID1|PartyID2",
+ *    "totag" : "TagID1 | TagID2",
+ *    "msgtype" : "text",
+ *    "agentid" : 1,
+ *    "text" : {
+ *        "content" : "你的快递已到,请携带工卡前往邮件中心领取。\n出发前可查看<a href=\"http://work.weixin.qq.com\">邮件中心视频实况</a>,聪明避开排队。"
+ *    },
+ *    "safe":0,
+ *    "enable_id_trans": 0,
+ *    "enable_duplicate_check": 0,
+ *    "duplicate_check_interval": 1800
+ * }
+ * 参数	是否必须	说明
+ * touser	否	指定接收消息的成员,成员ID列表(多个接收者用‘|’分隔,最多支持1000个)。
+ * 特殊情况:指定为”@all”,则向该企业应用的全部成员发送
+ * toparty	否	指定接收消息的部门,部门ID列表,多个接收者用‘|’分隔,最多支持100个。
+ * 当touser为”@all”时忽略本参数
+ * totag	否	指定接收消息的标签,标签ID列表,多个接收者用‘|’分隔,最多支持100个。
+ * 当touser为”@all”时忽略本参数
+ * msgtype	是	消息类型,此时固定为:text
+ * agentid	是	企业应用的id,整型。企业内部开发,可在应用的设置页面查看;第三方服务商,可通过接口 获取企业授权信息 获取该参数值
+ * content	是	消息内容,最长不超过2048个字节,超过将截断(支持id转译)
+ * safe	否	表示是否是保密消息,0表示否,1表示是,默认0
+ * enable_id_trans	否	表示是否开启id转译,0表示否,1表示是,默认0
+ * enable_duplicate_check	否	表示是否开启重复消息检查,0表示否,1表示是,默认0
+ * duplicate_check_interval	否	表示是否重复消息检查的时间间隔,默认1800s,最大不超过4小时
+ */
+public class QyWxTextMessage extends QyWxBaseMessage {
+
+    private String msgtype = "text";
+    private QyWxTextContent text;
+
+    private String safe="0";
+
+
+    public String getMsgtype() {
+        return msgtype;
+    }
+
+    public void setMsgtype(String msgtype) {
+        this.msgtype = msgtype;
+    }
+
+//    public String getContent() {
+//        return content;
+//    }
+//
+//    public void setContent(String content) {
+//        this.content = content;
+//    }
+
+    public String getSafe() {
+        return safe;
+    }
+
+    public void setSafe(String safe) {
+        this.safe = safe;
+    }
+
+
+
+    public QyWxTextContent getText() {
+        return this.text;
+    }
+
+    public void setText(String text) {
+        QyWxTextContent qt = new  QyWxTextContent();
+        qt.setContent(text);
+        this.text = qt;
+    }
+}

+ 5 - 0
suishenbang-wxportal/suishenbang-wxportal-common/src/main/resources/mapper/wxportal/WxQyUserMapper.xml

@@ -127,5 +127,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         set sys_user_id = null
         where sys_user_id = #{sysUserId}
     </update>
+
+    <select id="selectWxQyUserBySysUserId" parameterType="String" resultMap="WxQyUserResult">
+        <include refid="selectWxQyUserVo"/>
+        where sys_user_id = #{sysUserId}
+    </select>
     
 </mapper>