微信开放平台下,公众号获取到用户的unionId(非三方平台模式)
实现功能: 通过扫公众号的二维码获取到用户的unionId
实现步骤:
1.申请一个微信开放平台
步骤参考:https://jingyan.baidu.com/article/8275fc8670af2546a13cf65d.html
2.微信开放平台下:公众账号绑定公众号
绑定结果如下:
3.微信公众号下:公众号设置里面设置这个三个域名
4.微信公众号下:点开网页授权域名
需要把这个文件下载并放入域名根目录下,并确保可以访问:如下图
5.微信公众号下,设置ip白名单
点击查看出现ip白名单设置页面
二、代码层面操作
1.获取公众号的appId和appSercret,见步骤5的截图
2.获取用户授权地址
https://open.weixin.qq.com/connect/oauth2/authorize?appid=${你的公众号appId}&redirect_uri=${你的授权回调地址}&response_type=code&scope=snsapi_userinfo&state=${你的state}#wechat_redirect
注意:1.redirect_uri需要URLEncoder.encode加密,因为我没有前端页面所以我直接填的是我的后端代码的授权回调地址
2.state一般使用UUID.randomUUID().toString().replaceAll("-", "")
3. 前端将拿到的地址写入二维码
4. 用户微信扫码二维码
3.授权回调后处理
上代码
(1)常量类
// 全局常量类
public class GlobalConstants {// 公众号的appIdpublic static final String GONGZHONGHAO_APP_ID = "你的appId";// 公众号的appSecretpublic static final String GONGZHONGHAO_SECRET = "你的appSecret";// 通过code获取token地址private final String GET_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token";// 刷新token接口地址private final String REFREH_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/refresh_token";// 获取用户信息private final String GET_USER_URL = "https://api.weixin.qq.com/sns/userinfo";}
(2)主流程代码实现
public class UserWechatController {@Autowiredprivate WechatUserService wechatUserService;@RequestMapping("/$APPID$/callback")@ApiOperation(value = "公众号回调地址")public String callBack(HttpServletRequest request) throws Exception{//得到code用于交换tokenString code = request.getParameter("code");String state = request.getParameter("state");log.info("用户授权回调,code---->"+code+",state---->"+state);//判断state是否合法if (StringUtils.isBlank(code) || StringUtils.isBlank(state)) {throw new BusinessException("code获取失败,请重新登录");}//用户授权后的code换取tokenMap<Object, Object> token = wechatUserService.getAccessToken(code, GlobalConstants.GONGZHONGHAO_APP_ID, GlobalConstants.GONGZHONGHAO_SECRET);log.info("用户授权回调,token------------------>"+token);//判断是否成功获取到了tokenif (token.get("errcode") != null) {throw new Exception("token获取失败,请重新登录");}if (token.get("access_token") == null || token.get("openid") == null) {throw new Exception("access_token拉取失败,请重新登录");}if (token.get("refresh_token") != null && token.get("openid") != null) {String openId = token.get("openid").toString();String refreshToken = token.get("refresh_token").toString();//刷新accesstokenMap userInfo = wechatUserService.refrehToken(GlobalConstants.GONGZHONGHAO_APP_ID, refreshToken);log.info("用户授权回调,token------------------>"+userInfo);//使用token交换获取用户信息WxchatUserReceiveReponse user = wechatUserService.getUserInfo(userInfo);// TODO 用户信息已经获取,后续流程自行处理} return "SUCCESS";}}
(3)Service类
public interface WechatUserService{/**getAccessToken*/Map getAccessToken(String code, String appId, String secret);/*** 刷新token处理* @return*/Map refrehToken(String appId, String refreshToken);/*** 通过token获取用户信息* @return*/WxchatUserReceiveReponse getUserInfo(Map token);
}
(4)ServiceImpl实现类 注:本来这个类也应该作为一个工具类,不要学我,用这个不规范写法
@Service
@Slf4j
public class WechatUserServiceImpl implements WechatUserService {/*** 通过code获取token* @return*/@Overridepublic Map getAccessToken(String code, String appid, String secret){//构建请求数据Map<String, String> t = new HashMap<String, String>();t.put("appid", appid);t.put("secret", secret);t.put("code", code);t.put("grant_type", "authorization_code");//调用httpclient处理请求得到返回json数据String returnJson = HttpClientUtil.get(GlobalConstants.GET_TOKEN_URL, t);Map token = (Map) JSONObject.parse(returnJson);return token;}/*** 刷新token处理* @return*/@Overridepublic Map refrehToken(String appid, String refresh_token){//构建请求参数Map<String, String> m = new HashMap<String, String>();m.put("appid", appid);m.put("grant_type", "refresh_token");m.put("refresh_token", refresh_token);//调用httpclient发出请求String resultJson = HttpClientUtil.get(GlobalConstants.REFREH_TOKEN_URL, m);Map refreshToken = (Map)JSONObject.parse(resultJson);return refreshToken;}/*** 通过token获取用户信息* @param token* @return*/public WxchatUserReceiveReponse getUserInfo(Map token){//构建请求数据Map u = new HashMap();u.put("access_token",token.get("access_token"));u.put("openid",token.get("openid"));u.put("lang","zh_CN");//调用httpclient处理请求得到用户信息json数据String userJson = HttpClientUtil.get(GlobalConstants.GET_USER_URL, u);log.info("用户授权回调,userJson------------------>"+userJson);//转换成用户对象WxchatUserReceiveReponse wxchatUser = JSONObject.parseObject(userJson, WxchatUserReceiveReponse.class);log.info("用户授权回调,token------------------>"+wxchatUser);return wxchatUser;}}
(5) http工具类
package com.rhpass.cloud.basic.message.wechat;import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;import javax.net.ssl.SSLException;
import javax.net.ssl.SSLHandshakeException;import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.NoHttpResponseException;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.ConnectionKeepAliveStrategy;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.google.common.collect.Lists;public class HttpClientUtil {/** 默认连接超时时间毫秒 */public static int SO_TIME_OUT = 20000;/** 默认响应超时时间毫秒 */public static int CONNECTION_TIME_OUT = 20000;/*** 连接存活时间 默认60s*/private static final int CONNECTION_KEEP_ALIVE = 20 * 1000;private static CloseableHttpClient http = null;static {ConnectionSocketFactory plainsf = PlainConnectionSocketFactory.getSocketFactory();LayeredConnectionSocketFactory sslsf = SSLConnectionSocketFactory.getSocketFactory();Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory> create().register("http", plainsf).register("https", sslsf).build();PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry);// 将最大连接数增加cm.setMaxTotal(500);// 将每个路由基础的连接增加cm.setDefaultMaxPerRoute(50);// 请求重试处理HttpRequestRetryHandler httpRequestRetryHandler = new HttpRequestRetryHandler() {public boolean retryRequest(IOException exception, int executionCount, HttpContext context) {if (executionCount >= 3) {// 如果已经重试了3次,就放弃return false;}if (exception instanceof NoHttpResponseException) {// 如果服务器丢掉了连接,那么就重试return true;}if (exception instanceof SSLHandshakeException) {// 不要重试SSL握手异常return false;}if (exception instanceof InterruptedIOException) {// 超时return false;}if (exception instanceof UnknownHostException) {// 目标服务器不可达return false;}if (exception instanceof ConnectTimeoutException) {// 连接被拒绝return false;}if (exception instanceof SSLException) {// SSL握手异常return false;}HttpClientContext clientContext = HttpClientContext.adapt(context);HttpRequest request = clientContext.getRequest();// 如果请求是幂等的,就再次尝试if (!(request instanceof HttpEntityEnclosingRequest)) { return true; }return false;}};// 添加保持活性策略ConnectionKeepAliveStrategy keepAliveStrategy = new DefaultConnectionKeepAliveStrategy() {@Overridepublic long getKeepAliveDuration(final HttpResponse response, final HttpContext context) {long keepAlive = super.getKeepAliveDuration(response, context);if (keepAlive == -1) {keepAlive = CONNECTION_KEEP_ALIVE;}return keepAlive;}};http = HttpClients.custom().setConnectionManager(cm).setRetryHandler(httpRequestRetryHandler)// 定期清理连接池里的无效连接.evictExpiredConnections().setKeepAliveStrategy(keepAliveStrategy).setConnectionTimeToLive(CONNECTION_KEEP_ALIVE, TimeUnit.MILLISECONDS).build();}/*** 给定的URL连接POST数据,延时是固定的** @param urlvalue* @param param* @return*/public static String get(String urlvalue,Map<String, String> param) {return get(urlvalue, param, SO_TIME_OUT, CONNECTION_TIME_OUT);}/*** 给定的URL连接POST数据,延时是固定的** @param urlvalue* @param param* @return*/public static String get(String urlvalue, Map<String, String> param, int timeCout) {return get(urlvalue, param, timeCout, CONNECTION_TIME_OUT);}/*** 连接POST数据,延时可指定** @param urlvalue* @param param* @param socketTimeout* @param connectTimeout* @return* @throws IOException*/public static String get(String urlvalue, Map<String, String> param, int socketTimeout, int connectTimeout) {return getConnect(urlvalue, param, socketTimeout, connectTimeout);}private static String getConnect(String urlvalue, Map<String, String> param, int socketTimeout, int connectTimeout) {try {//创建URLBuilderURIBuilder uriBuilder=new URIBuilder(urlvalue);//设置参数if(param != null){param.forEach((key, value) ->{uriBuilder.setParameter(key,value);});}//2.创建HttpGet对象,设置URL地址HttpGet httpGet=new HttpGet(uriBuilder.build());RequestConfig config = RequestConfig.custom().setConnectTimeout(connectTimeout).setSocketTimeout(socketTimeout).build();httpGet.setConfig(config);CloseableHttpResponse response = http.execute(httpGet);return EntityUtils.toString(response.getEntity(), "utf-8");} catch (Exception e) {}return "";}}
(6)参数接收类
package com.rhpass.cloud.basic.wechat.dto.reponse;import java.io.Serializable;import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;@Data
@ApiModel(value="WxchatUserReceiveReponse对象", description="微信用户信息")
public class WxchatUserReceiveReponse implements Serializable{private static final long serialVersionUID = 1L;@ApiModelProperty(value = "openid")private String openid;@ApiModelProperty(value = "userId")private Integer userId;@ApiModelProperty(value = "昵称")private String nickname;@ApiModelProperty(value = "性别")private String sex;@ApiModelProperty(value = "省")private String province;@ApiModelProperty(value = "市")private String city;@ApiModelProperty(value = "头像")private String headimgurl;@ApiModelProperty(value = "用户特权信息,json 数组,如微信沃卡用户为(chinaunicom)")private String privilege;@ApiModelProperty(value = "unionid")private String unionid;}
至此,本文的配置和代码实现结束。
如有错误,清帮忙纠正。
微信开放平台下,公众号获取到用户的unionId(非三方平台模式)相关推荐
- 关于开发微信公众号获取手机用户运动数据的功能实现思路
一.前沿研究 微信公众号开发文档,浏览后没有任何关于获取微信运动数据的接口 https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp144 ...
- python获取微信用户基本信息_微信开放平台扫码登录获取用户基本信息!附可用demo...
微信开放平台提供了网站扫码登录的接口,用于获取用户基本信息(头像,昵称)方便网站快速接入微信登录,快捷登录.需要使用登录接口,需要成为微信开放平台认证开发者(300元)才可以获得这个接口权限. 准备工 ...
- tp5微信公众号获取用户openid_tp5+微信公众号获取用户基本信息
获取用户基本信息(UnionID机制) 获取用户基本信息(UnionID机制) 在关注者与公众号产生消息交互后,公众号可获得关注者的OpenID(加密后的微信号,每个用户对每个公众号的OpenID是唯 ...
- vue 微信公众号获取定位经纬度 腾讯地图逆地址解析为具体地址
最近做项目需要用到 微信公众号获取定位,并将定位转换为具体地址的需求,找了挺多,最后整理下,分享给大家~ 我这里使用的是腾讯地图,也可以使用其他的如百度.高德等. 思路是,先使用微信开放文档的获取定位 ...
- 微信公众号获取用户头像
一.首先来认识一下所有ID appid 微信公众号唯一ID appsecret 公众号分配唯一表示 access_token 公众号的全局唯一接口调用凭据 使用grant_type(client_cr ...
- 【微信】未关注公众号授权获取基本信息(头像昵称等)
引导用户点击设计好的链接,形如: https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx9a3d0c9c3170978c&re ...
- php微信静默授权获取头像,【微信】未关注公众号授权获取基本信息(头像昵称等)...
引导用户点击设计好的链接,形如: appid:为开发者微信公众号的appid. redirect_uri:微信验证成功后跳转到的重定向链接.编码后的地址. response_type:code sco ...
- java根据手机号获取微信信息_Java实现的微信公众号获取微信用户信息示例
本文实例讲述了Java实现的微信公众号获取微信用户信息.分享给大家供大家参考,具体如下: 注: 这里获取用户信息方式和网页授权获取用户信息方式不同.两个access_token不同,返回的结果也不同. ...
- 微信H5公众号获取openid爬坑记
前要: 之前做过的公众号授权一般是在登录时的,最近遇到一个直接微信打开企业微信发过来的链接进去预约页面,需要进来时查询当前微信的用户有没有预约过对应的申请,如果有就跳转到index的列表页,没有的话留 ...
最新文章
- 调用其他脚本上方法的方法
- [ZJOI2011]礼物
- StackToQueue
- Spark SQL JOIN操作代码示例
- Spring框架的事务管理的基本概念
- 文字投影_店铺门口投影灯,引领店铺新潮流
- 【每日SQL打卡】​​​​​​​​​​​DAY 2 丨组合两个表【难度简单】
- 一起学习C语言:函数(三)
- 智慧城市php源码,智慧城市本地O2O系统NIUCMS商业版V3.4完整源码
- 安装cocoaPod 的问题
- 华为服务器扩容内存进不去系统,服务器换内存系统出问题吗
- MFC架构下的DirectX8
- java中utf8转成gbk,java中GBK转UTF-8乱码的解决方法
- SDIO接口(4)——SDIO通信
- 网站服务器需不需要装杀毒软件,服务器要不要装杀毒软件
- oracle移动文件命令是什么意思,Oracle使用命令移动各类文件的方法
- 从软件工程师到IT猎头:我的一点经历和感触
- 【算法】红黑树插入数据(变色,左旋、右旋)(二)
- 拼多多商品APi、商品详情、产品页面信息接口
- 腾讯搜搜soso升级之路