wlzboy
2025-09-22 fe95f471666d93e7822a4886c1c69dafbd6b2a1e
ruoyi-common/src/main/java/com/ruoyi/common/utils/WechatUtils.java
@@ -4,7 +4,7 @@
import com.alibaba.fastjson2.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.client.RestTemplate;
import com.ruoyi.common.utils.http.HttpUtils;
import java.util.HashMap;
import java.util.Map;
@@ -18,7 +18,8 @@
    
    private static final Logger log = LoggerFactory.getLogger(WechatUtils.class);
    
    private static final String WECHAT_API_BASE_URL = "https://api.weixin.qq.com";
    private static final String WECHAT_API_BASE_URL = "https://open.weixin.qq.com";
    private static final String WECHAT_API_BASE_URL_SERVER = "https://api.weixin.qq.com";
    
    /**
     * 获取微信Access Token
@@ -29,10 +30,10 @@
     */
    public static String getAccessToken(String appId, String appSecret) {
        try {
            String url = WECHAT_API_BASE_URL + "/cgi-bin/token?grant_type=client_credential&appid=" + appId + "&secret=" + appSecret;
            String url = WECHAT_API_BASE_URL_SERVER + "/cgi-bin/token";
            String param = "grant_type=client_credential&appid=" + appId + "&secret=" + appSecret;
            
            RestTemplate restTemplate = new RestTemplate();
            String response = restTemplate.getForObject(url, String.class);
            String response = HttpUtils.sendGet(url, param);
            
            JSONObject jsonObject = JSON.parseObject(response);
            if (jsonObject.containsKey("access_token")) {
@@ -56,10 +57,10 @@
     */
    public static JSONObject getWechatUserInfo(String accessToken, String openid) {
        try {
            String url = WECHAT_API_BASE_URL + "/cgi-bin/user/info?access_token=" + accessToken + "&openid=" + openid + "&lang=zh_CN";
            String url = WECHAT_API_BASE_URL_SERVER + "/cgi-bin/user/info";
            String param = "access_token=" + accessToken + "&openid=" + openid + "&lang=zh_CN";
            
            RestTemplate restTemplate = new RestTemplate();
            String response = restTemplate.getForObject(url, String.class);
            String response = HttpUtils.sendGet(url, param);
            
            JSONObject jsonObject = JSON.parseObject(response);
            if (jsonObject.containsKey("openid")) {
@@ -84,10 +85,10 @@
     */
    public static JSONObject getWebAccessToken(String appId, String appSecret, String code) {
        try {
            String url = WECHAT_API_BASE_URL + "/sns/oauth2/access_token?appid=" + appId + "&secret=" + appSecret + "&code=" + code + "&grant_type=authorization_code";
            String url = WECHAT_API_BASE_URL_SERVER + "/sns/oauth2/access_token";
            String param = "appid=" + appId + "&secret=" + appSecret + "&code=" + code + "&grant_type=authorization_code";
            
            RestTemplate restTemplate = new RestTemplate();
            String response = restTemplate.getForObject(url, String.class);
            String response = HttpUtils.sendGet(url, param);
            
            JSONObject jsonObject = JSON.parseObject(response);
            if (jsonObject.containsKey("access_token")) {
@@ -111,10 +112,10 @@
     */
    public static JSONObject getWebUserInfo(String accessToken, String openid) {
        try {
            String url = WECHAT_API_BASE_URL + "/sns/userinfo?access_token=" + accessToken + "&openid=" + openid + "&lang=zh_CN";
            String url = WECHAT_API_BASE_URL_SERVER + "/sns/userinfo";
            String param = "access_token=" + accessToken + "&openid=" + openid + "&lang=zh_CN";
            
            RestTemplate restTemplate = new RestTemplate();
            String response = restTemplate.getForObject(url, String.class);
            String response = HttpUtils.sendGet(url, param);
            
            JSONObject jsonObject = JSON.parseObject(response);
            if (jsonObject.containsKey("openid")) {
@@ -140,8 +141,16 @@
     */
    public static String generateAuthUrl(String appId, String redirectUri, String scope, String state) {
        try {
            String encodedRedirectUri = java.net.URLEncoder.encode(redirectUri, "UTF-8");
            return WECHAT_API_BASE_URL + "/connect/oauth2/authorize?appid=" + appId + "&redirect_uri=" + encodedRedirectUri + "&response_type=code&scope=" + scope + "&state=" + state + "#wechat_redirect";
            // 清理和验证redirectUri
            String cleanRedirectUri = cleanRedirectUri(redirectUri);
            // URL编码
            String encodedRedirectUri = java.net.URLEncoder.encode(cleanRedirectUri, "UTF-8");
            return WECHAT_API_BASE_URL + "/connect/oauth2/authorize?appid=" + appId +
                   "&redirect_uri=" + encodedRedirectUri +
                   "&response_type=code&scope=" + scope +
                   "&state=" + state + "#wechat_redirect";
        } catch (Exception e) {
            log.error("生成微信授权URL异常: {}", e.getMessage());
            return null;
@@ -149,6 +158,37 @@
    }
    
    /**
     * 清理和验证redirectUri
     *
     * @param redirectUri 原始回调地址
     * @return 清理后的回调地址
     */
    private static String cleanRedirectUri(String redirectUri) {
        if (StringUtils.isEmpty(redirectUri)) {
            return redirectUri;
        }
        try {
            // 移除端口号(微信授权不支持端口号)
            if (redirectUri.contains(":81") || redirectUri.contains(":8080") || redirectUri.contains(":3000")) {
                redirectUri = redirectUri.replaceAll(":(81|8080|3000|8081|8082|8083|8084|8085|8086|8087|8088|8089|8090)", "");
                log.warn("检测到端口号,已自动移除: {}", redirectUri);
            }
            // 确保使用HTTPS(生产环境)
            if (redirectUri.startsWith("http://") && !redirectUri.contains("localhost") && !redirectUri.contains("127.0.0.1")) {
                redirectUri = redirectUri.replace("http://", "https://");
                log.warn("生产环境建议使用HTTPS,已自动转换: {}", redirectUri);
            }
            return redirectUri;
        } catch (Exception e) {
            log.error("清理redirectUri异常: {}", e.getMessage());
            return redirectUri;
        }
    }
    /**
     * 判断是否为微信浏览器
     * 
     * @param userAgent 用户代理字符串