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

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

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


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

遇到一个问题便解决一个问题,经过查找资料我们看到了以下官方说明
设置可信域名时,提示“检查域名所有权不通过”-帮助中心-企业微信
https://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
这个配置作用如下
看到这里我们就知道该如何处理了
那就是先屏蔽此句配置,解决我们眼前的问题,也就是让我们的校验文件可以用这个链接
https://wx.qq.com/WW_verify_7rG3kjVbXHngiald.txt 访问到
到此我们运行项目,浏览器访问链接成功。
接下来就是将项目放在域名指定服务器上,这里是因为我本地电脑并未匹配该域名的权限,大家可以视自己情况选择。
顺便提一下这里还可能存在的一个问题,就是你的端口号未被授予外网访问权限,这样就会存在你用IP地址虽然可以正常访问到校验文件,但是域名访问不成功,仔细阅读以下文件说明可知
详见:
此时需要进行网络方面的开通,处理方法在此不予说明,当我们的链接通过域名得以访问,也就是用企微提供的连接(如下图)能访问到,我们就可以去企微进行域名验证啦
验证成功如下:
到此,我们遇到的问题一正式解决。
接下来我们就可以正式展开开发,毕竟这只是最最开始的一步,接着我们回归正轨,也就是获取userid的前置任务——获取code,在此过程中除了上述提到的域名验证问题还有以下几个注意点
- 得到拼接的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,详见官方文档实例:
参考官方文件:
构造网页授权链接 - 文档 - 企业微信开发者中心
https://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:留在最后:
遇到问题就去解决问题,逐层剖析,逐步解决,一定要勇于尝试,让自己的想法落于实践,试错的过程注定漫长,但这些终将会成为我们宝贵的经验。

454

被折叠的 条评论
为什么被折叠?



