PC 微信扫码登陆

目录
1、注册微信开发平台
2、微信开发平台添加网站应用
3、PC微信登录流程介绍
4、获取用户基本信息(UnionID机制)

1、注册微信开发平台

官网网址 自行注册,需要注意的是注册邮箱号不用与腾讯其他产品同号。

2、微信开发平台添加网站应用
添加网站应用
填写基本信息
填写基本信息2
网站信息登记表模板
网站应用名称不能重复
添加授权回调域-可以修改

以上资料提交之后等待TX审核,审核时间大概2天左右,审核通过之后就可以查看AppID AppSecret以及申请微信登录
注意:如果注册完的开放平台之后有进行开发者认证时,审核通过之后微信登录默认是开通的,如果没有进行开发者认证点击申请开通 时会提醒进行开发者认证(如下图)

审核通过
基本信息、开发信息
提醒进行开发者认证
开发者资质认证
3、PC微信登录流程介绍

网站应用微信登录是基于OAuth2.0协议标准构建的微信OAuth2.0授权登录系统。进一步了解OAuth2.0-----理解OAuth2.0 官方介绍资料

大致的步骤如下:

  1. 第三方发起微信授权登录请求,微信用户允许授权第三方应用后,微信会拉起应用或重定向到第三方网站,并且带上授权临时票据code参数;
  2. 通过code参数加上AppID和AppSecret等,通过API换取access_token;
  3. 通过access_token进行接口调用,获取用户基本数据资源或帮助用户实现基本操作。
获取access_token时序图
获取access_token时序图

具体的步骤如下:

第一步:请求CODE

接口说明
https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
参数说明

参数 是否必须 说明
appid 应用唯一标识
redirect_uri 重定向地址,需要进行UrlEncode
response_type 填code
scope 应用授权作用域,拥有多个作用域用逗号(,)分隔,网页应用目前仅填写snsapi_login即可
state 用于保持请求和回调的状态,授权请求后原样带回给第三方。该参数可用于防止csrf攻击(跨站请求伪造攻击),建议第三方带上该参数,可设置为简单的随机数加session进行校验

若提示“该链接无法访问”,请检查参数是否填写错误,如redirect_uri的域名与审核时填写的授权域名不一致或scope不为snsapi_login。

返回说明
用户允许授权后,将会重定向到redirect_uri的网址上,并且带上code和state参数


redirect_uri?code=CODE&state=STATE


若用户禁止授权,则重定向后不会带上code参数,仅会带上state参数


redirect_uri?state=STATE


接口封装


    private static String qrconnect_url = "https://open.weixin.qq.com/connect/qrconnect";

 
    /**
     * 生成网页二维码授权链接
     * @param appId 应用id
     * @param redirect_uri 回跳地址
     * @return url
     */
    public static String getQrConnectURL(String appId, String redirect_uri) {
        return getQrConnectURL(appId, redirect_uri, null);
    }
    
    /**
     * 生成网页二维码授权链接
     * @param appId 应用id
     * @param redirect_uri 回跳地址
     * @param state 重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值,最多128字节
     * @return url
     */
    public static String getQrConnectURL(String appId, String redirect_uri, String state) {
        Map<String, String> params = new HashMap<String, String>();
        params.put("appid", appId);
        params.put("response_type", "code");
        params.put("redirect_uri", redirect_uri);
        params.put("scope", "snsapi_login");
        if (StrKit.isBlank(state)) {
            params.put("state", "wx#wechat_redirect");
        } else {
            params.put("state", state.concat("#wechat_redirect"));
        }
        String para = PaymentKit.packageSign(params, false);
        return qrconnect_url + "?" + para;
    }

接口测试

1、设置AppId、APPSecret以及回调域名
2、PC访问测试。开源项目中访问地址为:

http://域名/[项目名称]/toWebOauth
设置AppId、APPSecret以及回调域名

//pc扫描登陆
public void toWebOauth(){
    String calbackUrl=PropKit.get("domain")+"/oauth/webCallBack";
    String url=SnsAccessTokenApi.getQrConnectURL(PropKit.get("webAppId"), calbackUrl,"666");
    redirect(url);
}

如果授权回调域名与开发平台中的填写不一致将会出现以下提示

回调域名与接口调用时填写的域名不一致
第二步:通过code获取access_token
第三步:通过access_token调用接口获取用户信息

第二步、第三步过程与微信公众号授权登录一样可以参考之前写的一篇文章授权获取用户信息

授权后接口调用(UnionID)

获取用户个人信息(UnionID机制)

此接口用于获取用户个人信息。开发者可通过OpenID来获取用户基本信息。特别需要注意的是,如果开发者拥有多个移动应用、网站应用和公众帐号,可通过获取用户基本信息中的unionid来区分用户的唯一性,因为只要是同一个微信开放平台帐号下的移动应用、网站应用和公众帐号,用户的unionid是唯一的。换句话说,同一用户,对同一个微信开放平台下的不同应用,unionid是相同的。请注意,在用户修改微信头像后,旧的微信头像URL将会失效,因此开发者应该自己在获取用户信息后,将头像图片保存下来,避免微信头像URL失效后的异常情况。

官方介绍文档

接口封装可以参考开源项目中

网页授权(公众号、PC)获取用户信息

import com.jfinal.kit.StrKit;
import com.jfinal.weixin.sdk.kit.ParaMap;
import com.jfinal.weixin.sdk.kit.PaymentKit;
import com.jfinal.weixin.sdk.utils.HttpUtils;
import com.jfinal.weixin.sdk.utils.RetryUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;


public class SnsAccessTokenApi
{
    private static String url = "https://api.weixin.qq.com/sns/oauth2/access_token?grant_type=authorization_code";
    private static String authorize_uri = "https://open.weixin.qq.com/connect/oauth2/authorize";
    private static String qrconnect_url = "https://open.weixin.qq.com/connect/qrconnect";
    
    /**
     * 生成Authorize链接
     * @param appId 应用id
     * @param redirect_uri 回跳地址
     * @param snsapiBase snsapi_base(不弹出授权页面,只能拿到用户openid)snsapi_userinfo(弹出授权页面,这个可以通过 openid 拿到昵称、性别、所在地)
     * @return url
     */
    public static String getAuthorizeURL(String appId, String redirect_uri, boolean snsapiBase) {
        return getAuthorizeURL(appId, redirect_uri, null, snsapiBase);
    }
    
    /**
     * 生成Authorize链接
     * @param appId 应用id
     * @param redirectUri 回跳地址
     * @param state 重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值,最多128字节
     * @param snsapiBase snsapi_base(不弹出授权页面,只能拿到用户openid)snsapi_userinfo(弹出授权页面,这个可以通过 openid 拿到昵称、性别、所在地)
     * @return url
     */
    public static String getAuthorizeURL(String appId, String redirectUri, String state, boolean snsapiBase) {
        Map<String, String> params = new HashMap<String, String>();
        params.put("appid", appId);
        params.put("response_type", "code");
        params.put("redirect_uri", redirectUri);
        // snsapi_base(不弹出授权页面,只能拿到用户openid)
        // snsapi_userinfo(弹出授权页面,这个可以通过 openid 拿到昵称、性别、所在地)
        if (snsapiBase) {
            params.put("scope", "snsapi_base");
        } else {
            params.put("scope", "snsapi_userinfo");
        }
        if (StrKit.isBlank(state)) {
            params.put("state", "wx#wechat_redirect");
        } else {
            params.put("state", state.concat("#wechat_redirect"));
        }
        String para = PaymentKit.packageSign(params, false);
        return authorize_uri + "?" + para;
    }
    

    /**
     * 生成网页二维码授权链接
     * @param appId 应用id
     * @param redirect_uri 回跳地址
     * @return url
     */
    public static String getQrConnectURL(String appId, String redirect_uri) {
        return getQrConnectURL(appId, redirect_uri, null);
    }
    
    /**
     * 生成网页二维码授权链接
     * @param appId 应用id
     * @param redirect_uri 回跳地址
     * @param state 重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值,最多128字节
     * @return url
     */
    public static String getQrConnectURL(String appId, String redirect_uri, String state) {
        Map<String, String> params = new HashMap<String, String>();
        params.put("appid", appId);
        params.put("response_type", "code");
        params.put("redirect_uri", redirect_uri);
        params.put("scope", "snsapi_login");
        if (StrKit.isBlank(state)) {
            params.put("state", "wx#wechat_redirect");
        } else {
            params.put("state", state.concat("#wechat_redirect"));
        }
        String para = PaymentKit.packageSign(params, false);
        return qrconnect_url + "?" + para;
    }
    
    /**
     * 通过code获取access_token
     *
     * @param code   第一步获取的code参数
     * @param appId  应用唯一标识
     * @param secret 应用密钥AppSecret
     * @return SnsAccessToken
     */
    public static SnsAccessToken getSnsAccessToken(String appId, String secret, String code)
    {
        final Map<String, String> queryParas = ParaMap.create("appid", appId).put("secret", secret).put("code", code).getData();
        
        return RetryUtils.retryOnException(3, new Callable<SnsAccessToken>() {
            
            @Override
            public SnsAccessToken call() throws Exception {
                String json = HttpUtils.get(url, queryParas);
                return new SnsAccessToken(json);
            }
        });
    }
}

用户管理接口,获取用户基本信息(UnionID机制)

import com.jfinal.weixin.sdk.kit.ParaMap;
import com.jfinal.weixin.sdk.utils.HttpUtils;
import com.jfinal.weixin.sdk.utils.JsonUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 用户管理 API
 * <pre>
 * https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN
 * </pre>
 */
public class UserApi {
    
    private static String getUserInfo = "https://api.weixin.qq.com/cgi-bin/user/info";
    private static String getFollowers = "https://api.weixin.qq.com/cgi-bin/user/get";
    private static String batchGetUserInfo = "https://api.weixin.qq.com/cgi-bin/user/info/batchget?access_token=";

    /**
     * 获取用户基本信息(包括UnionID机制)
     * @param openId 普通用户的标识,对当前公众号唯一
     * @return ApiResult
     */
    public static ApiResult getUserInfo(String openId) {
        ParaMap pm = ParaMap.create("access_token", AccessTokenApi.getAccessTokenStr()).put("openid", openId).put("lang", "zh_CN");
        return new ApiResult(HttpUtils.get(getUserInfo, pm.getData()));
    }
    
    /**
     * 获取用户列表
     * @param nextOpenid 第一个拉取的OPENID,不填默认从头开始拉取
     * @return ApiResult
     */
    public static ApiResult getFollowers(String nextOpenid) {
        ParaMap pm = ParaMap.create("access_token", AccessTokenApi.getAccessTokenStr());
        if (nextOpenid != null)
            pm.put("next_openid", nextOpenid);
        return new ApiResult(HttpUtils.get(getFollowers, pm.getData()));
    }
    
    /**
     * 获取用户列表
     * @return ApiResult
     */
    public static ApiResult getFollows() {
        return getFollowers(null);
    }

    /**
     * 批量获取用户基本信息, by Unas
     * @param jsonStr json字符串
     * @return ApiResult
     */
    public static ApiResult batchGetUserInfo(String jsonStr) {
        String jsonResult = HttpUtils.post(batchGetUserInfo + AccessTokenApi.getAccessTokenStr(), jsonStr);
        return new ApiResult(jsonResult);
    }
    
    /**
     * 批量获取用户基本信息
     * @param openIdList openid列表
     * @return ApiResult
     */
    public static ApiResult batchGetUserInfo(List<String> openIdList) {
        Map<String, List<Map<String, Object>>> userListMap = new HashMap<String, List<Map<String, Object>>>();
        
        List<Map<String, Object>> userList = new ArrayList<Map<String,Object>>();
        for (String openId : openIdList) {
            Map<String, Object> mapData = new HashMap<String, Object>();
            mapData.put("openid", openId);
            mapData.put("lang", "zh_CN");
            userList.add(mapData);
        }
        userListMap.put("user_list", userList);
        
        return batchGetUserInfo(JsonUtils.toJson(userListMap));
    }
    
    private static String updateRemarkUrl = "https://api.weixin.qq.com/cgi-bin/user/info/updateremark?access_token=";
    
    /**
     * 设置备注名
     * @param openid 用户标识
     * @param remark 新的备注名,长度必须小于30字符
     * @return {ApiResult}
     */
    public static ApiResult updateRemark(String openid, String remark) {
        String url = updateRemarkUrl + AccessTokenApi.getAccessTokenStr();
        
        Map<String, String> mapData = new HashMap<String, String>();
        mapData.put("openid", openid);
        mapData.put("remark", remark);
        String jsonResult = HttpUtils.post(url, JsonUtils.toJson(mapData));
        
        return new ApiResult(jsonResult);
    }
}

推荐阅读
Android版-微信APP支付
极速开发微信公众号之微信买单
极速开发微信公众号之公众号支付
极速开发微信公众号之扫码支付
极速开发微信公众号之刷卡支付
极速开发微信公众号之现金红包
Android版-支付宝APP支付
支付宝Wap支付
一张二维码集成微信、支付宝支付

源码下载地址
记录学习的点滴,以此勉励不断奋斗的自己✌️✌️✌️ 如果对你有帮助记得点喜欢告诉我

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,348评论 6 491
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,122评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,936评论 0 347
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,427评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,467评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,785评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,931评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,696评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,141评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,483评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,625评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,291评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,892评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,741评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,977评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,324评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,492评论 2 348

推荐阅读更多精彩内容

  • 很早前就想了解下微信公众号开发,懒和拖延症让这计划迟迟没落实,正巧新项目有了微信公众号的业务,我心中没数地回应,我...
    英文名叫夏天阅读 4,407评论 1 4
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,757评论 25 707
  • 1 去微信开放平台创建应用 审核通过后会得到AppID和AppSecret(这两个很重要) 2 接入自己的网站 (...
    史史小子阅读 1,201评论 0 2
  • 看着时间一分一秒的走,今天一天又快过完了,又是一个十二点还没睡的日子。最近在一件事上纠结了半个月,似乎每天都在围着...
    漆家小三阅读 194评论 0 1
  • 有没有发现有的红木家具买回来,发现放在室内变小了,有的则放不下,还有的显得很突兀、别扭,这都是没有充分规划好空间大...
    林远腾博客阅读 266评论 0 0