【微信开放平台】微信第三方扫码登录(亲测可用)「建议收藏」

【微信开放平台】微信第三方扫码登录(亲测可用)「建议收藏」开放平台需要企业认证才能注册,正好这次公司提供了一个账号,调通以后,就顺便写一篇博客吧。公众平台与开放平台的区别微信开放平台主要面对移动应用/网站应用开发者,为其提供微信登录、分享、支付等相关权限和服务。微信公众平台微信公众平台用于管理、开放微信公众号(包括订阅号、服务号、企业号),简单的说就是微信公众号的后台运营、管理系统。这里想吐槽一下,微信基本注册全都要邮箱,公众号一…

大家好,又见面了,我是你们的朋友全栈君。

开放平台需要企业认证才能注册,正好这次公司提供了一个账号,调通以后,就顺便写一篇博客吧。

公众平台与开放平台的区别

微信开放平台

主要面对移动应用/网站应用开发者,为其提供微信登录、分享、支付等相关权限和服务。

微信公众平台

微信公众平台用于管理、开放微信公众号(包括订阅号、服务号、企业号),简单的说就是微信公众号的后台运营、管理系统。

这里想吐槽一下,微信基本注册全都要邮箱,公众号一个、小程序一个、开放平台一个、我哪他妈有这么多邮箱啊,又记不住密码,下面正题。

官方文档链接

准备工作

网站应用微信登录是基于OAuth2.0协议标准构建的微信OAuth2.0授权登录系统。
在进行微信OAuth2.在进行微信OAuth2.0授权登录接入之前,在微信开放平台注册开发者帐号,并拥有一个已审核通过的网站应用,并获得相应的AppID和AppSecret,申请微信登录且通过审核后,可开始接入流程。

【微信开放平台】微信第三方扫码登录(亲测可用)「建议收藏」

image.png

点击创建网站应用

【微信开放平台】微信第三方扫码登录(亲测可用)「建议收藏」

image.png

按照要求填写信息,等待审核通过就可以获取appid和appsecret

【微信开放平台】微信第三方扫码登录(亲测可用)「建议收藏」

image.png

然后找到回调授权域名这一项 修改成要回调的域名,例如:www.baidu.com 不要加http://或https://

【微信开放平台】微信第三方扫码登录(亲测可用)「建议收藏」

image.png

 

好了需要提前准备的东西就完事了,下面就是代码部分了。

 

【微信开放平台】微信第三方扫码登录(亲测可用)「建议收藏」

image.png

 

这是完整的调用图
我这里用的spring boot项目进行测试的,但是代码都大致相同

 

【微信开放平台】微信第三方扫码登录(亲测可用)「建议收藏」

image.png

第一步:请求CODE

这是自己用到的HttpClientUtils工具类

package com.lj.demo.controller.util;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.impl.client.HttpClients;
import java.net.SocketTimeoutException;
import java.security.GeneralSecurityException;
import java.io.IOException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import org.apache.commons.io.IOUtils;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.config.RequestConfig.Builder;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.conn.ssl.X509HostnameVerifier;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
/**
* @author LvJun
* @create 2018-03-16 17:51
**/
public class HttpClientUtils {
public static final int connTimeout=10000;
public static final int readTimeout=10000;
public static final String charset="UTF-8";
private static HttpClient client = null;
static {
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
cm.setMaxTotal(128);
cm.setDefaultMaxPerRoute(128);
client = HttpClients.custom().setConnectionManager(cm).build();
}
public static String postParameters(String url, String parameterStr) throws ConnectTimeoutException, SocketTimeoutException, Exception{
return post(url,parameterStr,"application/x-www-form-urlencoded",charset,connTimeout,readTimeout);
}
public static String postParameters(String url, String parameterStr,String charset, Integer connTimeout, Integer readTimeout) throws ConnectTimeoutException, SocketTimeoutException, Exception{
return post(url,parameterStr,"application/x-www-form-urlencoded",charset,connTimeout,readTimeout);
}
public static String postParameters(String url, Map<String, String> params) throws ConnectTimeoutException,
SocketTimeoutException, Exception {
return postForm(url, params, null, connTimeout, readTimeout);
}
public static String postParameters(String url, Map<String, String> params, Integer connTimeout,Integer readTimeout) throws ConnectTimeoutException,
SocketTimeoutException, Exception {
return postForm(url, params, null, connTimeout, readTimeout);
}
public static String get(String url) throws Exception {
return get(url, charset, null, null);
}
public static String get(String url, String charset) throws Exception {
return get(url, charset, connTimeout, readTimeout);
}
/**
* 发送一个 Post 请求, 使用指定的字符集编码.
*
* @param url
* @param body RequestBody
* @param mimeType 例如 application/xml "application/x-www-form-urlencoded" a=1&b=2&c=3
* @param charset 编码
* @param connTimeout 建立链接超时时间,毫秒.
* @param readTimeout 响应超时时间,毫秒.
* @return ResponseBody, 使用指定的字符集编码.
* @throws ConnectTimeoutException 建立链接超时异常
* @throws SocketTimeoutException  响应超时
* @throws Exception
*/
public static String post(String url, String body, String mimeType,String charset, Integer connTimeout, Integer readTimeout)
throws ConnectTimeoutException, SocketTimeoutException, Exception {
HttpClient client = null;
HttpPost post = new HttpPost(url);
String result = "";
try {
if (StringUtils.isNotBlank(body)) {
HttpEntity entity = new StringEntity(body, ContentType.create(mimeType, charset));
post.setEntity(entity);
}
// 设置参数
Builder customReqConf = RequestConfig.custom();
if (connTimeout != null) {
customReqConf.setConnectTimeout(connTimeout);
}
if (readTimeout != null) {
customReqConf.setSocketTimeout(readTimeout);
}
post.setConfig(customReqConf.build());
HttpResponse res;
if (url.startsWith("https")) {
// 执行 Https 请求.
client = createSSLInsecureClient();
res = client.execute(post);
} else {
// 执行 Http 请求.
client = HttpClientUtils.client;
res = client.execute(post);
}
result = IOUtils.toString(res.getEntity().getContent(), charset);
} finally {
post.releaseConnection();
if (url.startsWith("https") && client != null&& client instanceof CloseableHttpClient) {
((CloseableHttpClient) client).close();
}
}
return result;
}
/**
* 提交form表单
*
* @param url
* @param params
* @param connTimeout
* @param readTimeout
* @return
* @throws ConnectTimeoutException
* @throws SocketTimeoutException
* @throws Exception
*/
public static String postForm(String url, Map<String, String> params, Map<String, String> headers, Integer connTimeout,Integer readTimeout) throws ConnectTimeoutException,
SocketTimeoutException, Exception {
HttpClient client = null;
HttpPost post = new HttpPost(url);
try {
if (params != null && !params.isEmpty()) {
List<NameValuePair> formParams = new ArrayList<org.apache.http.NameValuePair>();
Set<Entry<String, String>> entrySet = params.entrySet();
for (Entry<String, String> entry : entrySet) {
formParams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
}
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formParams, Consts.UTF_8);
post.setEntity(entity);
}
if (headers != null && !headers.isEmpty()) {
for (Entry<String, String> entry : headers.entrySet()) {
post.addHeader(entry.getKey(), entry.getValue());
}
}
// 设置参数
Builder customReqConf = RequestConfig.custom();
if (connTimeout != null) {
customReqConf.setConnectTimeout(connTimeout);
}
if (readTimeout != null) {
customReqConf.setSocketTimeout(readTimeout);
}
post.setConfig(customReqConf.build());
HttpResponse res = null;
if (url.startsWith("https")) {
// 执行 Https 请求.
client = createSSLInsecureClient();
res = client.execute(post);
} else {
// 执行 Http 请求.
client = HttpClientUtils.client;
res = client.execute(post);
}
return IOUtils.toString(res.getEntity().getContent(), "UTF-8");
} finally {
post.releaseConnection();
if (url.startsWith("https") && client != null
&& client instanceof CloseableHttpClient) {
((CloseableHttpClient) client).close();
}
}
}
/**
* 发送一个 GET 请求
*
* @param url
* @param charset
* @param connTimeout  建立链接超时时间,毫秒.
* @param readTimeout  响应超时时间,毫秒.
* @return
* @throws ConnectTimeoutException   建立链接超时
* @throws SocketTimeoutException   响应超时
* @throws Exception
*/
public static String get(String url, String charset, Integer connTimeout,Integer readTimeout)
throws ConnectTimeoutException,SocketTimeoutException, Exception {
HttpClient client = null;
HttpGet get = new HttpGet(url);
String result = "";
try {
// 设置参数
Builder customReqConf = RequestConfig.custom();
if (connTimeout != null) {
customReqConf.setConnectTimeout(connTimeout);
}
if (readTimeout != null) {
customReqConf.setSocketTimeout(readTimeout);
}
get.setConfig(customReqConf.build());
HttpResponse res = null;
if (url.startsWith("https")) {
// 执行 Https 请求.
client = createSSLInsecureClient();
res = client.execute(get);
} else {
// 执行 Http 请求.
client = HttpClientUtils.client;
res = client.execute(get);
}
result = IOUtils.toString(res.getEntity().getContent(), charset);
} finally {
get.releaseConnection();
if (url.startsWith("https") && client != null && client instanceof CloseableHttpClient) {
((CloseableHttpClient) client).close();
}
}
return result;
}
/**
* 从 response 里获取 charset
*
* @param ressponse
* @return
*/
@SuppressWarnings("unused")
private static String getCharsetFromResponse(HttpResponse ressponse) {
// Content-Type:text/html; charset=GBK
if (ressponse.getEntity() != null  && ressponse.getEntity().getContentType() != null && ressponse.getEntity().getContentType().getValue() != null) {
String contentType = ressponse.getEntity().getContentType().getValue();
if (contentType.contains("charset=")) {
return contentType.substring(contentType.indexOf("charset=") + 8);
}
}
return null;
}
/**
* 创建 SSL连接
* @return
* @throws GeneralSecurityException
*/
private static CloseableHttpClient createSSLInsecureClient() throws GeneralSecurityException {
try {
SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
public boolean isTrusted(X509Certificate[] chain,String authType) throws CertificateException {
return true;
}
}).build();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, new X509HostnameVerifier() {
@Override
public boolean verify(String arg0, SSLSession arg1) {
return true;
}
@Override
public void verify(String host, SSLSocket ssl)
throws IOException {
}
@Override
public void verify(String host, X509Certificate cert)
throws SSLException {
}
@Override
public void verify(String host, String[] cns,
String[] subjectAlts) throws SSLException {
}
});
return HttpClients.custom().setSSLSocketFactory(sslsf).build();
} catch (GeneralSecurityException e) {
throw e;
}
}
}

微信有两种方式认证一种是调转到微信域名下,还一种是直接把二维码嵌套到自己网站中。

这里是跳转到微信的认证方式

首先在页面做一个简单的按钮 触发事件获取认证code

 <button onclick="login()">微信登录</button>

js调用部分

<script>
function login() {
$.ajax({
type: "POST",
//这个路径根据自己的情况填写
url: "/demo-wechat/wechat/getCode",
success: function (data) {
console.log(data);
if (data.code == 200) {
window.location.href = (data.result);
} else {
alert("认证失败");
}
},
error: function (data) {
alert("认证失败");
}
});
}
</script>

后台代码url参数都要根据自己的实际情况进行修改

    @RequestMapping("/getCode")
public void getCode() throws Exception {
//拼接url
StringBuilder url = new StringBuilder();
url.append("https://open.weixin.qq.com/connect/qrconnect?");
//appid
url.append("appid=" + "appid");
//回调地址 ,回调地址要进行Encode转码 
String redirect_uri = "回调地址"
//转码
url.append("&redirect_uri=" + URLEncodeUtil.getURLEncoderString(redirect_uri));
url.append("&response_type=code");
url.append("&scope=snsapi_login");
HttpClientUtils.get(url.toString(), "GBK");
}
参数 是否必填 说明
appid 应用唯一标识
redirect_uri 请使用urlEncode对链接进行处理
response_type 填code
scope 网页应用目前仅填写snsapi_login即可
state 安全性相关具体可以参考官方文档这里可以不填

参数说明

redirect_uri 这个参数是用户扫码确认以后微信调用自己的路径例如:https://www.baidu.com/wechat/callback
拼完路径可以打印出来看一下 完整的路径应该是这样
https://open.weixin.qq.com/connect/qrconnect?appid=wxbdc5610cc59c1631&redirect_uri=https%3A%2F%2Fpassport.yhd.com%2Fwechat%2Fcallback.do&response_type=code&scope=snsapi_login&state=3d6be0a4035d839573b04816624a415e#wechat_redirect
到此获取code就完成了,用户确认以后回调自己的时候会带两个参数,
1.code
2.state
如果调用没有传递state就不会返回state 用户拒绝了登录请求,返回的结果不会有code

第二步:通过code获取access_token

接下来完成回调的方法直接上代码

/**
* 微信回调
*/
@RequestMapping("/callback")
public ModelAndView callback(String code,String state) throws Exception {
System.out.println("===="+code+"==="+state+"====");
if(StringUtils.isNotEmpty(code)){
StringBuilder url = new StringBuilder();
url.append("https://api.weixin.qq.com/sns/oauth2/access_token?");
url.append("appid=" + "appid");
url.append("&secret=" + "secret");
//这是微信回调给你的code
url.append("&code=" + code);
url.append("&grant_type=authorization_code");
String result = HttpClientUtils.get(url.toString(), "UTF-8");
System.out.println("result:" + result.toString());
}
return new ModelAndView("login");
}

返回说明

正确的返回:
{

“access_token”:”ACCESS_TOKEN”,
“expires_in”:7200,
“refresh_token”:”REFRESH_TOKEN”,
“openid”:”OPENID”,
“scope”:”SCOPE”,
“unionid”: “o6_bmasdasdsad6_2sgVt7hMZOPfL”
}
错误返回样例:

{“errcode”:40029,”errmsg”:”invalid code”}

这个时候我们拿到用了用户的一些必要的信息,剩下的就根据自己具体的业务进行后面的操作吧。

这里是第二种 认证方式,把二维码嵌套到自己的网站

这里只需要改前台代码
创建一个放二维码的容器

<div id="login_container" style="width: 500px;height: 500px;"></div>

导入微信的JS

//我这种写法是spring boot对应的 根据自己前端框架导入
<script th:src="@{http://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js}"></script>

在JS里面实例这么一段代码

var obj = new WxLogin({
id:"login_container",
appid: "appid",
scope: "snsapi_login",
redirect_uri: "回调地址",
state: "",
style: "",//这个是二维码样式
href: ""
});

这样打开这个页面就会自动加载微信二维码。扫码认证后 后面流程不变,返回的也是code,根据code获取token。

这只是一个最简单入门的Demo,代码也有很多需要优化的地方,欢迎大家指正说明,最后感谢大家观看。

作者:路西法Lucifer丶
链接:https://www.jianshu.com/p/89c43290d7f6
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/135736.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • datagrip激活码_最新在线免费激活[通俗易懂]

    (datagrip激活码)JetBrains旗下有多款编译器工具(如:IntelliJ、WebStorm、PyCharm等)在各编程领域几乎都占据了垄断地位。建立在开源IntelliJ平台之上,过去15年以来,JetBrains一直在不断发展和完善这个平台。这个平台可以针对您的开发工作流进行微调并且能够提供…

  • 浏览器dns缓存清理_怎么清除ip地址缓存

    浏览器dns缓存清理_怎么清除ip地址缓存有dns的地方,就有缓存。浏览器、操作系统、LocalDNS、根域名服务器,它们都会对DNS结果做一定程度的缓存。本文总结一些常见的浏览器和操作系统的DNS缓存时间浏览器先查询自己的缓存,查不到,

  • 100套大数据可视化炫酷大屏Html5模板

    100套大数据可视化炫酷大屏Html5模板100套大数据可视化炫酷大屏Html5模板;包含行业:社区、物业、政务、交通、金融银行等,全网最新、最多,最全、最酷、最炫大数据可视化模板。源码地址 giteehttps://gitee.com/iGaoWei/big-data-view githubhttps://github.com/iGaoWei/BigDataView 使用说明 直接下载,使用浏览器访问静态页面即可。 git拉取代码$gitclonehttps://gitee….

  • IT十大名言 |IT历史上被引述最多的10句名人名言

    IT十大名言 |IT历史上被引述最多的10句名人名言IT十大名言|IT历史上被引述最多的10句名人名言1)1899″Everythingthatcanbeinventedhasalreadybeeninvented.”—–CharlesH.Duell,directoroftheU.S.PatentOffice2)1943″Ithinkthereisaworldmarketformay

    2022年10月21日
  • 抖音推荐算法总结[通俗易懂]

    抖音推荐算法究竟如何是做抖音短视频运营的同学非常关心的问题,抖音官方并没有披露正式的算法,但凭借着民间的智慧和官方披露的部分信息中,网友已经总结出抖音推荐算法的秘密。这里整理资料如下:1.发布后的推荐流程第0步:双重审核在抖音,每天有数量庞大的新作品上传,纯靠机器审核容易被钻空子,纯靠人工审核又不太现实。因此,双重审核成为抖音算法筛选视频内容的第一道门槛。机器审核(检测是否违…

  • 【hive】hive查询报错INFO: os::commit_memory(0x00000006e9990000, 3597074432, 0) failed; error=‘Cannot alloc

    【hive】hive查询报错INFO: os::commit_memory(0x00000006e9990000, 3597074432, 0) failed; error=‘Cannot alloc报错内容:INFO:Startingtask[Stage-14:MAPREDLOCAL]inserialmodeJavaHotSpot(TM)64-BitServerVMwarning:ignoringoptionMaxPermSize=512M;supportwasremovedin8.0JavaHotSpot(TM)64-BitServerVMwarning:INFO:os::commit_memory(0x00000006e9990000,

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号