微信通知

简介: 本文介绍了企业微信与小程序集成下,通过API获取access_token并发送消息的完整流程。包括前置条件、参数配置、代码实现及异步处理建议,适用于企业内部系统对接微信通知功能。

1.前置条件

  • 企业微信appId
  • 企业微信secret
  • 企业微信绑定小程序
  • 小程序的appId

2.发送示例

2.1 获取access_token(HTTPS-GET)


请求URL:

https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=corpid&corpsecret=corpsecret


示例入参:

corpid=wx161we55e1fe5e4fr

corpsecret=Rspav9pmjem3zve8fkjqe6yTtCs78Rwdabn6tNdU1g


public class AccessToken {
  // 获取到的凭证
  private String token;
  // 凭证有效时间,单位:秒
  private int expiresIn;
  public String getToken() {
    return token;
  }
  public void setToken(String token) {
    this.token = token;
  }
  public int getExpiresIn() {
    return expiresIn;
  }
  public void setExpiresIn(int expiresIn) {
    this.expiresIn = expiresIn;
  }
}
// url就是上述的,完整如下:
// https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=wx161we55e1fe5e4fr&corpsecret=Rspav9pmjem3zve8fkjqe6yTtCs78Rwdabn6tNdU1g
public static AccessToken getAccessToken(String url) {
    logger.info("[WeixinUtil.getAccessToken]:start getAccessToken,url:" + url);
    AccessToken accessToken = null;
    JSONObject jsonObject = httpRequest(url, "GET", null);
    if (jsonObject != null) {
        try {
            accessToken = new AccessToken();
            accessToken.setToken(jsonObject.getString("access_token"));
            accessToken.setExpiresIn(jsonObject.getInteger("expires_in"));
        } catch (JSONException e) {
            accessToken = null;
            logger.error("[WeixinUtil.getAccessToken]:getAccessToken occured an JSONException,errcode:"
                         + jsonObject.getInteger("errcode") + ",errmsg:" + jsonObject.getString("errmsg") + ",JSONException:" + e);
        }
    }
    logger.info("[WeixinUtil.getAccessToken]:end getAccessToken.");
    return accessToken;
}


2.2 发送

logger.info("发送企业号获取Token结束:" + accessTokenUrl + ",accessToken:" + JSONObject.toJSONString(accessToken));
// 查询通讯录分组,分组ID:在线咨询医生
String getDeptUserUrl = null;
if(10000 == hospitalId) {
    getDeptUserUrl = WechatUtil.QY_GET_DEPT_USER_URL_XMHA.replace("ACCESS_TOKEN", accessToken.getToken())
        .replace("DEPARTMENT_ID", "123").replace("FETCH_CHILD", "1");
} else if(10001 == hospitalId) {
    getDeptUserUrl = WechatUtil.QY_GET_DEPT_USER_URL_XMHA.replace("ACCESS_TOKEN", accessToken.getToken())
        .replace("DEPARTMENT_ID", "124").replace("FETCH_CHILD", "1");
}
JSONObject hResponse = WechatUtil.httpRequest(getDeptUserUrl, "GET", null);
if (null == hResponse) {
    logger.info("未能成功获取到通讯录");
    return;
}
String docNo = getDoctorNo(doctorNo);
WXQYUser toWXQYUser = null;
List<WXQYUser> wXQYUserList = getWXQYUserList(hResponse);
for (WXQYUser wxQYUser : wXQYUserList) {
    if (docNo.equals(wxQYUser.getHisid())) {
        // 发消息
        toWXQYUser = wxQYUser;
        break;
    }
}
if (null != toWXQYUser) {
    String toUserId = toWXQYUser.getUserid();
    String time = DateUtil.formatDate("MM-dd HH:mm", new Date());
    String descTime = time.split(" ")[0].substring(0, 2) + "月" +
        time.split(" ")[0].substring(3) + "日  " +
        time.split(" ")[1];
    String appIdForMiniProgram = imSystemConfigService.getImSystemConfig(hospitalId, HUUtil.APP_ID_FOR_MINI_PROGRAM);
    String jsonParam = "{\"touser\": \"" + toUserId + "\",\"toparty\":\"\",\"totag\":\"\",\"msgtype\":\"miniprogram_notice\",\"miniprogram_notice\":" +
        "{\"appid\":\"" +appIdForMiniProgram +  "\",\"page\":\"pages/index/chat/trade-start/trade-start?orderNo=" + orderNo +"\"," +
        "\"title\":\"新订单接诊提醒\",\"description\": \"" + descTime + "\",\"emphasis_first_item\":true," +
        "\"content_item\":[{\"key\":\"接诊通知\",\"value\":\"来新咨询订单了\"},{\"key\":\"咨询人\",\"value\":\""+subTitle+"\"},{\"key\":\"病情描述\",\"value\":\""+content+"\"}]},\"enable_id_trans\":0," +
        "\"enable_duplicate_check\":0,\"duplicate_check_interval\":1800}";
    logger.info("开始发送微信企业号消息,入参:" + jsonParam);
    String imsServiceDomainConfigStr = imSystemConfigService.getImSystemConfig(hospitalId,
                                                                               HUUtil.IMS_SERVICE_WECHAT_QYH_TEMPLATE_DOMAIN_CONFIG_KEY);
    if (null == imsServiceDomainConfigStr || "".equals(imsServiceDomainConfigStr)) {
        logger.info("IMS发送微信企业号消息服务地址配置信息不存在:" + hospitalId);
        return;
    }
    imsServiceDomainConfigStr = imsServiceDomainConfigStr + "?access_token=" + accessToken.getToken();
    String result = HUHttpUtil.sendJsonPostRequest(imsServiceDomainConfigStr, jsonParam, 0);
    logger.info("开始发送微信企业号消息,结果:" + result);
} else {
    logger.info("该医生" + doctorNo + "在企业号通讯录中不存在,终止发送企业号消息");
}

完整代码示例(建议异步)

private static final ThreadLocal<ExecutorService> synExecuteService = ThreadLocal.withInitial(() -> Executors.newFixedThreadPool(200));
private final static String QY_ACCESS_TOKEN_URL = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=CORPID&corpsecret=SECRET";
private final static String QY_GET_DEPT_USER_URL = "https://qyapi.weixin.qq.com/cgi-bin/user/list?access_token=ACCESS_TOKEN&department_id=DEPARTMENT_ID&fetch_child=FETCH_CHILD";
public void sendOpenWxMsg(final String doctorNo, final String title, final String subTitle, final String content, final String toUrl,
                              final String orderNo, final long hospitalId) {
    synExecuteService.submit(() -> {
        String appIdAppSecretConfigStr = imSystemConfigService.getImSystemConfig(hospitalId, HUUtil.WEIXIN_QY_APPID_SECRET_CONFIG_FOR_MINI_PROGRAM);
        if (null == appIdAppSecretConfigStr || "".equals(appIdAppSecretConfigStr)) {
            logger.info("未查询到APPID信息:" + hospitalId + ",KEY:" + HUUtil.WEIXIN_QY_APPID_SECRET_CONFIG);
            return;
        }
        String accessTokenUrl = WechatUtil.QY_ACCESS_TOKEN_URL_XMHA.replace("CORPID", appIdAppSecretConfigStr.split("=")[0])
            .replace("SECRET", appIdAppSecretConfigStr.split("=")[1]);
        AccessToken accessToken = WechatUtil.getAccessToken(accessTokenUrl);
        if (null == accessToken) {
            logger.info("未能成功获取到AccessToken");
            return;
        }
        logger.info("发送企业号获取Token结束:" + accessTokenUrl + ",accessToken:" + JSONObject.toJSONString(accessToken));
        // 查询通讯录分组,分组ID:在线咨询医生
        String getDeptUserUrl = null;
        // 不同医院部门编号不一样,对应部门编号在企业微信查看
        if(10000 == hospitalId) {
            getDeptUserUrl = WechatUtil.QY_GET_DEPT_USER_URL_XMHA.replace("ACCESS_TOKEN", accessToken.getToken())
                .replace("DEPARTMENT_ID", "123").replace("FETCH_CHILD", "1");
        } else if(10001 == hospitalId) {
            getDeptUserUrl = WechatUtil.QY_GET_DEPT_USER_URL_XMHA.replace("ACCESS_TOKEN", accessToken.getToken())
                .replace("DEPARTMENT_ID", "124").replace("FETCH_CHILD", "1");
        }
        JSONObject hResponse = WechatUtil.httpRequest(getDeptUserUrl, "GET", null);
        if (null == hResponse) {
            logger.info("未能成功获取到通讯录");
            return;
        }
        String docNo = getDoctorNo(doctorNo);
        WXQYUser toWXQYUser = null;
        List<WXQYUser> wXQYUserList = getWXQYUserList(hResponse);
        for (WXQYUser wxQYUser : wXQYUserList) {
            if (docNo.equals(wxQYUser.getHisid())) {
                // 发消息
                toWXQYUser = wxQYUser;
                break;
            }
        }
        if (null != toWXQYUser) {
            String toUserId = toWXQYUser.getUserid();
            String time = DateUtil.formatDate("MM-dd HH:mm", new Date());
            String descTime = time.split(" ")[0].substring(0, 2) + "月" +
                time.split(" ")[0].substring(3) + "日  " +
                time.split(" ")[1];
            String appIdForMiniProgram = imSystemConfigService.getImSystemConfig(hospitalId, HUUtil.APP_ID_FOR_MINI_PROGRAM);
            String jsonParam = "{\"touser\": \"" + toUserId + "\",\"toparty\":\"\",\"totag\":\"\",\"msgtype\":\"miniprogram_notice\",\"miniprogram_notice\":" +
                "{\"appid\":\"" +appIdForMiniProgram +  "\",\"page\":\"pages/index/chat/trade-start/trade-start?orderNo=" + orderNo +"\"," +
                "\"title\":\"新订单接诊提醒\",\"description\": \"" + descTime + "\",\"emphasis_first_item\":true," +
                "\"content_item\":[{\"key\":\"接诊通知\",\"value\":\"来新咨询订单了\"},{\"key\":\"咨询人\",\"value\":\""+subTitle+"\"},{\"key\":\"病情描述\",\"value\":\""+content+"\"}]},\"enable_id_trans\":0," +
                "\"enable_duplicate_check\":0,\"duplicate_check_interval\":1800}";
            logger.info("开始发送微信企业号消息,入参:" + jsonParam);
      // 微信企业号消息发送服务地址 http://ip:port/mp-api/wechat/enterprise/message/send
            String imsServiceDomainConfigStr = imSystemConfigService.getImSystemConfig(hospitalId, HUUtil.IMS_SERVICE_WECHAT_QYH_TEMPLATE_DOMAIN_CONFIG_KEY);
            if (null == imsServiceDomainConfigStr || "".equals(imsServiceDomainConfigStr)) {
                logger.info("IMS发送微信企业号消息服务地址配置信息不存在:" + hospitalId);
                return;
            }
            imsServiceDomainConfigStr = imsServiceDomainConfigStr + "?access_token=" + accessToken.getToken();
            String result = HUHttpUtil.sendJsonPostRequest(imsServiceDomainConfigStr, jsonParam, 0);
            logger.info("开始发送微信企业号消息,结果:" + result);
        } else {
            logger.info("该医生" + doctorNo + "在企业号通讯录中不存在,终止发送企业号消息");
        }
    });
}
/**
     * 发送GET请求
     *
     * @param requestUrl
     * @param requestMethod
     * @param outputStr
     * @return
     */
public static JSONObject httpRequest(String requestUrl, String requestMethod, String outputStr) {
    logger.info("[WeixinUtil.httpRequest]:请求入参:" + requestUrl);
    String respStr = HUHttpUtil.sendGet(requestUrl, null);
    logger.info("[WeixinUtil.httpRequest]:请求响应:" + respStr);
    try {
        return JSON.parseObject(respStr);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}
private List<WXQYUser> getWXQYUserList(JSONObject hResponse) {
    List<JSONObject> wXQYUserList = (List<JSONObject>) hResponse.get("userlist");
    List<JSONObject> nmList = null;
    WXQYUser wxQYUser = null;
    JSONObject mm = null;
    List<WXQYUser> wxQYUserList = new ArrayList<WXQYUser>();
    for (JSONObject jsObject : wXQYUserList) {
        if (jsObject.containsKey("userid")) {
            if (jsObject.containsKey("extattr")) {
                mm = jsObject.getJSONObject("extattr");
                if (null != mm.get("attrs")) {
                    nmList = (List<JSONObject>) mm.get("attrs");
                    for (JSONObject nmObject : nmList) {
                        if (nmObject.containsKey("name") && "hisid".equals(nmObject.getString("name"))
                            && null != nmObject.getString("value") && !"".equals(nmObject.getString("value"))) {
                            wxQYUser = new WXQYUser();
                            wxQYUser.setUserid(jsObject.getString("userid"));
                            wxQYUser.setName(jsObject.getString("name"));
                            wxQYUser.setMobile(jsObject.getString("mobile"));
                            wxQYUser.setHisid(nmObject.getString("value"));
                            wxQYUserList.add(wxQYUser);
                        }
                    }
                }
            }
        }
    }
    return wxQYUserList;
}
// 企业微信存储12345,数据库存储:医院ID+12345,随意这里做截取再去匹配
private String getDoctorNo(String doctorNo) {
    if (doctorNo.startsWith("10000")) {
        return doctorNo.substring(5, doctorNo.length());
    }
    if (doctorNo.startsWith("10001")) {
        return doctorNo.substring(5, doctorNo.length());
    }
    return doctorNo;
}
class WXQYUser {
  private String userid;
  private String name;
  private String mobile;
  private String hisid;
  public String getUserid() {
    return userid;
  }
  public void setUserid(String userid) {
    this.userid = userid;
  }
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  public String getMobile() {
    return mobile;
  }
  public void setMobile(String mobile) {
    this.mobile = mobile;
  }
  public String getHisid() {
    return hisid;
  }
  public void setHisid(String hisid) {
    this.hisid = hisid;
  }
}
相关文章
|
1天前
|
缓存 运维 监控
一场FullGC故障排查
本文记录了一次Java应用CPU使用率异常升高的排查过程。通过分析发现,问题根源为频繁Full GC导致CPU飙升,而Full GC是因用户上传的Excel数据被加载为大对象并长期驻留JVM内存所致。使用JProfiler分析堆内存,定位到List&lt;Map&lt;String, String&gt;&gt;结构造成内存膨胀,空间效率仅约13.4%。最终提出“治本”与“治标”两类解决方案:一是将大数据移出JVM内存,存入Redis;二是优化代码,及时清理无用字段以减小对象体积。文章总结了从监控识别、工具分析到根本解决的完整排查思路,对类似性能问题具有参考价值。(238字)
|
1天前
|
存储 缓存 负载均衡
Nacos注册中心
本文介绍Nacos的安装部署、服务注册中心整合、分级模型、负载均衡策略、权重控制、环境隔离及实例类型,详解其在微服务架构中的应用,帮助开发者掌握Nacos核心功能与最佳实践。
 Nacos注册中心
|
1天前
|
负载均衡 算法 架构师
Ribbon负载均衡
本文深入讲解Spring Cloud中Ribbon实现客户端负载均衡的原理,包括@LoadBalanced注解的作用、负载均衡策略分类与算法,以及如何自定义配置和优化首次调用延迟的饥饿加载机制,帮助读者全面理解微服务间的流量分发技术。
Ribbon负载均衡
|
1天前
|
Java Nacos Maven
Eureka服务注册与发现
本节介绍Eureka注册中心的搭建与使用,完成服务注册与发现功能,为后续Nacos替换做铺垫。
 Eureka服务注册与发现
|
2天前
|
安全 JavaScript
JeecgBoot介绍
JeecgBoot是一款基于代码生成器的低代码开发平台,支持零代码快速开发。采用SpringBoot2.x、Ant Design&Vue、Mybatis-plus等主流技术,前后端分离架构,集成Shiro、JWT安全控制,助力高效构建企业级应用。
JeecgBoot介绍
|
2天前
|
NoSQL 关系型数据库 Java
基础环境配置
项目开发环境要求JDK8+、Maven、Redis 3.2+、MySQL 5.7+,推荐使用Idea开发工具,需安装Lombok插件和JRebel热部署工具。技术栈基于SpringBoot、MybatisPlus、Shiro及SpringCloud Alibaba,适合构建微服务架构应用。
基础环境配置
|
1天前
|
数据库 前端开发 NoSQL
代码拉取与运行
本文档介绍JeecgBoot前后端项目部署流程,包含代码拉取(在线/离线)、数据库脚本导入、Idea工程配置、修改数据库与Redis连接、后端启动及前端Vue3项目运行步骤,附目录结构与关键配置说明,助您快速搭建开发环境。
代码拉取与运行
|
1天前
|
Dubbo IDE API
SpringCloud工程部署启动
本文介绍SpringCloud微服务工程搭建全过程,涵盖项目创建、模块配置、数据库部署及服务远程调用实现。通过两种方案快速搭建工程,使用RestTemplate完成服务间HTTP通信,并解析调用流程与设计思想,帮助开发者掌握微服务基础架构与协作机制。
|
1天前
|
数据采集 领域建模 数据库
领域模型图(数据架构/ER图)
本文介绍如何通过四色原型法进行领域建模,构建数据架构中的ER图。利用时标性(MI)、参与方-地点-物品(PPT)、角色(Role)和描述(DESC)四类原型,逐步从业务流程中提炼实体与关系,最终形成清晰的数据模型,助力系统设计。
|
1天前
|
uml C语言
系统时序图
时序图(Sequence Diagram)是UML中描述对象间消息传递时间顺序的交互图。横轴为对象,纵轴为时间,通过生命线、控制焦点和消息等元素展现动态协作过程,强调交互的时间先后关系,适用于建模并发与同步行为。