15158846557 在线咨询 在线咨询
15158846557 在线咨询
所在位置: 首页 > 营销资讯 > 网站运营 > 【微信登录】网页授权与APP授权

【微信登录】网页授权与APP授权

时间:2022-08-10 15:30:01 | 来源:网站运营

时间:2022-08-10 15:30:01 来源:网站运营

前言

微信APP支付,微信授权,微信JSAPI支付,微信退款,支付宝APP支付,支付宝手机网站支付,支付宝退款。笔者都放到公众号: JAVA大贼船。微信搜一搜,方便以后开发用哦!

官方文档

网页授权

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

APP授权

https://developers.weixin.qq.com/doc/oplatform/Mobile_App/WeChat_Login/Development_Guide.html

iOS 接入指南

https://developers.weixin.qq.com/doc/oplatform/Mobile_App/Access_Guide/iOS.html

Android 接入指南

https://developers.weixin.qq.com/doc/oplatform/Mobile_App/Access_Guide/Android.html

流程步骤说明(具体说明参考官方文档,这里只描述大体)

1、引导用户进入授权页面同意授权,获取 code
2、通过 code 换取网页授权 access_token(与基础支持中的 access_token 不同)
3、如果需要,开发者可以刷新网页授权 access_token,避免过期
4、通过网页授权 access_token 和 openid 获取用户基本信息(支持 UnionID 机制)
疑问 1:scope 为 snsapi_base 和 scope 为 snsapi_userinfo 的区别?

snsapi_base 是静默授权并自动跳转到回调页的,snsapi_userinfo 是需要用户手动同意。
疑问 2:网页授权 access_token 和普通 access_token 的区别?

普通 access_token 获取用户信息时,如果用户未关注,信息获取就为空。而网页授权 access_token 的获取,只要用户许可,就可以获得,不论用户是否关注。
疑问 3:UnionID 和 openid 的区别?

unionid 对同一个微信开放平台下的不同应用(移动应用、网站应用和公众帐号)都是相同的。
而 openid 对同一个微信开放平台下的不同应用都是不相同的,如用户授权应用 A 和应用 B,那么用户的两个 openid 是不相同的,并且一个应用对应一个 openid,如用户在次授权给应用 A,openid 不变。
疑问 4:关于UnionID机制

即如果开发者有多个公众号,或在公众号、移动应用之间统一用户帐号的需求,需要前往微信开放平台(http://open.weixin.qq.com)绑定公众号后,才可利用UnionID机制来满足上述需求。

踩过的坑

解决:在公众号设置-功能设置-网页授权,配置前端存放txt文件的路径,如http://www.xxx.com/static,然后点击提交,可以事先测一下能不能访问到txt的内容。
解决:前往微信开放平台,绑定该公众号,大功告成
  1. 第三方发起微信授权登录请求,微信用户允许授权第三方应用后,微信会拉起应用或重定向到第三方网站,并且带上授权临时票据 code 参数;
  2. 通过 code 参数加上 AppID 和 AppSecret 等,通过 API 换取 access_token;
  3. 通过 access_token 进行接口调用,获取用户基本数据资源或帮助用户实现基本操作。



准备工作

代码实现(含 APP 和 H5)

application.yml

# 微信相关配置wx: #商户 ID MCH_ID: # 项目基础域名 BASEURL: #微信登录-用户同意后回调域名(前端域名) URL: # 公众号APP_ID H_APP_ID: # 公众号秘钥 H_APP_SECRET: # app的APP_ID A_APP_ID: # APP的 秘钥 A_APP_SECRET: #微信登录-微信授权基本地址 LOGIN_AUTH_BASE_URL: https://open.weixin.qq.com/connect/oauth2/authorize? #微信登录-获取ACCESS_TOKEN的URL LOGIN_ACCESS_TOKEN_URL: https://api.weixin.qq.com/sns/oauth2/access_token? #微信登录-获取登录人信息的url LOGIN_USER_INFO_URL: https://api.weixin.qq.com/sns/userinfo? #微信登录-用户同意后回调地址(前端地址) LOGIN_RETURN_URL: ${wx.URL}/static/weixinShouQuan.html #微信登录-应用授权作用域,snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid), snsapi_userinfo #(弹出授权页面,可通过openid拿到昵称、性别、所在地。并且,即使在未关注的情况下,只要用户授权,也能获取其信息 ) SCOPE: snsapi_userinfoYmlParament

/** * 获取yml参数实体 */@Component@Datapublic class YmlParament { /*微信相关字段*/ @Value("${wx.BASEURL}") private String baseurl; @Value("${wx.H_APP_ID}") private String h_app_id; @Value("${wx.A_APP_ID}") private String a_app_id; @Value("${wx.H_APP_SECRET}") private String h_app_secret; @Value("${wx.A_APP_SECRET}") private String a_app_secret; @Value("${wx.LOGIN_ACCESS_TOKEN_URL}") private String login_access_token_url; @Value("${wx.LOGIN_USER_INFO_URL}") private String login_user_info_url; @Value("${wx.LOGIN_AUTH_BASE_URL}") private String login_auth_base_url; @Value("${wx.LOGIN_RETURN_URL}") private String login_return_url; @Value("${wx.SCOPE}") private String scope;} H5 获取 code

前端通过后台拿到授权url,然后前端请求该url得到code再请求后台

WxController

@ApiOperation("获取授权url") @PostMapping("/getWeiXinLoginUrl") public R getWeiXinLoginUrl() throws Exception { String url = ymlParament.getLogin_auth_base_url() + "appid=" + ymlParament.getH_app_id()+ "&redirect_uri=" + ymlParament.getLogin_return_url()+ "&response_type=code"+ "&scope=snsapi_userinfo" + "&state=STATE#wechat_redirect"; //这里的R是自己自定义的 return R.ok().data("redirectUrl", url); }


APP 获取 code

iOS 平台应用授权登录接入代码示例(请参考 iOS 接入指南):

-(void)sendAuthRequest{ //构造SendAuthReq结构体 SendAuthReq* req =[[[SendAuthReq alloc]init]autorelease]; req.scope = @"snsapi_userinfo"; req.state = @"123"; //第三方向微信终端发送一个SendAuthReq消息结构 [WXApi sendReq:req];}Android 平台应用授权登录接入代码示例(请参考 Android 接入指南):

{ // send oauth request Final SendAuth.Req req = new SendAuth.Req(); req.scope = "snsapi_userinfo"; req.state = "wechat_sdk_demo_test"; api.sendReq(req);}


通过 code 换取网页授权 access_token,然后通过 access_token 和 openid 拉取用户信息

WxController

/*H5和app都可以调用*/ @ApiOperation("获取微信用户信息") @PostMapping(value = "/getWxUserInFo") public R getWxUserInFo(@RequestBody String body) throws Exception { String state = JacksonUtil.parseString(body, "state"); String code = JacksonUtil.parseString(body, "code"); //标志哪一个应用,用来获取对应的appid和appsecret Integer openIdType = JacksonUtil.parseInteger(body, "openIdType"); //1、获取code if(IsNull.isNull(code) || IsNull.isNull(state)) { return R.error("参数不能为空"); } //2、通过code获取accesstoken,UserWxOpenidEums是用来记录应用的,如type1是xxAPP,type2是xx服务号 JSONObject accessToken=WxUtils.getAccessTokenByCode(code, openIdType==UserWxOpenidEums.TYPE_1.getKey()?ymlParament.getA_app_id():ymlParament.getH_app_id(),openIdType==UserWxOpenidEums.TYPE_1.getKey()?ymlParament.getA_app_secret():ymlParament.getH_app_secret(),ymlParament.getLogin_access_token_url()); //3、获取用户信息 JSONObject userinfo=WxUtils.getUserinfo(openIdType==UserWxOpenidEums.TYPE_1.getKey()?ymlParament.getA_app_id():ymlParament.getH_app_id(),accessToken.getString("openid"), accessToken.getString("access_token"), ymlParament.getLogin_user_info_url()); if(!IsNull.isNull(userinfo.getString("errcode"))){ return R.error(userinfo.getString("errmsg")); } return R.ok().data("token", token).data("userinfo",userinfo);}WxUtils

/** * =============>>登录<<============= * 第二步 * 通过code获取access_token * 正确时返回的JSON数据包如下: * { "access_token":"ACCESS_TOKEN", "expires_in":7200, "refresh_token":"REFRESH_TOKEN", "openid":"OPENID", "scope":"SCOPE" } */ public static JSONObject getAccessTokenByCode(String code,String appId,String appSecret,String login_access_token_url) throws Exception { Map<String, String> map = new HashMap<String, String>(); map.put("appid",appId); map.put("secret",appSecret); map.put("code",code); map.put("grant_type","authorization_code"); return (JSONObject)JSON.parse(HttpUtil.get(login_access_token_url, map)); } /** * =============>>登录<<============= * 第三步:刷新access_token(如果需要) * 正确时返回的JSON数据包如下: * { "access_token":"ACCESS_TOKEN", "expires_in":7200, "refresh_token":"REFRESH_TOKEN", "openid":"OPENID", "scope":"SCOPE" } */ public static JSONObject refreshAccessToken(String appid,String refresh_token) throws Exception { Map<String, String> map = new HashMap<>(); map.put("appid",appid); map.put("grant_type","refresh_token"); map.put("refresh_token",refresh_token); return (JSONObject)JSON.parse(HttpUtil.get("https://api.weixin.qq.com/sns/oauth2/refresh_token?", map)); } /** * =============>>登录<<============= * 第四部,获取用户信息 * 通过code获取access_token * 正确时返回的JSON数据包如下: * { "openid":" OPENID", "nickname": NICKNAME, "sex":"1", "province":"PROVINCE", "city":"CITY", "country":"COUNTRY", "headimgurl": "http://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/46", "privilege":[ "PRIVILEGE1" "PRIVILEGE2" ], "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL" } * @throws Exception */ public static JSONObject getUserinfo(String appid,String openid,String accessToken,String login_user_info_url) throws Exception { //先判断下accessToken是否有效 HashMap<String, String> param =new HashMap<String, String>(); param.put("access_token", accessToken); param.put("openid", openid); JSONObject check=(JSONObject)JSON.parse(HttpUtil.get("https://api.weixin.qq.com/sns/auth?access_token="+accessToken+"&openid="+openid, param)); //检验授权凭证(access_token)是否有效,如果accessToken失效了,则刷新accessToken if(!check.getString("errcode").equals("0")) { accessToken=refreshAccessToken(appid, accessToken).getString("refresh_token"); } param =new HashMap<String, String>(); param.put("openid",openid); param.put("access_token",accessToken); param.put("lang","zh_CN"); return (JSONObject) JSON.parse(HttpUtil.get(login_user_info_url, param)); }HttpUtil

public static String get(String urlStr, Map<String, String> parameters) throws IOException { URL url = new URL(urlStr); HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection(); httpURLConnection.setDoInput(true); httpURLConnection.setDoOutput(true); // 设置该连接是可以输出的 httpURLConnection.setRequestMethod("GET"); // 设置请求方式 httpURLConnection.setRequestProperty("charset", "utf-8"); PrintWriter pw = new PrintWriter(new BufferedOutputStream(httpURLConnection.getOutputStream())); StringBuffer parameter = new StringBuffer(); parameter.append("1=1"); for (Entry<String, String> entry : parameters.entrySet()) { parameter.append("&" + entry.getKey() + "=" + entry.getValue()); } pw.write(parameter.toString());// 向连接中写数据(相当于发送数据给服务器) pw.flush(); pw.close(); BufferedReader br = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream(), "utf-8")); String line = null; StringBuilder sb = new StringBuilder(); while ((line = br.readLine()) != null) { // 读取数据 sb.append(line + "/n"); } br.close(); return sb.toString(); }JacksonUtil

public class JacksonUtil { public static String parseString(String body, String field) { ObjectMapper mapper = new ObjectMapper(); JsonNode node; try { node = mapper.readTree(body); JsonNode leaf = node.get(field); if (leaf != null) { return leaf.asText(); } } catch (IOException e) { e.printStackTrace(); } return null; } public static Integer parseInteger(String body, String field) { ObjectMapper mapper = new ObjectMapper(); JsonNode node; try { node = mapper.readTree(body); JsonNode leaf = node.get(field); if (leaf != null) { return leaf.asInt(); } } catch (IOException e) { e.printStackTrace(); } return null; }}



关键词:授权

74
73
25
news

版权所有© 亿企邦 1997-2025 保留一切法律许可权利。

为了最佳展示效果,本站不支持IE9及以下版本的浏览器,建议您使用谷歌Chrome浏览器。 点击下载Chrome浏览器
关闭