Java-企业微信获取登录用户的userid问题点解决记录

常遇问题之一 —— redirect _ uri需使用应用可信域名

原因:企微配置可信域名与redirect _ uri访问链接不一致

在本次java开发中,我遇到问题如下:

我要访问的链接是http://xxx.xx.cn:8020,我目前直接访问网页可以访问成功。但是在企业微信中需要设置可信域名,按习惯我将可行域名设置为xxx.xx.cn(之前该域名已认证过),访问获取code的相关链接发现提示上述错误,排查原因是企微要求配置的可信域名,必须与访问链接的域名完全一致;若访问链接URL带了端口号,端口号也需要登记到可信域名中,也就是我们可信域名要设置为xxx.xx.cn:8020,详细说明参考以下官方文档说明。

此时如果我们将可信域名设置为xxx.xx.cn:8020时我们会遇到另一个问题就是会提示 “域名所有权检验不通过”

遇到一个问题便解决一个问题,经过查找资料我们看到了以下官方说明

设置可信域名时,提示“检查域名所有权不通过”-帮助中心-企业微信icon-default.png?t=O83Ahttps://open.work.weixin.qq.com/help2/pc/15370

其中重点为:假设系统生成的校验文件是WW_verify_7rG3kjVbXHngiald.txt,则下载该文件并放到wx.qq.com的根目录下,然后在浏览器打开以下链接检查是否能正常访问:https://wx.qq.com/WW_verify_7rG3kjVbXHngiald.txt 

在这块我遇到的问题是对域名根目录的位置产生了疑问,可能对一些开发小白也会有此疑惑,最初以为是放在项目文件的最外层,显然事实告诉我并不对,后来突然想到这不是静态文件吗,那么岂不是和一些css文件大同小异,于是进行尝试,首先去随机访问了一个css文件,查看其位置,如下图所示

既然我们要让这个链接https://wx.qq.com/WW_verify_7rG3kjVbXHngiald.txt得以访问,那么css文件最外层所在位置便是我们要放TXT校验文件的位置

于是在我的springboot项目中我找到了以下位置,大家可以进行参考

接着我又遇到一个问题,虽然放在了最外层,但依旧无法通过企业微信提供的访问地址访问到校验文件,继续排查,我们仔细观察刚才的css文件访问地址,可以发现在端口号后还有我们固定的项目路径,在项目路径后才是css文件的层级位置,豁然开朗。

这里可能有些开发者不会遇到该问题,可跳过,但按照部分人的开发习惯,我们可能会在配置文件中配置server.servlet.context-path=/xxxxx

这个配置作用如下

参考文章:Springboot 添加server.servlet.context-path相关使用总结-优快云博客icon-default.png?t=O83Ahttps://blog.youkuaiyun.com/qq_38322527/article/details/101691785

看到这里我们就知道该如何处理了

那就是先屏蔽此句配置,解决我们眼前的问题,也就是让我们的校验文件可以用这个链接
https://wx.qq.com/WW_verify_7rG3kjVbXHngiald.txt  访问到

到此我们运行项目,浏览器访问链接成功。

接下来就是将项目放在域名指定服务器上,这里是因为我本地电脑并未匹配该域名的权限,大家可以视自己情况选择。

顺便提一下这里还可能存在的一个问题,就是你的端口号未被授予外网访问权限,这样就会存在你用IP地址虽然可以正常访问到校验文件,但是域名访问不成功,仔细阅读以下文件说明可知

详见:

自建应用 “域名归属校验不通过” 及 “域名主体校验未通过”问题!ToB Dev企微常见问题系列 - 开发者社区 - 企业微信开发者中心icon-default.png?t=O83Ahttps://developer.work.weixin.qq.com/community/article/detail?content_id=16526195469746891698

此时需要进行网络方面的开通,处理方法在此不予说明,当我们的链接通过域名得以访问,也就是用企微提供的连接(如下图)能访问到,我们就可以去企微进行域名验证啦

验证成功如下:

到此,我们遇到的问题一正式解决。

接下来我们就可以正式展开开发,毕竟这只是最最开始的一步,接着我们回归正轨,也就是获取userid的前置任务——获取code,在此过程中除了上述提到的域名验证问题还有以下几个注意点

  1. 得到拼接的OAuth2链接

https://open.weixin.qq.com/connect/oauth2/authorize?appid=CorpID&redirect_uri=https://www.xxx.com/test&response_type=code&scope=snsapi_base&agentid=AgentId&state=test#wechat_redirect 

注意根据URL规范,将上述参数redirect_uri分别进行UrlEncode,详见官方文档实例:

参考官方文件:

构造网页授权链接 - 文档 - 企业微信开发者中心icon-default.png?t=O83Ahttps://developer.work.weixin.qq.com/document/path/91022

相关代码如下:

Controller文件

可复制代码:

@Controller
@RequestMapping("/assetSearch")
public class AssetSearchController {

    //访问code
    @RequestMapping("/toGetCode")
    public void toGetCode(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        WechatConfigUtil.getCode(request, response);
    }

    //    获取userid返回页面

    @RequestMapping("/toAssetSearch")
    @ResponseBody
    public String toAssetSearch(Model model, @RequestParam(value = "code", required = false) String code) throws IOException {
        String userId = WechatConfigUtil.getUserId(code);
        return "userId:" + userId;
    }

WechatConfigUtil工具类

可复制:

@Component
public class WechatConfigUtil {
    private static Integer agentId;
    private static String secret;
    // 企业id
    private static String corpId;
    // 用于访问redis的密码,没设置就不需要这个字段
    private static String redisPwd;

    @Value("${wx-cp-config.secret}")
    public void setSecret(String secret) {
        WechatConfigUtil.secret = secret;
    }

    @Value("${wx-cp-config.corpid}")
    public void setCorpId(String corpId) {
        WechatConfigUtil.corpId = corpId;
    }

    @Value("${wx-cp-config.redis-pwd}")
    public void setRedisPwd(String redisPwd) {
        WechatConfigUtil.redisPwd = redisPwd;
    }

    @Value("${wx-cp-config.agentid}")
    public void setAgentId(Integer agentId) {
        WechatConfigUtil.agentId = agentId;
    }

    private static final String REDIRECT_URI = "填写转换完的URL"; // 回调URL
    //获取code
    public static void getCode(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 从请求参数中获取code
        String code = request.getParameter("code");
        if (code != null) {
            response.getWriter().println("Received code: " + code);
        } else {
            // 如果没有code,则构建授权URL并重定向用户
            String authUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + corpId + "&redirect_uri=" + REDIRECT_URI +"&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect";
            response.sendRedirect(authUrl);
        }
    }

    //企业微信获取访问用户身份userID
    public static String getUserId(String code) throws IOException {
        String accessToken = AccessTokenUtil.getAccessToken(corpId, secret);
        String url = "https://qyapi.weixin.qq.com/cgi-bin/auth/getuserinfo?access_token=ACCESS_TOKEN&code=CODE";
        url = url.replace("ACCESS_TOKEN", accessToken).replace("CODE", code);
        String res = HttpRequest.get(url).execute().body();
        JSONObject jsonObject = JSON.parseObject(res);
        String userId = (String) jsonObject.get("userid");
//      System.out.println(userId1);

        return userId;

    }

AccessTokenUtil(获取access_token实现

可复制:

import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import java.io.IOException;
//获取Token接口
public class AccessTokenUtil {
    public static String getAccessToken(String CORP_ID,String CORP_SECRET) throws IOException {
        String GetToken = "https://qyapi.weixin.qq.com/cgi-bin/gettoken";
        String ACCESS_TOKEN_URL = GetToken +"?Corpid=" + CORP_ID + "&corpsecret=" + CORP_SECRET;
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url(ACCESS_TOKEN_URL)
                .build();
        Response response = client.newCall(request).execute();

        if (response.isSuccessful()) {
            String responseBody = response.body().string();
            JsonObject jsonObject = JsonParser.parseString(responseBody).getAsJsonObject();
            return jsonObject.get("access_token").getAsString();
        } else {
            throw new IOException("Failed to get access token");
        }
    }

}

到此已获取到userid,可以用userid继续进行相关操作,例如查询某些信息等等。

Ps:留在最后:

遇到问题就去解决问题,逐层剖析,逐步解决,一定要勇于尝试,让自己的想法落于实践,试错的过程注定漫长,但这些终将会成为我们宝贵的经验。

企业微信开发中,通过手机号获取用户ID(UserID)通常涉及调用企业微信提供的API来完成。企业微信提供了相应的接口支持,开发者可以通过这些接口实现根据手机号查询用户信息的求。 ### 通过手机号获取用户ID的流程 1. **获取访问令牌(access_token)** 在调用企业微信API之前,要先获取`access_token`。这是调用大多数企业微信接口的必要参数,通常通过企业的CorpID和CorpSecret来获取。 2. **调用获取用户信息的接口** 企业微信提供了一个接口用于根据手机号查询用户UserID,具体接口为: ``` POST https://qyapi.weixin.qq.com/cgi-bin/user/getuserid?access_token=ACCESS_TOKEN ``` 请求体要包含手机号信息,示例如下: ```json { "mobile": "13800000000" } ``` 调用成功后,返回的结果中将包含对应的用户UserID: ```json { "errcode": 0, "errmsg": "ok", "userid": "zhangsan" } ``` 3. **处理异常情况** 如果手机号未绑定到企业微信用户,或者手机号输入错误,接口会返回相应的错误码和提示信息。因此,在实际开发中,要对可能的异常情况进行捕获和处理。 ### Java代码示例 以下是一个简单的Java代码片段,展示了如何通过HTTP请求调用上述接口: ```java import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; public class WeComUserService { private static final String GET_USERID_URL = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserid?access_token="; public String getUserIdByMobile(String accessToken, String mobile) throws Exception { String requestUrl = GET_USERID_URL + accessToken; URL url = new URL(requestUrl); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST"); conn.setDoOutput(true); conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8"); String jsonInputString = "{\"mobile\": \"" + mobile + "\"}"; try (OutputStream os = conn.getOutputStream()) { byte[] input = jsonInputString.getBytes("utf-8"); os.write(input, 0, input.length); } StringBuilder response = new StringBuilder(); try (BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"))) { String responseLine = null; while ((responseLine = br.readLine()) != null) { response.append(responseLine.trim()); } } // 解析返回结果,提取userid字段 // 这里可以使用JSON解析库如Gson或Jackson进行更复杂的解析 if (response.toString().contains("\"userid\"")) { int startIndex = response.indexOf("\"userid\": \"") + 11; int endIndex = response.indexOf("\"", startIndex); return response.substring(startIndex, endIndex); } else { throw new RuntimeException("Failed to get user ID: " + response.toString()); } } public static void main(String[] args) { try { WeComUserService service = new WeComUserService(); String accessToken = "YOUR_ACCESS_TOKEN"; // 替换为实际的access_token String mobile = "13800000000"; // 替换为要查询的手机号 String userId = service.getUserIdByMobile(accessToken, mobile); System.out.println("User ID: " + userId); } catch (Exception e) { e.printStackTrace(); } } } ``` ### 注意事项 - **权限问题**:确保应用具有调用相关接口的权限。 - **安全性**:`access_token`是敏感信息,不应硬编码在代码中,建议通过配置文件或安全存储方式管理[^2]。 - **错误处理**:在生产环境中,应添加更详细的日志记录和错误处理机制,以应对网络问题或API返回异常的情况。 通过上述步骤和代码示例,可以在Java开发中实现根据手机号获取企业微信用户ID的功能。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值