diff --git a/src/main/java/com/gxwebsoft/common/core/config/MybatisPlusConfig.java b/src/main/java/com/gxwebsoft/common/core/config/MybatisPlusConfig.java index 0d8fd36..568e756 100644 --- a/src/main/java/com/gxwebsoft/common/core/config/MybatisPlusConfig.java +++ b/src/main/java/com/gxwebsoft/common/core/config/MybatisPlusConfig.java @@ -56,6 +56,7 @@ public class MybatisPlusConfig { "sys_tenant", "sys_dictionary", "sys_dictionary_data", + "sys_user_oauth", "sys_email_record", "sys_plug" ).contains(tableName); diff --git a/src/main/java/com/gxwebsoft/common/core/constants/PlatformConstants.java b/src/main/java/com/gxwebsoft/common/core/constants/PlatformConstants.java new file mode 100644 index 0000000..896f8e3 --- /dev/null +++ b/src/main/java/com/gxwebsoft/common/core/constants/PlatformConstants.java @@ -0,0 +1,12 @@ +package com.gxwebsoft.common.core.constants; + +public class PlatformConstants { + public static final String MP_OFFICIAL = "MP-OFFICIAL"; // 微信公众号 + public static final String MP_WEIXIN = "MP-WEIXIN"; // 微信小程序 + public static final String MP_ALIPAY = "MP-ALIPAY"; // 支付宝小程序 + public static final String WEB = "WEB"; // web(同H5) + public static final String H5 = "H5"; // H5(推荐使用 WEB) + public static final String APP = "APP"; // App + public static final String MP_BAIDU = "MP-BAIDU"; // 百度小程序 + public static final String MP_TOUTIAO = "MP-TOUTIAO"; // 百度小程序 +} diff --git a/src/main/java/com/gxwebsoft/common/core/constants/WxOfficialConstants.java b/src/main/java/com/gxwebsoft/common/core/constants/WxOfficialConstants.java deleted file mode 100644 index a025610..0000000 --- a/src/main/java/com/gxwebsoft/common/core/constants/WxOfficialConstants.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.gxwebsoft.common.core.constants; - -public class WxOfficialConstants { - // 获取 Access token - public static final String GET_ACCESS_TOKEN_API = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET"; -} diff --git a/src/main/java/com/gxwebsoft/common/core/security/SecurityConfig.java b/src/main/java/com/gxwebsoft/common/core/security/SecurityConfig.java index e105722..e28e2cd 100644 --- a/src/main/java/com/gxwebsoft/common/core/security/SecurityConfig.java +++ b/src/main/java/com/gxwebsoft/common/core/security/SecurityConfig.java @@ -53,7 +53,8 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { "/api/login-alipay/*", "/api/wx-login/loginByMpWxPhone", "/api/wxWorkQrConnect", - "/api/sys/user-plan-log/wx-pay/**" + "/api/sys/user-plan-log/wx-pay/**", + "/api/wx-official/**" ) .permitAll() .anyRequest() diff --git a/src/main/java/com/gxwebsoft/common/system/controller/WxLoginController.java b/src/main/java/com/gxwebsoft/common/system/controller/WxLoginController.java index 07de0c1..0633e05 100644 --- a/src/main/java/com/gxwebsoft/common/system/controller/WxLoginController.java +++ b/src/main/java/com/gxwebsoft/common/system/controller/WxLoginController.java @@ -35,6 +35,8 @@ import java.io.File; import java.util.HashMap; import java.util.concurrent.TimeUnit; +import static com.gxwebsoft.common.core.constants.PlatformConstants.MP_OFFICIAL; +import static com.gxwebsoft.common.core.constants.PlatformConstants.MP_WEIXIN; import static com.gxwebsoft.common.core.constants.RedisConstants.ACCESS_TOKEN_KEY; @RestController @@ -136,6 +138,7 @@ public class WxLoginController extends BaseController { addUser.setStatus(0); addUser.setUsername(createUsername("wx_")); addUser.setNickname("微信用户"); + addUser.setPlatform(MP_WEIXIN); addUser.setGradeId(2); if(userParam.getPhone() != null){ addUser.setPhone(userParam.getPhone()); diff --git a/src/main/java/com/gxwebsoft/common/system/controller/WxOfficialController.java b/src/main/java/com/gxwebsoft/common/system/controller/WxOfficialController.java new file mode 100644 index 0000000..c7d4b1b --- /dev/null +++ b/src/main/java/com/gxwebsoft/common/system/controller/WxOfficialController.java @@ -0,0 +1,261 @@ +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.Role; +import com.gxwebsoft.common.system.entity.User; +import com.gxwebsoft.common.system.entity.UserOauth; +import com.gxwebsoft.common.system.entity.UserRole; +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); + // 关注操作 + 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; + } + + @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(count); + } +} diff --git a/src/main/java/com/gxwebsoft/common/system/entity/UserOauth.java b/src/main/java/com/gxwebsoft/common/system/entity/UserOauth.java index b60ff48..3e0b969 100644 --- a/src/main/java/com/gxwebsoft/common/system/entity/UserOauth.java +++ b/src/main/java/com/gxwebsoft/common/system/entity/UserOauth.java @@ -52,7 +52,6 @@ public class UserOauth implements Serializable { private Integer status; @ApiModelProperty(value = "是否删除, 0否, 1是") - @TableLogic private Integer deleted; @ApiModelProperty(value = "租户id") diff --git a/src/main/java/com/gxwebsoft/common/system/mapper/RoleMapper.java b/src/main/java/com/gxwebsoft/common/system/mapper/RoleMapper.java index c1de9ce..ddfab6a 100644 --- a/src/main/java/com/gxwebsoft/common/system/mapper/RoleMapper.java +++ b/src/main/java/com/gxwebsoft/common/system/mapper/RoleMapper.java @@ -18,4 +18,5 @@ public interface RoleMapper extends BaseMapper { @InterceptorIgnore(tenantLine = "true") List selectListAll(@Param("param") RoleParam param); + } diff --git a/src/main/java/com/gxwebsoft/common/system/param/UserParam.java b/src/main/java/com/gxwebsoft/common/system/param/UserParam.java index e03e36d..0623056 100644 --- a/src/main/java/com/gxwebsoft/common/system/param/UserParam.java +++ b/src/main/java/com/gxwebsoft/common/system/param/UserParam.java @@ -120,6 +120,18 @@ public class UserParam extends BaseParam { @ApiModelProperty(value = "所在辖区") private String region; + @ApiModelProperty("关注数") + private Integer followers; + + @ApiModelProperty("粉丝数") + private Integer fans; + + @ApiModelProperty("获赞数") + private Integer likes; + + @ApiModelProperty("评论数") + private Integer commentNumbers; + @ApiModelProperty(value = "择偶区域") @TableField(exist = false) private String cityMate; @@ -202,15 +214,7 @@ public class UserParam extends BaseParam { @TableField(exist = false) private Boolean showProfile; - @ApiModelProperty("关注数") - private Integer followers; - - @ApiModelProperty("粉丝数") - private Integer fans; - - @ApiModelProperty("获赞数") - private Integer likes; - - @ApiModelProperty("评论数") - private Integer commentNumbers; + @ApiModelProperty("openId") + @TableField(exist = false) + private String openId; } diff --git a/src/main/java/com/gxwebsoft/common/system/service/RoleService.java b/src/main/java/com/gxwebsoft/common/system/service/RoleService.java index 3e76263..c533f96 100644 --- a/src/main/java/com/gxwebsoft/common/system/service/RoleService.java +++ b/src/main/java/com/gxwebsoft/common/system/service/RoleService.java @@ -2,6 +2,7 @@ package com.gxwebsoft.common.system.service; import com.baomidou.mybatisplus.extension.service.IService; import com.gxwebsoft.common.system.entity.Role; +import com.gxwebsoft.common.system.param.RoleParam; /** * 角色Service @@ -10,5 +11,5 @@ import com.gxwebsoft.common.system.entity.Role; * @since 2018-12-24 16:10:32 */ public interface RoleService extends IService { - + Role getByRoleCode(RoleParam roleParam); } diff --git a/src/main/java/com/gxwebsoft/common/system/service/impl/RoleServiceImpl.java b/src/main/java/com/gxwebsoft/common/system/service/impl/RoleServiceImpl.java index f543abd..aa163a7 100644 --- a/src/main/java/com/gxwebsoft/common/system/service/impl/RoleServiceImpl.java +++ b/src/main/java/com/gxwebsoft/common/system/service/impl/RoleServiceImpl.java @@ -3,9 +3,12 @@ package com.gxwebsoft.common.system.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.gxwebsoft.common.system.entity.Role; import com.gxwebsoft.common.system.mapper.RoleMapper; +import com.gxwebsoft.common.system.param.RoleParam; import com.gxwebsoft.common.system.service.RoleService; import org.springframework.stereotype.Service; +import java.util.List; + /** * 角色服务实现类 * @@ -15,4 +18,9 @@ import org.springframework.stereotype.Service; @Service public class RoleServiceImpl extends ServiceImpl implements RoleService { + @Override + public Role getByRoleCode(RoleParam roleParam) { + final List roleList = baseMapper.selectListAll(roleParam); + return roleList.get(0); + } } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index e09dc16..7659ea8 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,6 +1,6 @@ # 端口 server: - port: 9015 + port: 9090 # socketIo socketio: port: 9191 diff --git a/src/test/java/com/gxwebsoft/generator/SysGenerator.java b/src/test/java/com/gxwebsoft/generator/SysGenerator.java index 3176488..4dee577 100644 --- a/src/test/java/com/gxwebsoft/generator/SysGenerator.java +++ b/src/test/java/com/gxwebsoft/generator/SysGenerator.java @@ -50,7 +50,7 @@ public class SysGenerator { // "sys_industry" // "sys_plug", // "sys_company" -// "sys_user_oauth" + "sys_user_oauth" // "sys_user_grade" // "sys_user_referee" // "sys_notice" @@ -60,9 +60,9 @@ public class SysGenerator { // "sys_chat_message", // "sys_chat_conversation" // "sys_user_group" - "sys_app", - "sys_app_user", - "sys_app_url" +// "sys_app", +// "sys_app_user", +// "sys_app_url" }; // 需要去除的表前缀 private static final String[] TABLE_PREFIX = new String[]{