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

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

微信开放平台

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

微信公众平台

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

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

官方文档链接

准备工作

网站应用微信登录是基于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=GBKif (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() {@Overridepublic boolean verify(String arg0, SSLSession arg1) {return true;}@Overridepublic void verify(String host, SSLSocket ssl)throws IOException {}@Overridepublic void verify(String host, X509Certificate cert)throws SSLException {}@Overridepublic 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 {//拼接urlStringBuilder url = new StringBuilder();url.append("https://open.weixin.qq.com/connect/qrconnect?");//appidurl.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");//这是微信回调给你的codeurl.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
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

【微信开放平台】微信第三方扫码登录(亲测可用)相关推荐

  1. 微信开放平台PC端扫码登录

    最近公司给我安排一个微信登录的功能,需求是这样的: 1.登录授权 点击二维码图标后,登录界面切换为如下样式(二维码),微信扫描二维码并授权,即可成功登录:    若当前账号未绑定微信账号,扫描后提示& ...

  2. PHP语言:微信开放平台PC端扫码登录

    需求: 微信扫码时每次需要弹窗确认效果. 微信开放平台 :创建网站应用,绑定公众号,用于打通公众号用户数据. 注意域名填写规范,不带协议.eg:www.xxx-test.com 页面嵌套扫码登录二维码 ...

  3. 微信开放平台【第三方平台】java开发总结:预授权码(pre_auth_code)(三)

    微信第三方平台预授权码(pre_auth_code)开发说明(全网最详细的微信第三方平台预授权码开发说明) 预授权码 预授权码(pre_auth_code)是第三方平台方实现授权托管的必备信息,每个预 ...

  4. 微信开放平台开发第三方授权登陆(二):PC网页端

    微信开放平台开发系列文章: 微信开放平台开发第三方授权登陆(一):开发前期准备 微信开放平台开发第三方授权登陆(二):PC网页端 微信开放平台开发第三方授权登陆(三):Android客户端 微信开放平 ...

  5. 企业微信三方开发(五):扫码登录

    其他链接 初识微信开发 企业微信三方开发:注册企业微信服务商 企业微信三方开发(一):回调验证及重要参数获取 企业微信三方开发(二):获取access_token 企业微信三方开发(三):网页授权登录 ...

  6. 微信开放平台开发第三方授权登陆(三):Android客户端

    微信开放平台开发系列文章: 微信开放平台开发第三方授权登陆(一):开发前期准备 微信开放平台开发第三方授权登陆(二):PC网页端 微信开放平台开发第三方授权登陆(三):Android客户端 微信开放平 ...

  7. 微信开放平台之第三方平台开发,模板小程序如何提交?

    大家好,我是悟空码字 12月25日,天气晴朗,阳光普照,今天是圣诞节.因为疫情影响,小羊人的增多,街上放眼望去,人烟稀少.楼下除了几个十一二岁的小男孩在玩耍,也没有像往日老人悠闲打牌.小孩嬉戏那般热闹 ...

  8. 微信开放平台【第三方平台】java开发总结:验证票据(component_verify_ticket)(-)

    微信第三方平台验证票据(component_verify_ticket)开发说明(全网最详细的微信第三方平台验证票据开发说明) 概述 微信公众平台-第三方平台(简称第三方平台)开放给所有通过开发者资质 ...

  9. 微信开放平台·微信公众号接口调用报错【“errcode“:48001“errmsg“:“api unauthorized...“】

    目录 问题描述 使用场景 解决方案 问题描述 使用场景 复现场景: 微信开放平台·微信公众号链接:微信开发平台 按照文档说明通过 code 获取 access_token 检验授权凭证(access_ ...

  10. phpstorm 2017激活码(亲测可用)

    phpstorm 2017激活码(亲测可用) 一. 二.(红框内输入:http://jetbrains.license.laucyun.com 直到看到绿色ok,重启就不会在弹出不该弹出的窗口了)

最新文章

  1. c++以空格分开的输入数组_技术贴,MATLAB矩阵与数组汇总讲解
  2. 环境/---Liunx环境安装
  3. fixed the link error 1000 in vc2008
  4. “最佳融合通信创新应用平台”认证!2021 年度全球新经济卓越成就奖揭晓
  5. 58端口使用技巧跟推送_Kindle使用技巧:定时推送
  6. 西部数码 php.ini,如何修改PHP的memory_limit限制
  7. face alignment---各种算法框架
  8. Kubernetes学习总结(6)——Kubernetes 7周年:它为什么如此受欢迎?
  9. PBR在城域网上的应用
  10. android应用开发全程实录-你有多熟悉listview? .
  11. Delphi 设计模式:《HeadFirst设计模式》Delphi7代码---工厂模式之简单工厂[转]
  12. abaqus算出来的转角单位是什么_ABAQUS统一单位方法
  13. 琴生Jensen不等式,条件期望
  14. 如何在博途精智面板及WinCC RT ADV中创建面板
  15. 安装配置fcitx输入法
  16. Windows7 密码破解
  17. bzoj4199luogu2178 noi2015品酒大会 后缀数组
  18. 5大关键,让你二十年后依然是人才
  19. 整数规划---0-1型整数规划
  20. 徐松亮常用开发软件与网站

热门文章

  1. cmd 更改计算机名
  2. 模拟量输出模块支持西门子三菱PLC接DCS控制系统
  3. JAVA大数据需要学什么
  4. 罗技M545鼠标是不是垃圾鼠标中的战斗机?
  5. mac使用hbuilderx安卓模拟器调试app
  6. 鸟哥的LINUX私房菜 基础学习篇 读书笔记 -- 第零章 计算机概论 (一)
  7. Maxent模型预测
  8. 三菱PLC FX3GA系列 FNC57 PLSY 脉冲输出
  9. 黑马JAVA知识点总结
  10. excel根据条件列转行_excel怎么批量把行变成列