Java-微信网页授权获取用户信息

微信网页授权后获取用户信息并重定向

微信公众号开发还是比较简单的,话不多说,直接开始演示微信网页如何授权获取用户信息。

微信开发文档:

https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html

开发思路:

1、提供一个链接,带有一个redirect_url参数,代表在获取用户信息后要返回的页面。
2、在上一个链接中跳转进行微信网页授权。
3、授权成功后获取code。
4、通过code调用微信接口获取access_token。
5、通过access_token获取用户基本信息。
6、将用户信息拼在之前定义的redirect_url中,并重定向到redirect_url。

Java代码

controller层


import com.aaa.project.system.emplikes.domain.Emplikes;
import com.aaa.project.system.emplikes.service.IEmplikesService;
import com.aaa.project.system.friendinfo.domain.Friendinfo;
import com.aaa.project.system.friendinfo.service.IFriendinfoService;
import com.aaa.project.system.wxuserinfo.domain.Wxuserinfo;
import com.aaa.project.system.wxuserinfo.service.IWxuserinfoService;
import com.aaa.project.tool.CORS.Cors;
import com.aaa.project.tool.WeChatAccredit.service.WXAccreditService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Controller
@RequestMapping("/wxaccredit")
public class WXAccreditController {

 	//微信授权后返回的地址
    private String getCodeUrl = "https://www.xxxx.cn/wxaccredit/redirect/code?redirect_url=";
    
    //微信网页授权地址
    private String getWechatCodeUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?" +
            "appid=[APPID]&" +                  //微信appid
            "redirect_uri=[REDIRECT_URI]&" +    //获取网页授权后,微信重定向地址
            "response_type=code&" +
            "scope=snsapi_userinfo&" +          //授权方式
            "state=STATE#wechat_redirect";

    /**
     * 微信点击授权重定向
     * @param redirectUrl 项目地址
     * @return 重定向获取信息
     * @throws UnsupportedEncodingException
     */
    @RequestMapping("/redirect")
    public String redirect( @RequestParam(name = "redirect_url", defaultValue = "", required = false) String redirectUrl ) throws UnsupportedEncodingException {
        //一次编码
        redirectUrl = URLEncoder.encode(redirectUrl, "utf-8");
        //二次编码
        redirectUrl = URLEncoder.encode(getCodeUrl + redirectUrl, "utf-8");
        //最终得到的微信获取微信授权地址
        String url = getWechatCodeUrl
                .replace("[APPID]", "xxxxxxxxxxxxxxxxx")
                .replace("[REDIRECT_URI]", redirectUrl);
        return "redirect:" + url;
    }

    /**
     * 这里的地址由微信重定向跳转,携带code参数。
     */
    @RequestMapping("/redirect/code")
    public String getCode(
            @RequestParam(name = "redirect_url", defaultValue = "", required = false) String redirect_url,
           @RequestParam(name = "code", defaultValue = "", required = false) String code) throws Exception {
        if (StringUtils.isBlank(code)) {
            return "redirect:" + redirect_url + "?error=code-is-null";
        }
        //解码重定向地址
        redirect_url = URLDecoder.decode(redirect_url, "utf-8");
        //根据code获取微信相关信息
        Map<String, Object> accesstokenInfo = wxAccreditService.getACCESSTOKEN(code);
        String errcode = (String)accesstokenInfo.get("errcode");
        String access_token = (String)accesstokenInfo.get("access_token");
        String refresh_token = (String)accesstokenInfo.get("refresh_token");
        String openid = (String)accesstokenInfo.get("openid");
        if(StringUtils.isEmpty(errcode)){
            //第四步:拉取用户信息(需scope为 snsapi_userinfo)
            Map<String, Object> weiXinUserInfo = wxAccreditService.getWeiXinUserInfo(accesstokenInfo);
            Map<String, Object> userInfo = createUserInfoHtml(weiXinUserInfo);
            Object openids = userInfo.get("openid");
            Object nickname = userInfo.get("nickname");
            Object headimgurl = userInfo.get("headimgurl");
            Object sexString = userInfo.get("sexString");
            Object province = userInfo.get("province");
            Object city = userInfo.get("city");
            Object country = userInfo.get("country");
            //----- 这里可以根据需要进行数据库操作,将数据添加到数据库中 -----
            //最后重定向到原来的页面中
            return "redirect:" + urls ;
        }
        return "";
    }
    
    /**
     * 生成微信用户信息
     * @param weiXinUserInfo
     * @return
     */
    private Map<String,Object> createUserInfoHtml(Map<String, Object> weiXinUserInfo) {
        String openid = (String)weiXinUserInfo.get("openid");
        String nickname = (String)weiXinUserInfo.get("nickname");
        Double sex = (Double)weiXinUserInfo.get("sex");
        String headimgurl = (String)weiXinUserInfo.get("headimgurl");
        String sexString = "";
        if(sex == 1.0d){
            sexString = "男";
        }else{
            sexString = "女";
        }
        String province = (String)weiXinUserInfo.get("province");
        String city = (String)weiXinUserInfo.get("city");
        String country = (String)weiXinUserInfo.get("country");
        Map<String,Object> map=new HashMap<>();
        map.put("openid",openid);
        map.put("nickname",nickname);
        map.put("sexString",sexString);
        map.put("headimgurl",headimgurl);
        map.put("province",province);
        map.put("city",city);
        map.put("country",country);
        return map;
    }
 }
    

service层


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Map;
import org.springframework.http.ResponseEntity;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import org.springframework.web.client.RestTemplate;

@Service
public class WXAccreditService {

    // 微信appid---微信公众平台
    public static final String appIdWx = "xxxxxxxxxxxx";
    // 微信AppSecret---微信公众平台
    public static final String appSecretWx = "xxxxxxxxxxxxxxxxx";

    @Autowired
    private RestTemplate restTemplate;

    private static final String GETWEIXINUSERINFO_AUTHORIZE="https://open.weixin.qq.com/connect/oauth2/authorize";
    private static final String GETWEIXINUSERINFO_GETACCESSTOKEN = "https://api.weixin.qq.com/sns/oauth2/access_token";
    private static final String GETWEIXINUSERINFO_GETUSERINFO = "https://api.weixin.qq.com/sns/userinfo";

    public String buildAuthorizeURL(String url){
        return concatAuthorizeURL(url);
    }

    /**
     * 拼接引导用户授权重定向的URL
     * snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid)
     * snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且, 即使在未关注的情况下,只要用户授权,也能获取其信息 )
     * @param url
     * @return
     */
    private String concatAuthorizeURL(String url) {
        StringBuilder authorizeUrl = new StringBuilder(GETWEIXINUSERINFO_AUTHORIZE);
        authorizeUrl.append("?appid=").append(appIdWx);
        authorizeUrl.append("&redirect_uri=").append(url);
        authorizeUrl.append("&response_type=code");
        authorizeUrl.append("&scope=snsapi_userinfo");
        authorizeUrl.append("&state=").append("STATE");
        authorizeUrl.append("#wechat_redirect");
        return authorizeUrl.toString();
    }

    /**
     * 获取微信用户的 accesstoken 和 openid
     * @param code
     * @return
     */
    public Map<String,Object> getACCESSTOKEN(String code){

        String getAccessTokenUrl = concatGetAccessTokenInfoURL(code);
        String json = postRequestForWeiXinService(getAccessTokenUrl);
        Map<String,Object> map = jsonToMap(json);

        return map;
    }
    
    /**
     * 拼接调用微信服务获取  accesstoken 和 openid URL
     * @param code
     * @return
     */
    private String concatGetAccessTokenInfoURL(String code) {
        StringBuilder getAccessTokenUrl = new StringBuilder(GETWEIXINUSERINFO_GETACCESSTOKEN);
        getAccessTokenUrl.append("?appid=").append(appIdWx);
        getAccessTokenUrl.append("&secret=").append(appSecretWx);
        getAccessTokenUrl.append("&code=").append(code);
        getAccessTokenUrl.append("&grant_type=authorization_code");
        return getAccessTokenUrl.toString();
    }

    /**
     * 获取微信用户信息
     * @param map
     * @return
     */
    public Map getWeiXinUserInfo(Map<String, Object> map) {
        String getUserInfoUrl = concatGetWeiXinUserInfoURL(map);
        String json = getRequestForWeiXinService(getUserInfoUrl);
        Map userInfoMap = jsonToMap(json);
        return userInfoMap;
    }
    
    /**
     * 拼接调用微信服务获取用户信息的URL
     * @param map
     * @return
     */
    private String concatGetWeiXinUserInfoURL(Map<String, Object> map) {
        String openId = (String) map.get("openid");
        String access_token = (String) map.get("access_token");
        // 检验授权凭证(access_token)是否有效
        StringBuilder getUserInfoUrl = new StringBuilder(GETWEIXINUSERINFO_GETUSERINFO);
        getUserInfoUrl.append("?access_token=").append(access_token);
        getUserInfoUrl.append("&openId=").append(openId);
        getUserInfoUrl.append("&lang=zh_CN");
        return getUserInfoUrl.toString();
    }

    public String mapToJson(Map map){
        Gson gson = new Gson();
        String json = gson.toJson(map);
        return json;
    }
    
    private Map jsonToMap(String json) {
        Gson gons = new Gson();
        Map map = gons.fromJson(json, new TypeToken<Map>(){}.getType());
        return map;
    }

    private String postRequestForWeiXinService(String getAccessTokenUrl) {
        ResponseEntity<String> postForEntity = restTemplate.postForEntity(getAccessTokenUrl, null, String.class);
        String json = postForEntity.getBody();
        return json;
    }

    private String getRequestForWeiXinService(String getUserInfoUrl) {
        ResponseEntity<String> postForEntity = restTemplate.getForEntity(getUserInfoUrl.toString(), String.class);
        String json = postForEntity.getBody();
        return json;
    }

}

config层


import java.time.Duration;
import java.util.concurrent.TimeUnit;
import com.aaa.project.tool.WeChatAccredit.support.CustomConnectionKeepAliveStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

@Configuration
public class RestTemplateConfig {
	@Bean
	public RestTemplate restTemplate(RestTemplateBuilder builder) {
		//return builder.build();
		return builder
				.setConnectTimeout(Duration.ofMillis(100))
				.setReadTimeout(Duration.ofMillis(500))
				.requestFactory(this::requestFactory)
				.build();
	}
	
	@Bean
	public HttpComponentsClientHttpRequestFactory requestFactory() {
		PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(30, TimeUnit.SECONDS);
		connectionManager.setMaxTotal(200);
		connectionManager.setDefaultMaxPerRoute(20);
		CloseableHttpClient httpClient = HttpClients.custom()
				.setConnectionManager(connectionManager)
				.evictIdleConnections(30, TimeUnit.SECONDS)
				.disableAutomaticRetries()
				// 有 Keep-Alive 认里面的值,没有的话永久有效
			//.setKeepAliveStrategy(DefaultConnectionKeepAliveStrategy.INSTANCE)
				// 换成自定义的
				.setKeepAliveStrategy(new CustomConnectionKeepAliveStrategy())
				.build();
		HttpComponentsClientHttpRequestFactory requestFactory =
				new HttpComponentsClientHttpRequestFactory(httpClient);
		return requestFactory;
	}
}

support层


import java.util.Arrays;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.http.HttpResponse;
import org.apache.http.conn.ConnectionKeepAliveStrategy;
import org.apache.http.protocol.HTTP;
import org.apache.http.protocol.HttpContext;

public class CustomConnectionKeepAliveStrategy implements ConnectionKeepAliveStrategy {

	 private final long DEFAULT_SECONDS = 30;

	    @Override
	    public long getKeepAliveDuration(HttpResponse response, HttpContext context) {
	        return Arrays.asList(response.getHeaders(HTTP.CONN_KEEP_ALIVE))
	                .stream()
	                .filter(h -> StringUtils.equalsIgnoreCase(h.getName(), "timeout")
	                        && StringUtils.isNumeric(h.getValue()))
	                .findFirst()
	                .map(h -> NumberUtils.toLong(h.getValue(), DEFAULT_SECONDS))
	                .orElse(DEFAULT_SECONDS) * 1000;
	    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
如果你想在Java实习中实现企业微信自建应用授权登录获取用户信息,可以按照以下步骤进行: 1. 获取应用ID和应用Secret,可以在企业微信管理后台创建自建应用时获得。 2. 配置可信域名、回调URL、授权回调域名和网页授权域名,确保域名的正确性和安全性。 3. 在Java项目中使用企业微信提供的OAuth2.0接口或者开源的Java SDK,实现授权登录功能。 4. 引导用户跳转到企业微信授权页面进行授权授权成功后,企业微信会回调预设的回调URL,返回授权码。 5. 通过授权获取access_token和用户信息,可以使用企业微信提供的OAuth2.0接口或者开源的Java SDK完成。 以下是一个使用Java SDK实现企业微信自建应用授权登录获取用户信息的示例代码: ```java // 1. 获取应用ID和应用Secret String appId = "your_app_id"; String appSecret = "your_app_secret"; // 2. 配置可信域名、回调URL、授权回调域名和网页授权域名 // 3. 使用Java SDK实现授权登录功能 WxCpService wxCpService = WxCpConfiguration.getCpService(appId); String redirectUrl = "https://your_callback_url"; String state = "your_state"; String authorizeUrl = wxCpService.getOauth2Service().buildAuthorizationUrl(redirectUrl, state); // 4. 引导用户跳转到企业微信授权页面进行授权 // 5. 企业微信回调预设的回调URL,返回授权码 String code = request.getParameter("code"); // 6. 通过授权获取access_token和用户信息 WxCpOAuth2AccessToken wxCpOAuth2AccessToken = wxCpService.getOauth2Service().getAccessToken(code); String accessToken = wxCpOAuth2AccessToken.getAccessToken(); String userId = wxCpOAuth2AccessToken.getUserId(); WxCpUser wxCpUser = wxCpService.getUserService().getById(userId); ``` 注意事项: 1. 在开发过程中,需要保证应用ID、应用Secret、回调URL等参数的正确性。 2. 在获取access_token和用户信息时,需要保证请求的准确性和安全性。 3. 在获取用户信息时,需要保证授权作用域的正确性和权限的足够性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值