添加微信接口

master
吴顺杰 10 months ago
parent d950819399
commit 41dcf52b25

@ -0,0 +1,98 @@
package com.ruoyi.system.controller;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.system.domain.dto.request.WeChatCodeRequest;
import com.ruoyi.system.domain.dto.request.WeChatRequest;
import com.ruoyi.system.service.WeChatService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
*
*
* @Author: wu
* @DateTime: 2023/4/25 9:14
*/
@Api(tags = "微信签名")
@RestController
@RequestMapping("/shian/wechat")
@Transactional(rollbackFor = Exception.class)
public class WeChatController extends BaseController {
@Resource
private WeChatService weChatService;
/**
* accessToken
*
* @return accessToken
*/
@ApiOperation("获取微信accessToken")
@GetMapping("/findAccessToken")
public AjaxResult findAccessToken() {
return AjaxResult.success(weChatService.findAccessToken());
}
/**
*
*
* @param req
* @return
*/
@ApiOperation("获取微信二维码")
@PostMapping("/findWxCode")
public AjaxResult findWxCode(@RequestBody WeChatCodeRequest req) {
return AjaxResult.success(weChatService.findWxCode(req));
}
/**
*
*
* @param code
* @return
*/
@ApiOperation("获取微信手机号")
@GetMapping("/getUserPhoneNumber")
public AjaxResult getUserPhoneNumber(String code) {
return AjaxResult.success(weChatService.getUserPhoneNumber(code));
}
/**
* jsapiTicket
*
* @return jsapiTicket
*/
@ApiOperation("获取微信jsapiTicket")
@GetMapping("/findJsapiTicket")
public AjaxResult findJsapiTicket() {
return AjaxResult.success(weChatService.findJsapiTicket());
}
/**
*
*
* @param req
* @return
*/
@ApiOperation("微信获取签名")
@GetMapping("/findSignature")
public AjaxResult findSignature(@Validated WeChatRequest req) {
return AjaxResult.success(weChatService.findSignature(req));
}
}

@ -0,0 +1,47 @@
package com.ruoyi.system.domain.dto.request;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
/**
*
*
* @author wu
* @since 2023/11/27 15:19
*/
@Data
@ApiModel(value = "获取小程序码请求类")
public class WeChatCodeRequest implements Serializable {
private static final long serialVersionUID = 8837329526135742856L;
/**
* 1024 scancode_time
* query
* "?foo=bar" wx.getLaunchOptionsSync query
* {foo:"bar"}
*/
@ApiModelProperty(value = "扫码进入的小程序页面路径,最大长度 1024 个字符,不能为空," +
"scancode_time为系统保留参数不允许配置对于小游戏可以只传入 query 部分," +
"来实现传参效果,如:传入 \"?foo=bar\",即可在 wx.getLaunchOptionsSync " +
"接口中的 query 参数获取到 {foo:\"bar\"}。", required = true)
@NotBlank(message = "小程序页面路径不能为空")
private String path;
/**
* px430 280px 1280px
*/
@ApiModelProperty(value = "二维码的宽度,单位 px。默认值为430最小 280px最大 1280px")
private Integer width;
/**
* id
*/
@ApiModelProperty(value = "商户id", required = true)
@NotNull(message = "商户id不能为空")
private Long shanghuId;
}

@ -0,0 +1,41 @@
package com.ruoyi.system.domain.dto.request;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import java.io.Serializable;
/**
*
*
* @Author: wu
* @DateTime: 2023/4/25 10:37
*/
@Data
@ApiModel("微信获取签名请求类")
public class WeChatRequest implements Serializable {
private static final long serialVersionUID = 8932390218136420099L;
/**
*
*/
@ApiModelProperty(value = "随机字符串", required = true)
@NotBlank(message = "字符串不能为空")
private String noncestr;
/**
*
*/
@ApiModelProperty(value = "时间戳", required = true)
@NotBlank(message = "时间戳不能为空")
private String timestamp;
/**
* URL
*/
@ApiModelProperty(value = "当前网页的URL", required = true)
@NotBlank(message = "当前网页的URL不能为空")
private String url;
}

@ -0,0 +1,54 @@
package com.ruoyi.system.service;
import com.ruoyi.system.domain.dto.request.WeChatCodeRequest;
import com.ruoyi.system.domain.dto.request.WeChatRequest;
import java.util.Map;
/**
*
*
* @Author: wu
* @DateTime: 2023/4/25 9:30
*/
public interface WeChatService {
/**
* accessToken
*
* @return accessToken
*/
String findAccessToken();
/**
* jsapiTicket
*
* @return jsapiTicket
*/
String findJsapiTicket();
/**
*
*
* @param req
* @return
*/
String findSignature(WeChatRequest req);
/**
*
*
* @param code
* @return
*/
Map<String, Object> getUserPhoneNumber(String code);
/**
*
*
* @param req
* @return
*/
byte[] findWxCode(WeChatCodeRequest req);
}

@ -0,0 +1,159 @@
package com.ruoyi.system.service.impl;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.ruoyi.common.constant.TokenConstants;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.system.domain.dto.request.WeChatCodeRequest;
import com.ruoyi.system.domain.dto.request.WeChatRequest;
import com.ruoyi.system.service.WeChatService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Formatter;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
*
*
* @Author: wu
* @DateTime: 2023/4/25 9:31
*/
@Service
public class WeChatServiceImpl implements WeChatService {
@Value("${wechat.appid}")
private String appid;
@Value("${wechat.secret}")
private String secret;
@Resource
private RedisCache redisCache;
/**
* sha
*
* @param str
* @return
* @throws NoSuchAlgorithmException
*/
private String SHA1(String str) throws NoSuchAlgorithmException {
MessageDigest crypt = MessageDigest.getInstance("SHA-1");
crypt.reset();
crypt.update(str.getBytes());
Formatter formatter = new Formatter();
for (byte b : crypt.digest()) {
formatter.format("%02x", b);
}
String result = formatter.toString();
formatter.close();
return result;
}
@Override
public String findAccessToken() {
String accessToken;
accessToken = redisCache.getCacheObject(TokenConstants.ACCESS_TOKEN + appid);
if (StrUtil.isNotEmpty(accessToken)) {
return accessToken;
}
Map<String, Object> map = new HashMap<>(3);
String grantType = "client_credential";
map.put("grant_type", grantType);
map.put("appid", appid);
map.put("secret", secret);
String body = HttpUtil.get("https://api.weixin.qq.com/cgi-bin/token", map);
accessToken = (String) new JSONObject(body).get("access_token");
// accessToken存入redis
redisCache.setCacheObject(TokenConstants.ACCESS_TOKEN + appid, accessToken, 7200, TimeUnit.SECONDS);
return accessToken;
}
@Override
public String findJsapiTicket() {
String ticket;
ticket = redisCache.getCacheObject(TokenConstants.JsapiTicket + appid);
if (StrUtil.isNotEmpty(ticket)) {
return ticket;
}
String accessToken = findAccessToken();
Map<String, Object> map = new HashMap<>(2);
map.put("access_token", accessToken);
String type = "jsapi";
map.put("type", type);
String body = HttpUtil.get("https://api.weixin.qq.com/cgi-bin/ticket/getticket", map);
ticket = (String) new JSONObject(body).get("ticket");
// accessToken存入redis
redisCache.setCacheObject(TokenConstants.JsapiTicket + appid, ticket, 7200, TimeUnit.SECONDS);
return ticket;
}
@Override
public String findSignature(WeChatRequest req) {
String signature;
String jsapi_ticket = findJsapiTicket();
String url = req.getUrl();
String nonceStr = req.getNoncestr();
String timestamp = req.getTimestamp();
String[] arr = new String[]{"jsapi_ticket=" + jsapi_ticket, "noncestr=" + nonceStr, "timestamp=" + timestamp, "url=" + url};
Arrays.sort(arr);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < arr.length; i++) {
sb.append(arr[i]);
if (i != arr.length - 1) {
sb.append("&");
}
}
try {
signature = SHA1(sb.toString());
} catch (Exception e) {
throw new ServiceException("未知异常,请联系管理员");
}
return signature;
}
/**
*
*
* @param code
* @return
*/
@Override
public Map<String, Object> getUserPhoneNumber(String code) {
String accessToken = this.findAccessToken();
Map<String, Object> map = new HashMap<>();
map.put("code", code);
String jsonStr = JSONUtil.toJsonStr(map);
String body = HttpUtil.post("https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" + accessToken, jsonStr);
return new JSONObject(body);
}
/**
*
*
* @param req
* @return
*/
@Override
public byte[] findWxCode(WeChatCodeRequest req) {
String accessToken = this.findAccessToken();
Map<String, Object> map = new HashMap<>();
if (req.getWidth() != null) {
map.put("width", req.getWidth());
}
map.put("path", req.getPath() + "?shanghuId=" + req.getShanghuId());
String jsonStr = JSONUtil.toJsonStr(map);
String body = HttpUtil.post("https://api.weixin.qq.com/wxa/getwxacode?access_token=" + accessToken, jsonStr);
return body.getBytes();
}
}

@ -136,3 +136,7 @@ xss:
excludes: /system/notice
# 匹配链接
urlPatterns: /system/*,/monitor/*,/tool/*
wechat:
appid: wxba26a482b035e825
secret: 9e8777a19992b5017a5da7621599373e

@ -0,0 +1,25 @@
package com.ruoyi.common.constant;
/**
* token
*
* @Author: wu
* @DateTime: 2023/3/14 17:18
*/
public class TokenConstants {
/**
* redis token
*/
public static String LOGIN_INFO = "loginInfo:";
/**
* redis WeChat token
*/
public static String ACCESS_TOKEN = "accessToken:";
/**
* redis WeChat ticket
*/
public static String JsapiTicket = "jsapiTicket:";
}
Loading…
Cancel
Save