|
|
@@ -0,0 +1,419 @@
|
|
|
+package com.jpsoft.employment.modules.wechat.controller;
|
|
|
+
|
|
|
+import cn.hutool.core.date.DateUtil;
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
+import com.alibaba.fastjson.TypeReference;
|
|
|
+import com.alipay.api.domain.CompanyInfo;
|
|
|
+import com.jpsoft.employment.config.WxConfig;
|
|
|
+import com.jpsoft.employment.modules.common.dto.MessageResult;
|
|
|
+import com.jpsoft.employment.modules.common.service.impl.RedisServiceImpl;
|
|
|
+import com.jpsoft.employment.modules.common.utils.Generator.CaptchaUtilA;
|
|
|
+import com.jpsoft.employment.modules.common.utils.Generator.CircleCaptchaA;
|
|
|
+import com.jpsoft.employment.modules.common.utils.SMSUtil;
|
|
|
+import com.jpsoft.employment.modules.common.utils.Sign;
|
|
|
+import com.jpsoft.employment.modules.common.utils.WeixinUtil;
|
|
|
+import com.jpsoft.employment.modules.job.entity.JobUser;
|
|
|
+import com.jpsoft.employment.modules.job.service.JobUserService;
|
|
|
+import com.jpsoft.employment.modules.pay.properties.WxPayProperties;
|
|
|
+import com.jpsoft.employment.modules.sys.entity.User;
|
|
|
+import com.jpsoft.employment.modules.sys.service.UserService;
|
|
|
+import com.jpsoft.employment.modules.wechat.callback.EventCallback;
|
|
|
+import com.jpsoft.employment.modules.wechat.entity.AccessToken;
|
|
|
+import com.jpsoft.employment.modules.wechat.vo.UserInfo;
|
|
|
+import com.sun.corba.se.impl.protocol.giopmsgheaders.ReplyMessage;
|
|
|
+import io.swagger.annotations.ApiImplicitParam;
|
|
|
+import io.swagger.annotations.ApiImplicitParams;
|
|
|
+import io.swagger.annotations.ApiOperation;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
+import org.apache.http.HttpResponse;
|
|
|
+import org.apache.http.HttpStatus;
|
|
|
+import org.apache.http.client.methods.HttpPost;
|
|
|
+import org.apache.http.entity.StringEntity;
|
|
|
+import org.apache.http.impl.client.CloseableHttpClient;
|
|
|
+import org.apache.http.impl.client.HttpClientBuilder;
|
|
|
+import org.apache.http.util.EntityUtils;
|
|
|
+import org.springframework.beans.BeanUtils;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.data.redis.core.ValueOperations;
|
|
|
+import org.springframework.web.bind.annotation.*;
|
|
|
+
|
|
|
+import javax.servlet.http.HttpServletRequest;
|
|
|
+import javax.servlet.http.HttpServletResponse;
|
|
|
+import java.io.BufferedReader;
|
|
|
+import java.io.IOException;
|
|
|
+import java.io.InputStreamReader;
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.net.URLEncoder;
|
|
|
+import java.util.*;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+/**
|
|
|
+ * @author 墨鱼_mo
|
|
|
+ * @date 2019-12-3 15:08
|
|
|
+ */
|
|
|
+
|
|
|
+@Slf4j
|
|
|
+@RequestMapping("/wechat")
|
|
|
+@RestController
|
|
|
+public class WxController {
|
|
|
+
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private WxConfig wxConfig;
|
|
|
+
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private ValueOperations<String, Object> valueOperations;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private RedisServiceImpl redisService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private WxPayProperties wxPayProperties;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private JobUserService jobUserService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private UserService userService;
|
|
|
+
|
|
|
+ @ApiOperation(value = "获取微信配置")
|
|
|
+ @GetMapping(value = "/getConfig")
|
|
|
+ public MessageResult getConfig(String url) {
|
|
|
+
|
|
|
+ int code = 200;
|
|
|
+ String message = "获取成功";
|
|
|
+ Object data = "";
|
|
|
+ boolean result = true;
|
|
|
+
|
|
|
+ try {
|
|
|
+ AccessToken token = WeixinUtil.getAccessToken(wxPayProperties.getAppId(), wxPayProperties.getAppSecret());
|
|
|
+
|
|
|
+ Map<String, String> wxMap = Sign.sign(WeixinUtil.getJsAPI(token.getToken()), url);
|
|
|
+
|
|
|
+ wxMap.put("appId", wxPayProperties.getAppId());
|
|
|
+
|
|
|
+ log.warn(JSONObject.toJSONString(wxMap));
|
|
|
+
|
|
|
+ HashMap<String, Object> dataMap = new HashMap<String, Object>();
|
|
|
+
|
|
|
+ dataMap.put("wxConfig", wxMap);
|
|
|
+
|
|
|
+ data = dataMap;
|
|
|
+ } catch (Exception ex) {
|
|
|
+ log.error(ex.getMessage(),ex);
|
|
|
+
|
|
|
+ code = 500;
|
|
|
+ result = false;
|
|
|
+ message = "系统错误";
|
|
|
+ }
|
|
|
+
|
|
|
+ return new MessageResult(result, message, data, code);
|
|
|
+ }
|
|
|
+
|
|
|
+ @ApiOperation(value = "获取微信code")
|
|
|
+ @PostMapping(value = "findWechatUrl")
|
|
|
+ public MessageResult findWechatUrl(@RequestBody String url) {
|
|
|
+
|
|
|
+ String newpath = WeixinUtil.getCodeRequest(wxPayProperties.getAppId(), url, "snsapi_userinfo");
|
|
|
+
|
|
|
+ HashMap<String, Object> dataMap = new HashMap<String, Object>();
|
|
|
+
|
|
|
+ dataMap.put("wechatUrl", newpath);
|
|
|
+
|
|
|
+ return new MessageResult(true, "获取成功", dataMap, 200);
|
|
|
+ }
|
|
|
+
|
|
|
+ @ApiOperation(value = "获取公众号用户信息")
|
|
|
+ @GetMapping(value = "findUserInfo/{code}")
|
|
|
+ public MessageResult findUserInfo(@PathVariable String code) {
|
|
|
+ try {
|
|
|
+ log.warn("code=" + code);
|
|
|
+ log.warn("appId=" + wxPayProperties.getAppId());
|
|
|
+ log.warn("appSecret=" + wxPayProperties.getAppSecret());
|
|
|
+
|
|
|
+ AccessToken at = WeixinUtil.getAccessToken(wxPayProperties.getAppId(), wxPayProperties.getAppSecret(), code);
|
|
|
+
|
|
|
+
|
|
|
+ if (at != null && StringUtils.isNotBlank(at.getOpenid())) {
|
|
|
+ String openId = at.getOpenid();
|
|
|
+ System.out.println("openId:" + openId);
|
|
|
+
|
|
|
+ UserInfo userInfo = WeixinUtil.getUserInfo(openId, at.getToken());
|
|
|
+
|
|
|
+ HashMap<String, Object> dataMap = new HashMap<String, Object>();
|
|
|
+
|
|
|
+ dataMap.put("userInfo", userInfo);
|
|
|
+
|
|
|
+ return new MessageResult(true, "获取微信信息成功", userInfo, 200);
|
|
|
+
|
|
|
+ } else {
|
|
|
+ return new MessageResult(false, "获取微信信息失败", "", 400);
|
|
|
+ }
|
|
|
+
|
|
|
+ } catch (Exception ex) {
|
|
|
+ ex.printStackTrace();
|
|
|
+ return new MessageResult(false, "系统错误", "", 500);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @GetMapping(value = "getAppId/{id}")
|
|
|
+ @ResponseBody
|
|
|
+ public MessageResult getAppId(@PathVariable("id") String id) {
|
|
|
+
|
|
|
+ int code = 200;
|
|
|
+ String message = "获取成功";
|
|
|
+ Object data = "";
|
|
|
+ boolean result = true;
|
|
|
+
|
|
|
+ try {
|
|
|
+
|
|
|
+ HashMap<String, Object> wxMap = new HashMap<>();
|
|
|
+
|
|
|
+ wxMap.put("appId", wxPayProperties.getAppId());
|
|
|
+
|
|
|
+ HashMap<String, Object> dataMap = new HashMap<String, Object>();
|
|
|
+
|
|
|
+ dataMap.put("wxConfig", wxMap);
|
|
|
+
|
|
|
+ data = dataMap;
|
|
|
+
|
|
|
+ } catch (Exception ex) {
|
|
|
+ code = 500;
|
|
|
+ message = "系统错误";
|
|
|
+ result = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ return new MessageResult(result, message, data, code);
|
|
|
+ }
|
|
|
+
|
|
|
+ @ApiOperation(value = "获取图片验证码信息")
|
|
|
+ @GetMapping("/getVerifyPic")
|
|
|
+ public MessageResult getVerifyPic(String openId, HttpServletResponse response) {
|
|
|
+ int code = 200;
|
|
|
+ String message = "获取验证码成功";
|
|
|
+ Object data = "";
|
|
|
+ boolean result = true;
|
|
|
+
|
|
|
+ try {
|
|
|
+
|
|
|
+ if (StringUtils.isBlank(openId)) {
|
|
|
+ throw new Exception("openId为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ CircleCaptchaA captcha = CaptchaUtilA.createCircleCaptcha(200, 100, 4, 0);
|
|
|
+ captcha.write(response.getOutputStream());
|
|
|
+ String verifyPic = captcha.getCode();
|
|
|
+ redisService.put("code", openId, verifyPic, 120);
|
|
|
+
|
|
|
+
|
|
|
+ response.getOutputStream().close();
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ code = 500;
|
|
|
+ message = e.getMessage();
|
|
|
+ result = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ return new MessageResult(result, message, data, code);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @ApiOperation(value = "管理员绑定微信openid")
|
|
|
+ @PostMapping(value = "/bindWechat")
|
|
|
+ public MessageResult<String> bindWechat(String eventKey,String openId){
|
|
|
+ MessageResult<String> messageResult = new MessageResult<>();
|
|
|
+
|
|
|
+ try{
|
|
|
+ String[] arr = eventKey.split(",");
|
|
|
+
|
|
|
+ String userId = arr[1];
|
|
|
+ User user = userService.get(userId);
|
|
|
+
|
|
|
+ if (user!=null) {
|
|
|
+ user.setOpenId(openId);
|
|
|
+ user.setUpdateTime(new Date());
|
|
|
+ user.setUpdateBy(userId);
|
|
|
+ userService.update(user);
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ throw new Exception("用户不存在!");
|
|
|
+ }
|
|
|
+
|
|
|
+ messageResult.setMessage(user.getUserName() + "绑定微信成功!");
|
|
|
+ messageResult.setResult(true);
|
|
|
+ }
|
|
|
+ catch (Exception ex){
|
|
|
+ messageResult.setResult(false);
|
|
|
+ messageResult.setMessage(ex.getMessage());
|
|
|
+
|
|
|
+ log.error(ex.getMessage(),ex);
|
|
|
+ }
|
|
|
+
|
|
|
+ return messageResult;
|
|
|
+ }
|
|
|
+
|
|
|
+ @ApiOperation(value = "用户绑定微信openid")
|
|
|
+ @PostMapping(value = "/bindPersonWechat")
|
|
|
+ public MessageResult<String> bindPersonWechat(String eventKey,String openId){
|
|
|
+ MessageResult<String> messageResult = new MessageResult<>();
|
|
|
+
|
|
|
+ try{
|
|
|
+ String[] arr = eventKey.split(",");
|
|
|
+
|
|
|
+ String userId = arr[1];
|
|
|
+ String phone = arr[2];
|
|
|
+
|
|
|
+ JobUser jobUser = jobUserService.get(userId);
|
|
|
+
|
|
|
+ //多传一个电话号码避免,测试环境和正式环境混淆
|
|
|
+ if (jobUser!=null) {
|
|
|
+ if(jobUser.getTel().equals(phone)) {
|
|
|
+ jobUser.setOpenId(openId);
|
|
|
+ jobUser.setUpdateTime(new Date());
|
|
|
+ jobUser.setUpdateBy(userId);
|
|
|
+ jobUserService.update(jobUser);
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ throw new Exception("用户手机号错误!");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ throw new Exception("用户不存在!");
|
|
|
+ }
|
|
|
+
|
|
|
+ messageResult.setMessage(jobUser.getRealName() + "绑定微信成功!");
|
|
|
+ messageResult.setResult(true);
|
|
|
+ }
|
|
|
+ catch (Exception ex){
|
|
|
+ messageResult.setResult(false);
|
|
|
+ messageResult.setMessage(ex.getMessage());
|
|
|
+
|
|
|
+ log.error(ex.getMessage(),ex);
|
|
|
+ }
|
|
|
+
|
|
|
+ return messageResult;
|
|
|
+ }
|
|
|
+
|
|
|
+ @ApiOperation(value = "验证服务器地址的有效性")
|
|
|
+ @GetMapping("/get")
|
|
|
+ @ResponseBody
|
|
|
+ public String index(@RequestParam(defaultValue = "") String signature,
|
|
|
+ @RequestParam(defaultValue = "") String timestamp,
|
|
|
+ @RequestParam(defaultValue = "") String nonce,
|
|
|
+ @RequestParam(defaultValue = "") String echostr) {
|
|
|
+ log.warn("signature=" + signature);
|
|
|
+ log.warn("timestamp=" + timestamp);
|
|
|
+ log.warn("nonce=" + nonce);
|
|
|
+ log.warn("echostr=" + echostr);
|
|
|
+
|
|
|
+ if (WeixinUtil.checkSignature(wxConfig.getToken(), signature, timestamp, nonce)) {
|
|
|
+ return echostr;
|
|
|
+ } else {
|
|
|
+ return "index";
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @ResponseBody
|
|
|
+ @ApiOperation(value = "创建二维码")
|
|
|
+ @PostMapping("/qrcode/create")
|
|
|
+ @ApiImplicitParams({
|
|
|
+ @ApiImplicitParam(name = "expire_seconds", paramType = "query", required = true, value = "该二维码有效时间,以秒为单位。 最大不超过2592000(即30天),此字段如果不填,则默认有效期为30秒。"),
|
|
|
+ @ApiImplicitParam(name = "action_name", paramType = "query", required = true, value = "二维码类型,QR_SCENE为临时的整型参数值,QR_STR_SCENE为临时的字符串参数值,QR_LIMIT_SCENE为永久的整型参数值,QR_LIMIT_STR_SCENE为永久的字符串参数值"),
|
|
|
+ @ApiImplicitParam(name = "scene_id", paramType = "query", value = "场景值ID,临时二维码时为32位非0整型,永久二维码时最大值为100000(目前参数只支持1--100000)"),
|
|
|
+ @ApiImplicitParam(name = "scene_str", paramType = "query", value = "场景值ID(字符串形式的ID),字符串类型,长度限制为1到64")
|
|
|
+ })
|
|
|
+ public cn.hutool.json.JSONObject createQrcode(@RequestParam(name = "expire_seconds", defaultValue = "300") long expireSeconds,
|
|
|
+ @RequestParam(name = "action_name", defaultValue = "QR_STR_SCENE") String actionName,
|
|
|
+ @RequestParam(name = "scene_id", required = false) String sceneId,
|
|
|
+ @RequestParam(name = "scene_str", required = false) String sceneStr) {
|
|
|
+ cn.hutool.json.JSONObject resultObj = new cn.hutool.json.JSONObject();
|
|
|
+
|
|
|
+ try {
|
|
|
+ StringBuilder urlBuilder = new StringBuilder();
|
|
|
+ AccessToken accessToken = WeixinUtil.getAccessToken(wxConfig.getAppId(), wxConfig.getAppSecret());
|
|
|
+
|
|
|
+ urlBuilder.append(wxConfig.getCreateQrCodeUrl())
|
|
|
+ .append("?access_token=")
|
|
|
+ .append(URLEncoder.encode(accessToken.getToken(), "UTF-8"));
|
|
|
+
|
|
|
+ cn.hutool.json.JSONObject jsonObject = new cn.hutool.json.JSONObject();
|
|
|
+ jsonObject.put("expire_seconds", expireSeconds);
|
|
|
+ jsonObject.put("action_name", actionName);
|
|
|
+
|
|
|
+ cn.hutool.json.JSONObject actionInfo = new cn.hutool.json.JSONObject();
|
|
|
+ cn.hutool.json.JSONObject scene = new cn.hutool.json.JSONObject();
|
|
|
+
|
|
|
+ StringBuilder keyBuilder = new StringBuilder();
|
|
|
+
|
|
|
+ keyBuilder.append(accessToken);
|
|
|
+
|
|
|
+ if (StringUtils.isNotEmpty(sceneId)) {
|
|
|
+ scene.put("scene_id", sceneId);
|
|
|
+ keyBuilder.append(sceneId);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (StringUtils.isNotEmpty(sceneStr)) {
|
|
|
+ scene.put("scene_str", sceneStr);
|
|
|
+ keyBuilder.append(sceneStr);
|
|
|
+ }
|
|
|
+
|
|
|
+ String qrcodeUrl = (String) valueOperations.get("QRCODE_" + keyBuilder.toString());
|
|
|
+
|
|
|
+ if (StringUtils.isNotEmpty(qrcodeUrl)) {
|
|
|
+ resultObj.put("data", qrcodeUrl);
|
|
|
+ resultObj.put("result", true);
|
|
|
+ } else {
|
|
|
+ actionInfo.put("scene", scene);
|
|
|
+
|
|
|
+ jsonObject.put("action_info", actionInfo);
|
|
|
+
|
|
|
+ StringEntity entity = new StringEntity(jsonObject.toString(), "utf-8");
|
|
|
+
|
|
|
+ entity.setContentType("application/json");//发送json数据需要设置contentType
|
|
|
+
|
|
|
+ HttpPost httpPost = new HttpPost(urlBuilder.toString());
|
|
|
+ CloseableHttpClient httpClient = HttpClientBuilder.create().build();
|
|
|
+
|
|
|
+ httpPost.setEntity(entity);
|
|
|
+
|
|
|
+ HttpResponse res = httpClient.execute(httpPost);
|
|
|
+
|
|
|
+ if (res.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
|
|
|
+ String content = EntityUtils.toString(res.getEntity());// 返回json格式:
|
|
|
+ cn.hutool.json.JSONObject ret = new cn.hutool.json.JSONObject(content);
|
|
|
+
|
|
|
+ if (ret.containsKey("errcode")) {
|
|
|
+ resultObj.put("result", false);
|
|
|
+ resultObj.put("message", ret.getStr("errmsg"));
|
|
|
+ resultObj.put("code", ret.getInt("errcode"));
|
|
|
+ } else {
|
|
|
+ String ticket = ret.getStr("ticket");
|
|
|
+ long expire_seconds = ret.getLong("expire_seconds");
|
|
|
+
|
|
|
+ qrcodeUrl = wxConfig.getShowQrCodeUrl() + "?ticket=" + URLEncoder.encode(ticket, "UTF-8");
|
|
|
+
|
|
|
+ valueOperations.set("QRCODE_" + keyBuilder, qrcodeUrl, expire_seconds - 5, TimeUnit.SECONDS);
|
|
|
+
|
|
|
+ resultObj.put("data", qrcodeUrl);
|
|
|
+ resultObj.put("result", true);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ resultObj.put("result", false);
|
|
|
+ resultObj.put("message", "weixin服务器未正常返回!");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (Exception ex) {
|
|
|
+ log.error(ex.getMessage(), ex);
|
|
|
+
|
|
|
+ resultObj.put("message", ex.getMessage());
|
|
|
+ resultObj.put("result", false);
|
|
|
+ }
|
|
|
+
|
|
|
+ return resultObj;
|
|
|
+ }
|
|
|
+}
|