package com.gxwebsoft.common.system.controller; import cn.hutool.core.util.RandomUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.XmlUtil; import cn.hutool.crypto.digest.DigestUtil; import cn.hutool.http.HttpRequest; import cn.hutool.http.HttpUtil; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.alipay.api.internal.util.file.IOUtils; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.gxwebsoft.common.core.utils.CommonUtil; import com.gxwebsoft.common.core.utils.RedisUtil; import com.gxwebsoft.common.core.web.ApiResult; import com.gxwebsoft.common.core.web.BaseController; import com.gxwebsoft.common.system.entity.*; import com.gxwebsoft.common.system.param.RoleParam; import com.gxwebsoft.common.system.param.UserParam; import com.gxwebsoft.common.system.service.RoleService; import com.gxwebsoft.common.system.service.UserOauthService; import com.gxwebsoft.common.system.service.UserRoleService; import com.gxwebsoft.common.system.service.UserService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import org.springframework.web.bind.annotation.*; import org.w3c.dom.Document; import org.w3c.dom.Element; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import java.io.IOException; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.concurrent.TimeUnit; import static com.gxwebsoft.common.core.constants.PlatformConstants.MP_OFFICIAL; @Api(tags = "微信公众号接口") @RestController @RequestMapping("/api/wx-official") public class WxOfficialController extends BaseController { // 公众号AppID private static final String appid = "wxa67c676fc445590e"; // 秘钥 private static final String secret = "a450297b5ca8e081080148799d4e6b25"; // 订阅消息模板ID private static final String templateId = "LBoByn-TLb2qJS7yR838lGRU-BA-RZE6jm-adb7AWPA"; // 小程序APPID private static final String miniAppid = "wx541db955e7a62709"; @Resource private UserService userService; @Resource private RoleService roleService; @Resource private UserRoleService userRoleService; @Resource private UserOauthService userOauthService; @Resource private RedisUtil redisUtil; @ApiOperation("验证微信服务器") @GetMapping("/{id}") public String validate(@PathVariable("id") Integer tenantId,@RequestParam String nonce,@RequestParam String timestamp,@RequestParam String signature,@RequestParam String echostr){ System.out.println("nonce = " + nonce); System.out.println("tenantId = " + tenantId); if(tenantId == null){ return null; } String token = "gxwebsoft"; String[] array = new String[]{token, timestamp, nonce}; // 将token、timestamp、nonce三个参数进行字典序排序 Arrays.sort(array); // 将三个参数字符串拼接成一个字符串进行sha1加密 StringBuilder sb = new StringBuilder(); for (String str: array){ sb.append(str); } final String strSha1 = DigestUtil.sha1Hex(sb.toString()); if (strSha1.equals(signature)) { return echostr; } return null; } @ApiOperation("接收微信的xml消息") @Transactional(rollbackFor = {Exception.class}) @RequestMapping("/{id}") @ResponseBody public String receiveMessages(HttpServletRequest request,@PathVariable("id") Integer tenantId) throws IOException { System.out.println("tenantId = " + tenantId); Integer userId = 0; // 用户ID // 从请求中获取XML数据 String xmlData = IOUtils.toString(request.getInputStream(), "UTF-8"); System.out.println("xmlData = " + xmlData); // 解析XML数据 Document document = XmlUtil.parseXml(xmlData); Element rootElement = XmlUtil.getRootElement(document); Element FromUserName = XmlUtil.getElement(rootElement, "FromUserName"); String openId = FromUserName.getTextContent(); System.out.println("openId = " + openId); if(StrUtil.isNotBlank(openId)){ // 获取用户基本信息(UnionID机制) final String userStr = HttpUtil.get("https://api.weixin.qq.com/cgi-bin/user/info?access_token=" + getAccessToken() + "&openid="+ openId +"&lang=zh_CN"); // 保存第三方用户信息表shop_user_oauth final JSONObject jsonObject = JSONObject.parseObject(userStr); final String unionid = jsonObject.getString("unionid"); final String subscribe = jsonObject.getString("subscribe"); System.out.println("unionid = " + unionid); sendTemplateMessage(openId); // 关注操作 if (subscribe != null &&subscribe.equals("1")) { final int count = userOauthService.count(new LambdaQueryWrapper().eq(UserOauth::getOauthType, MP_OFFICIAL).eq(UserOauth::getUnionid, unionid).eq(UserOauth::getTenantId,tenantId)); System.out.println("count = " + count); if (count == 0) { // 其他平台是否有注册过 final List list = userOauthService.list(new LambdaQueryWrapper().eq(UserOauth::getUnionid, unionid).eq(UserOauth::getDeleted, 0)); final int size = list.size(); // 新用户注册 if (size== 0) { User user = new User(); user.setStatus(0); user.setUsername("wxoff_".concat(RandomUtil.randomString(12))); user.setStatus(0); user.setNickname("微信公众号用户"); user.setPlatform(MP_OFFICIAL); user.setGradeId(1); user.setPassword(userService.encodePassword(CommonUtil.randomUUID16())); user.setTenantId(tenantId); user.setRecommend(0); final RoleParam roleParam = new RoleParam(); roleParam.setTenantId(tenantId); roleParam.setRoleCode("guest"); Role role = roleService.getByRoleCode(roleParam); user.setRoleId(role.getRoleId()); if (userService.saveUser(user)) { userId = user.getUserId(); // 添加用户角色 final UserRole userRole = new UserRole(); userRole.setUserId(user.getUserId()); userRole.setTenantId(user.getTenantId()); userRole.setRoleId(user.getRoleId()); userRoleService.save(userRole); } System.out.println("新微信公众号用户 = " + userId); } // 更新 if (!CollectionUtils.isEmpty(list)) { for (UserOauth item: list){ if(item.getUserId() != null){ userId = item.getUserId(); } } System.out.println("其他平台有注册过 = " + userId); } // 保存第三方用户记录 final UserOauth userOauth = new UserOauth(); userOauth.setOauthType(MP_OFFICIAL); userOauth.setUnionid(unionid); userOauth.setOauthId(openId); userOauth.setUserId(userId); userOauth.setTenantId(tenantId); boolean save = userOauthService.save(userOauth); System.out.println("关注微信公众号 = " + save); } } } return null; } private void sendTemplateMessage(String openId){ String url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + getAccessToken(); TemplateMessage templateMessage = new TemplateMessage(); templateMessage.setToUser(openId); templateMessage.setTemplateId("dVSbX2NRzAG7IuN4kkCQhgV-LjzxvApN3PgrGlon9JU"); /* 您好,您已成功消费。 商品名:微信影城影票 消费时间:2013年8月20日 20:38 备注:您可以回复文字或语音对该商品及商家进行评价哦~ {{productType.DATA}}:{{name.DATA}} 消费时间:{{time.DATA}} {{remark.DATA}} */ HashMap data = new HashMap<>(); data.put("first",new TemplateMessageDTO("您收到了一条新的订单。")); data.put("tradeDateTime",new TemplateMessageDTO("02月18日 01时05分")); data.put("customerInfo",new TemplateMessageDTO("广州 王俊")); data.put("orderItemName",new TemplateMessageDTO("兴趣车型")); data.put("orderItemData",new TemplateMessageDTO("骐达 2011款 1.6 CVT 舒适版")); data.put("remark",new TemplateMessageDTO("截止24日09:39分,您尚有10个订单未处理。")); System.out.println("data = " + data); // 链式构建请求 String result = HttpRequest.post(url) .body(JSONObject.toJSONString(data))//表单内容 .timeout(20000)//超时,毫秒 .execute().body(); System.out.println("result = " + result); System.out.println("getAccessToken() = " + getAccessToken()); } @ApiOperation("send发送订阅通知") @PostMapping("/send") public ApiResult send(UserParam param) { // send发送订阅通知 String url = "https://api.weixin.qq.com/cgi-bin/message/subscribe/bizsend?access_token=" + getAccessToken(); final UserOauth userOauth = userOauthService.getOne(new LambdaQueryWrapper().eq(UserOauth::getUserId, param.getUserId()).eq(UserOauth::getOauthType,"MP-OFFICIAL").eq(UserOauth::getDeleted, 0)); if(userOauth != null){ param.setOpenId(userOauth.getOauthId()); final String oauthId = userOauth.getOauthId(); // 跳转小程序链接 HashMap miniprogram = new HashMap<>(); miniprogram.put("appid",miniAppid); miniprogram.put("pagepath","pages/chat/chat?friendId=" + param.getUserId()); // 参数 HashMap data = new HashMap<>(); final HashMap thing1 = new HashMap<>(); final HashMap thing2 = new HashMap<>(); thing1.put("value","有新访客需要接待"); thing2.put("value","吉媒小红娘"); data.put("thing1",thing1); data.put("thing2",thing2); // 请求主服务器获取用户信息 HashMap map = new HashMap<>(); map.put("access_token", getAccessToken()); map.put("touser",oauthId); // "opEVj6e1YIlMyovkOQFCLJ7llmuI" // 红娘来信通知 map.put("template_id", templateId); map.put("miniprogram",JSONObject.toJSONString(miniprogram)); map.put("data",data); // 新访客通知 // map.put("tid","XMpEsDHmZZqpiaAzmPqO0Gk_h39WCRkaNZ9VoSI9F34"); // map.put("page","https://admin.jimeigroup.cn"); // map.put("sceneDesc","消息提醒"); System.out.println("map = " + map); // 链式构建请求 String result = HttpRequest.post(url) .body(JSONObject.toJSONString(map))//表单内容 .timeout(20000)//超时,毫秒 .execute().body(); JSONObject jsonObject = JSONObject.parseObject(result); // System.out.println("jsonObject = " + jsonObject); if(jsonObject != null){ return success(jsonObject); } } return fail("请求失败",getAccessToken()); } // 调用接口凭证 private String getAccessToken() { String key = MP_OFFICIAL.concat(":access_token:5"); // 从缓存获取access_token String value = redisUtil.get(key); if (value != null) { // 解析access_token JSONObject response = JSON.parseObject(value); return response.getString("access_token"); } // 微信获取凭证接口https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET String apiUrl = "https://api.weixin.qq.com/cgi-bin/token"; // 组装url参数 String url = apiUrl.concat("?grant_type=client_credential").concat("&appid=").concat(appid).concat("&secret=").concat(secret); // 执行get请求 String result = HttpUtil.get(url); // 解析access_token JSONObject response = JSON.parseObject(result); if (response.getString("access_token") != null) { // 存入缓存 redisUtil.set(key, result,7000L, TimeUnit.SECONDS); return response.getString("access_token"); } return null; } @ApiOperation("test") @PostMapping("/test") public ApiResult count(){ final int count = userOauthService.count(new LambdaQueryWrapper().eq(UserOauth::getOauthType, MP_OFFICIAL).eq(UserOauth::getUnionid, "o0FaIuKa2UsVp6FCbvmZlrcaBRCM")); System.out.println("count = " + count); return success(getAccessToken()); } }