当前位置: 首页 > news >正文

企业微信对接 代理 WXJava Ngnix映射 weixin-java-cp

        <!--企业微信SDK--><dependency><groupId>com.github.binarywang</groupId><artifactId>weixin-java-cp</artifactId><version>4.7.0</version></dependency>

我自己实现方法为了打印企业微信解密消息,可以使用WXJava 原生的方法,我是ngnix代理。

导入WXJava示例项目的包
在这里插入图片描述

package net.healthan.digital.wxcp.controller.single;import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.XmlUtils;
import me.chanjar.weixin.cp.api.WxCpOAuth2Service;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.api.WxCpUserService;
import me.chanjar.weixin.cp.bean.WxCpUser;
import me.chanjar.weixin.cp.bean.WxCpUserDetail;
import me.chanjar.weixin.cp.bean.message.WxCpXmlMessage;
import me.chanjar.weixin.cp.config.WxCpConfigStorage;
import me.chanjar.weixin.cp.util.crypto.WxCpCryptUtil;
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
import me.chanjar.weixin.cp.util.xml.XStreamTransformer;
import net.healthan.digital.common.core.exception.BizErrorException;
import net.healthan.digital.common.core.util.R;
import net.healthan.digital.common.security.annotation.Inner;
import net.healthan.digital.wxcp.config.single.WxCpConfiguration;
import net.healthan.digital.wxcp.utils.JsonUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;import java.util.HashMap;
import java.util.List;import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.OAuth2.GET_USER_AUTH_INFO;
import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.User.USER_GET;/*** @author <a href="https://github.com/binarywang">Binary Wang</a>*/
@RestController
@RequestMapping("/wx/cp/portal/{agentId}")
@Slf4j
public class WxPortalController {private static final String PROXY_URL = "http://127.0.0.1:22380/wxcp-api";/*** 授权码登录*/@GetMapping("/login")@Inner(value = false)public R<HashMap<String, Object>> getCode(@PathVariable Integer agentId, String code) throws WxErrorException {log.info("wxcp-login-start");if (StringUtils.isBlank(code)) {throw new BizErrorException("code不能为空");}log.info("code=>{}", code);final WxCpService wxCpService = WxCpConfiguration.getCpService(agentId);if (ObjectUtil.isEmpty(wxCpService)) {throw new BizErrorException("请配置企业微信");}String getUserAuthInfoUrl = PROXY_URL + String.format(GET_USER_AUTH_INFO, code);String getUserAuthInfoResponse = wxCpService.get(getUserAuthInfoUrl, null);JSONObject getUserAuthInfoJsonObject = JSONObject.parseObject(getUserAuthInfoResponse);log.info("getUserAuthInfoUrl通过前置机发起企业微信请求=>{}", getUserAuthInfoResponse);
//        String userTicket = getUserAuthInfoJsonObject.getString("userTicket");String userId = getUserAuthInfoJsonObject.getString("userid");HashMap<String, Object> hashMap = new HashMap<>();if (StringUtils.isBlank(userId)) {throw new BizErrorException("用户ID不能为空");}try {//读取通讯录信息String userGetUrl = PROXY_URL + USER_GET + userId;String userGetUrlResponse = wxCpService.get(userGetUrl, null);log.info("userGetUrl通过前置机发起企业微信请求=>{}", userGetUrlResponse);WxCpUser wxCpUser = WxCpGsonBuilder.create().fromJson(userGetUrlResponse, WxCpUser.class);List<WxCpUser.Attr> extAttrs = wxCpUser.getExtAttrs();if (CollectionUtil.isEmpty(extAttrs)) {throw new BizErrorException("第三方接口:企业微信-调用读取通讯录接口-获取工号失败");}boolean notHasWorkNo = true;for (WxCpUser.Attr extAttr : extAttrs) {if (StringUtils.equals(extAttr.getName(), "工号")) {if (StringUtils.isNotBlank(extAttr.getTextValue())) {notHasWorkNo = false;}}}if (notHasWorkNo) {throw new BizErrorException("第三方接口:企业微信-调用读取通讯录接口-获取工号失败");}hashMap.put("wxCpUser", wxCpUser);} catch (Exception e) {log.info(e.getMessage());throw new BizErrorException("第三方接口:企业微信-调用读取通讯录接口失败");}
//        if (StringUtils.isNotBlank(userTicket)) {
//            try {
//                WxCpOAuth2Service oauth2Service = wxCpService.getOauth2Service();
//                //获取用户敏感信息,未使用
//                WxCpUserDetail userDetail = oauth2Service.getUserDetail(userTicket);
//                hashMap.put("userDetail", userDetail);
//            }catch (Exception e){
//                e.printStackTrace();
//            }
//        }log.info("企业微信登录结果=>{}", JSON.toJSONString(hashMap));return R.ok(hashMap);}public void getS() {
//        https://qyapi.weixin.qq.com/cgi-bin/auth/getuserinfo?access_token=ACCESS_TOKEN&code=CODE}@Inner(value = false)@GetMapping(produces = "text/plain;charset=utf-8")public String authGet(@PathVariable Integer agentId,@RequestParam(name = "msg_signature", required = false) String signature,@RequestParam(name = "timestamp", required = false) String timestamp,@RequestParam(name = "nonce", required = false) String nonce,@RequestParam(name = "echostr", required = false) String echostr) {log.info("\nGet请求");log.info("\n接收到来自微信服务器的认证消息:signature = [{}], timestamp = [{}], nonce = [{}], echostr = [{}]",signature, timestamp, nonce, echostr);if (StringUtils.isAnyBlank(signature, timestamp, nonce, echostr)) {throw new IllegalArgumentException("请求参数非法,请核实!");}log.info("agentId=>{}", agentId);final WxCpService wxCpService = WxCpConfiguration.getCpService(agentId);if (wxCpService == null) {throw new IllegalArgumentException(String.format("未找到对应agentId=[%d]的配置,请核实!", agentId));}if (wxCpService.checkSignature(signature, timestamp, nonce, echostr)) {return new WxCpCryptUtil(wxCpService.getWxCpConfigStorage()).decrypt(echostr);}return "非法请求";}@Inner(value = false)@PostMapping(produces = "application/xml; charset=UTF-8")public String post(@PathVariable Integer agentId,@RequestBody String requestBody,@RequestParam("msg_signature") String signature,@RequestParam("timestamp") String timestamp,@RequestParam("nonce") String nonce) {log.info(String.valueOf(LocalDateTimeUtil.now()));log.info("\nPost请求");log.info("\n接收微信请求:[signature=[{}], timestamp=[{}], nonce=[{}], requestBody=[\n{}\n] ",signature, timestamp, nonce, requestBody);log.info("agentId=>{}", agentId);final WxCpService wxCpService = WxCpConfiguration.getCpService(agentId);log.info("wxCpService=>{}", wxCpService);try {WxCpXmlMessage inMessage = fromEncryptedXml(requestBody, wxCpService.getWxCpConfigStorage(),timestamp, nonce, signature);log.debug("\n消息解密后内容为:\n{} ", JsonUtils.toJson(inMessage));} catch (Exception e) {log.info("post微信请求解密失败" + e.getMessage());}//        WxCpXmlOutMessage outMessage = this.route(agentId, inMessage);
//        if (outMessage == null) {
//            return "success";
//        }//        String out = outMessage.toEncryptedXml(wxCpService.getWxCpConfigStorage());
//        log.debug("\n组装回复信息:{}", out);return "success";}public static WxCpXmlMessage fromEncryptedXml(String encryptedXml, WxCpConfigStorage wxCpConfigStorage,String timestamp, String nonce, String msgSignature) {log.info("fromEncryptedXml");WxCpCryptUtil cryptUtil = new WxCpCryptUtil(wxCpConfigStorage);log.info("cryptUtil:{}", cryptUtil);WxCpXmlMessage wxCpXmlMessage = fromXml(encryptedXml);String plainText = cryptUtil.decryptXml(msgSignature, timestamp, nonce, encryptedXml);log.info("解密后的原始xml消息内容:{}", plainText);if (StringUtils.isNotEmpty(wxCpXmlMessage.getAgentId())) {return fromXml(plainText, wxCpXmlMessage.getAgentId());} else {return fromXml(plainText);}}/*** From xml wx cp xml message.** @param xml     the xml* @param agentId the agent id* @return the wx cp xml message*/public static WxCpXmlMessage fromXml(String xml, String agentId) {//修改微信变态的消息内容格式,方便解析xml = xml.replace("</PicList><PicList>", "");final WxCpXmlMessage xmlMessage = fromXml(xml);xmlMessage.setAgentId(agentId);return xmlMessage;}protected static WxCpXmlMessage fromXml(String xml) {//修改微信变态的消息内容格式,方便解析xml = xml.replace("</PicList><PicList>", "");final WxCpXmlMessage xmlMessage = XStreamTransformer.fromXml(WxCpXmlMessage.class, xml);xmlMessage.setAllFieldsMap(XmlUtils.xml2Map(xml));return xmlMessage;}}
    # 通用匹配所有以 /wxcp-api/ 开头的路径location ^~ /wxcp-api/ {# 移除请求路径中的 /wxcp-api 前缀rewrite ^/wxcp-api/(.*) /$1 break;# 转发到企业微信APIproxy_pass https://qyapi.weixin.qq.com;# 伪造客户端IP地址proxy_set_header X-Real-IP 127.0.0.1;proxy_set_header X-Forwarded-For 127.0.0.1;}
http://www.dtcms.com/a/354347.html

相关文章:

  • Vue 登录页高低分辨率背景图优化实现
  • mathtype公式存在乱码
  • SqlHelper类的方法详细解读和使用示例
  • Libvio访问异常排查指南
  • sql server 取起始日期到结束日期中自然月最后一天,与日期维度行转列
  • 数据治理:AI健康血液的生命线
  • Elasticsearch数据迁移快照方案初探(一):多节点集群配置踩坑记
  • Anaconda的安装与使用
  • 文本分块的优化策略-语义完整性、控制长度、重叠切分、结合模型,考虑大模型输入限制
  • matlab的app中传递数据
  • 林墨2025全新个人EP《嘻嘻呵呵嘿嘿哈哈》 第三支单曲解锁
  • 【数据分享】安徽省安庆市地理基础数据(道路、水系、铁路、行政边界(含乡镇)、DEM等)
  • 企业分支上云的常见误区与纠正方案
  • LeetCode - 反转链表 / K 个一组翻转链表
  • HSA35NV001美光固态闪存NQ482NQ470
  • CT03-215.数组中第k大的元素
  • 面试之微服务架构
  • 美团面试手撕:手动实现开方函数math.sqrt(x)
  • Spring Security 深度学习(一): 基础入门与默认行为分析
  • 【Vue2 ✨】Vue2 入门之旅(一):初识 Vue2
  • 详细梳理 MyBatis-Plus 的 QueryWrapper 和 LambdaQueryWrapper的入门到精通
  • App中分发中的防盗链开发是做什么的?防盗链有什么作用?什么是防盗链?
  • vscode 如何调试 python 2.7
  • 【PyTorch】基于YOLO的多目标检测项目(一)
  • 免费开源图片压缩工具|绿色版本地运行,支持批量压缩+格式转换,不上传数据,隐私安全有保障!
  • 解决delphi label 在timer下闪烁的问题
  • 字节面试手撕题:神经网络模型损失函数与梯度推导
  • CSS(面试)
  • Mojomox-在线 AI logo 设计工具
  • 从“流量焦虑”到“稳定增长”:用内容平衡术解锁Adsense变现新密码