<!--企业微信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;
# 转发到企业微信API
proxy_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;
}