Android微信授权登录分享---封装类

2018.03.22 增加微信分享

简介

⚠️本文不包含sdk 集成、appId申请等基础步骤,入门移步 微信官方集成文档,查找错误码请戳微信官方错误码

项目地址: WechatHelper

微信授权登陆

使用方式

  • 请在在UserConstants类中设置AppIDAppSecret

  • 请在需要接收微信回调页面增加WechatObserver处理回调后的结果(参见MainActivity.WechatAuthObserver)

  • 请在发起微信授权时调用

    WechatHelper.getInstance().addWechatObserver(mWechatLoginObserver);
    WechatHelper.getInstance().authorizeByWechat();
    

请注意观察者收到回调后的线程问题

整体流程

外部进行授权操作时,首先需要注册Observer,然后调用接口方法authorizeByWechat。当授权状态发生变化时,Observer会接收到对应的状态,最终通过Handler触发不同状态的下的操作。

微信分享(在线链接/网络图片/在线图片)

使用方式

  • 请在在UserConstants类中设置AppIDAppSecret

方法说明:

  1. 对话分享接口:

WechatHelper.getInstance().shareWechat(ShareParams params)

使用参考:

分享类型 具体方法
链接分享 WechatShareTest.shareLinkToWechat
网络图片分享 WechatShareTest.shareNetworkImageToWechat
本地图片分享 WechatShareTest.shareLocalImageToWechat
  1. 朋友圈分享接口:

WechatHelper.getInstance().shareWechatMoments(ShareParams params)

使用参考:

分享类型 具体方法
链接分享 WechatShareTest.shareLinkToWechatMoments
网络图片分享 WechatShareTest.shareNetworkImageToWechatMoments
本地图片分享 WechatShareTest.shareLocalImageToWechatMoments
  1. 分享参数ShareParams

    ShareParams属性 功能 取值
    mShareType 分享类型 ShareType.LOCAL_IMAGE(本地图片分享),ShareType.NETWORK_IMAGE(网络图片分享),ShareType.LINK(链接分享)
    mTitle 分享标题 String类型
    mText 分享内容 String类型
    mLinkUrl 分享链接 String类型
    mNetworkImageUrl 分享网络图片链接 String类型
    mLocalBitmap 分享本地图片 Bitmap类型

核心类

WechatHelper

public class WechatHelper {
    private static final String TAG = "WechatManager";

    private final String GET_REQUEST_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token";
    private final String GET_EXPIRE_TOKEN_URL = "https://api.weixin.qq.com/sns/aaswuth";
    private final String GET_USER_INFO_URL = "https://api.weixin.qq.com/sns/userinfo";
    private final String GET_REFRESH_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/refresh_token";

    public static final int WECHAT_CHECK_SUCCESS = 166;
    public static final int WECHAT_CHECK_FAILURE = 167;

    private static IWXAPI api;

    private static WechatHelper instance;

    private static WechatObservable mWechatObservable;

    private WXErrorInfo mWXErrorInfo;

    public void addWechatObserver(WechatObserver observer) {
        mWechatObservable.addObserver(observer);
    }

    public void removeWechatObserver(WechatObserver observer) {
        mWechatObservable.deleteObserver(observer);
    }

    public void removeAllWechatObserver() {
        mWechatObservable.deleteObservers();
    }

    public void sendUserConfirmMessage(int code) {
        mWechatObservable.sendStateChange(code);
    }

    private WechatHelper() {
        api = WXAPIFactory.createWXAPI(GlobalConfig.getAppContext(), UserConstants.WECHAT_APPIDS, true);
        api.registerApp(UserConstants.WECHAT_APPIDS);
        mWechatObservable = new WechatObservable();
    }

    public static WechatHelper getInstance() {
        if (instance == null) {
            synchronized (WechatHelper.class) {
                if (instance == null) {
                    instance = new WechatHelper();
                }
            }
        }

        return instance;
    }

    public IWXAPI getApi() {
        return api;
    }

    public void authorizeByWechat() {
        Log.i(TAG, "authorizeByWechat: ");

        if (!isAvailable()) {
            mWechatObservable.sendStateChange(WECHAT_CHECK_FAILURE);
            return;
        }

        SendAuth.Req req = new SendAuth.Req();
        req.scope = "snsapi_userinfo";
        req.state = "app_wechat";
        api.sendReq(req);
    }

    public void checkAccessToken(String code) {
        // 从手机本地获取存储的授权口令信息,判断是否存在access_token,不存在请求获取,存在就判断是否过期
        String accessToken = WechatInfoSPHelper.getWechatAccessToken();
        String openid = WechatInfoSPHelper.getWechatOpenid();

        if (!TextUtils.isEmpty(accessToken) && !TextUtils.isEmpty(openid)) {
            // 有access_token,判断是否过期有效
            isExpireAccessToken(accessToken, openid);
        } else {
            getTokenFromCode(code);
        }
    }

    private void isExpireAccessToken(final String accessToken, final String openid) {
        Log.i(TAG, "isExpireAccessToken: ");
        if (TextUtils.isEmpty(accessToken) || TextUtils.isEmpty(openid)) {
            mWechatObservable.sendStateChange(WECHAT_CHECK_FAILURE);
            return;
        }

        // 使用网络库发起请求
        NetworkHttpParam params = new NetworkHttpParam();
        params.put("access_token", accessToken);
        params.put("openid", openid);

        OkHttpHelper.getInstance().requestStringGet(GET_EXPIRE_TOKEN_URL, params, new WechatDataHandler(false) {

            @Override
            public void onWechatSuccess(String response) {
                super.onWechatSuccess(response);

                if (validateSuccess(response)) {
                    // accessToken没有过期,获取用户信息
                    getUserInfo(accessToken, openid);
                } else {
                    // 过期了,使用refresh_token来刷新accesstoken
                    refreshAccessToken();
                }
            }
        });
    }

    private void refreshAccessToken() {
        Log.i(TAG, "refreshAccessToken: ");
        // 从本地获取存储的refresh_token
        final String refreshToken = WechatInfoSPHelper.getWechatRefreshToken();

        if (refreshToken == null) {
            mWechatObservable.sendStateChange(WECHAT_CHECK_FAILURE);
            return;
        }

        // 发起网络请求 刷新token
        NetworkHttpParam params = new NetworkHttpParam();
        params.put("appid", UserConstants.WECHAT_APPIDS);
        params.put("grant_type", "refresh_token");
        params.put("refresh_token", refreshToken);

        OkHttpHelper.getInstance().requestStringGet(GET_REFRESH_TOKEN_URL, params, new WechatDataHandler(true) {

            @Override
            public void onWechatDataSuccess(String response) {
                super.onWechatDataSuccess(response);

                WXAccessTokenInfo tokenInfo = JsonFactory.fromJson(response, WXAccessTokenInfo.class);

                if (tokenInfo == null) {
                    mWechatObservable.sendStateChange(WECHAT_CHECK_FAILURE);
                } else {
                    WechatInfoSPHelper.saveWechatAccessInfoToSP(tokenInfo);
                    getUserInfo(tokenInfo.access_token, tokenInfo.openid);
                }
            }
        });
    }

    /**
     * 使用code获取微信登陆token凭证
     */
    private void getTokenFromCode(String code) {
        Log.i(TAG, "getTokenFromCode: ");
        if (TextUtils.isEmpty(code)) {
            mWechatObservable.sendStateChange(WECHAT_CHECK_FAILURE);
            return;
        }

        // 发起网络请求 刷新token
        NetworkHttpParam params = new NetworkHttpParam();
        params.put("appid", UserConstants.WECHAT_APPIDS);
        params.put("secret", UserConstants.WECHAT_SECRET);
        params.put("code", code);
        params.put("grant_type", "authorization_code");

        OkHttpHelper.getInstance().requestStringGet(GET_REQUEST_ACCESS_TOKEN_URL, params, new WechatDataHandler(true) {

            @Override
            public void onWechatDataSuccess(String response) {
                super.onWechatDataSuccess(response);

                WXAccessTokenInfo tokenInfo = JsonFactory.fromJson(response, WXAccessTokenInfo.class);

                if (tokenInfo == null) {
                    mWechatObservable.sendStateChange(WECHAT_CHECK_FAILURE);
                } else {
                    WechatInfoSPHelper.saveWechatAccessInfoToSP(tokenInfo);

                    getUserInfo(tokenInfo.access_token, tokenInfo.openid);
                }
            }
        });
    }

    // 使用access_token获取用户信息
    private void getUserInfo(String access_token, String openid) {
        Log.i(TAG, "getUserInfo: ");

        if (TextUtils.isEmpty(access_token) || TextUtils.isEmpty(openid)) {
            mWechatObservable.sendStateChange(WECHAT_CHECK_FAILURE);
            return;
        }

        // 发起网络请求 刷新token
        NetworkHttpParam params = new NetworkHttpParam();
        params.put("access_token", access_token);
        params.put("lang", "zh_CN");
        params.put("openid", openid);

        OkHttpHelper.getInstance().requestStringGet(GET_USER_INFO_URL, params, new WechatDataHandler(true) {

            @Override
            public void onWechatDataSuccess(String response) {
                super.onWechatDataSuccess(response);

                WXUserInfo userInfo = JsonFactory.fromJson(response, WXUserInfo.class);

                if (userInfo == null) {
                    mWechatObservable.sendStateChange(WECHAT_CHECK_FAILURE);
                } else {
                    WechatInfoSPHelper.saveWechatUserInfoToSP(userInfo);
                    mWechatObservable.sendStateChange(WECHAT_CHECK_SUCCESS);
                }
            }
        });
    }

    private boolean validateSuccess(String response) {
        Log.i(TAG, "validateSuccess: " + response);

        if (response.contains("errcode") && response.contains("errmsg")) {
            int code = 66666;

            try {
                JSONObject obj = new JSONObject(response);
                code = obj.getInt("errcode");

                if (code != 66666) {
                    return false;
                }

            } catch (JSONException e) {
                e.printStackTrace();
                return true;
            }
        }

        return true;
    }

    private class LeWechatHandler implements NetworkHandler<Object> {

        @Override
        public void onSuccess(Object response) {
            Log.i(TAG, "WechatVolleyHandler onSuccess: " + response);
            String responseStr = (String) response;

            if (TextUtils.isEmpty(responseStr)) {
                mWechatObservable.sendStateChange(WECHAT_CHECK_FAILURE);
                return;
            }

            onWechatSuccess(responseStr);
        }

        @Override
        public void onFailure(int errorCode) {
            Log.i(TAG, "WechatVolleyHandler onFailure: " + errorCode);
            mWechatObservable.sendStateChange(WECHAT_CHECK_FAILURE);
        }

        public void onWechatSuccess(String response) {

        }
    }

    /**
     * 增加异常判断
     */
    private class WechatDataHandler extends LeWechatHandler {

        // 微信校验token接口:  校验不成功时返回数据格式与网络失败格式相同
        private boolean mNeedCheckError = false;

        WechatDataHandler(boolean needCheckError) {
            mNeedCheckError = needCheckError;
        }

        @Override
        public void onWechatSuccess(String response) {
            super.onWechatSuccess(response);

            if (mNeedCheckError && !validateSuccess(response)) {
                mWXErrorInfo = JsonFactory.fromJson(response, WXErrorInfo.class);

                if (mWXErrorInfo == null) {
                    mWechatObservable.sendStateChange(WECHAT_CHECK_FAILURE);
                } else {
                    mWechatObservable.sendStateChange(WECHAT_CHECK_FAILURE);
                }

                return;
            }

            onWechatDataSuccess(response);
        }

        public void onWechatDataSuccess(String response) {

        }
    }

    ///////////////// 微信分享 //////////////////////

    /**
     * 微信对话分享
     */
    public void shareWechat(ShareParams params, SucceedAndFailedHandler shareListener) {
        switch (params.getShareType()) {
            case ShareType.LOCAL_IMAGE:
                shareLocalImage(params, shareListener);
                break;
            case ShareType.NETWORK_IMAGE:
                shareNetworkImage(params, shareListener);
                break;
            case ShareType.LINK:
                shareLink(params, shareListener);
                break;
            default:
                shareListener.onFailure(-1);
        }
    }

    /**
     * 微信朋友圈分享
     */
    public void shareWechatMoments(ShareParams params, SucceedAndFailedHandler shareListener) {
        switch (params.getShareType()) {
            case ShareType.LOCAL_IMAGE:
                shareMomentsLocalImage(params, shareListener);
                break;
            case ShareType.NETWORK_IMAGE:
                shareMomentsNetworkImage(params, shareListener);
                break;
            case ShareType.LINK:
                shareMomentsLink(params, shareListener);
                break;
            default:
                shareListener.onFailure(-1);
        }
    }

    /**
     * 微信对话分享 本地图片
     */
    private void shareLocalImage(ShareParams params, SucceedAndFailedHandler shareListener) {
        Bitmap bmp = params.getLocalBitmap();

        if (bmp == null) {
            if (shareListener != null) {
                shareListener.onFailure(-1);
            }
            return;
        }

        wechatShareImage(shareListener, bmp);
    }

    /**
     * 微信对话分享 网络图片
     */
    private void shareNetworkImage(ShareParams params, final SucceedAndFailedHandler shareListener) {
        String shareImage = params.getNetworkImageUrl();

        if (TextUtils.isEmpty(shareImage)) {
            if (shareListener != null) {
                shareListener.onFailure(-1);
            }
            return;
        }

        NetworkHandler<Bitmap> imgHandler = new NetworkHandler<Bitmap>() {
            @Override
            public void onSuccess(Bitmap bitmap) {
                wechatShareImage(shareListener, bitmap);
            }

            @Override
            public void onFailure(int errorCode) {
                if (shareListener != null) {
                    shareListener.onFailure(-1);
                }
            }
        };

        OkHttpHelper.getInstance().requestBitmapFromUrl(shareImage, imgHandler);
    }

    /**
     * 微信对话分享 在线链接
     */
    private void shareLink(final ShareParams params, final SucceedAndFailedHandler shareListener) {
        if (TextUtils.isEmpty(params.getLinkUrl())) {
            if (shareListener != null) {
                shareListener.onFailure(-1);
            }
            return;
        }

        // 缩略图
        String thumbUrl = params.getNetworkImageUrl();

        if (TextUtils.isEmpty(thumbUrl)) {
            wechatShareLink(getDefaultBitmap(), params, shareListener);
        } else {
            NetworkHandler<Bitmap> imgHandler = new NetworkHandler<Bitmap>() {
                @Override
                public void onSuccess(Bitmap thumbBitmap) {
                    wechatShareLink(thumbBitmap, params, shareListener);
                }

                @Override
                public void onFailure(int errorCode) {
                    wechatShareLink(getDefaultBitmap(), params, shareListener);
                }
            };

            OkHttpHelper.getInstance().requestBitmapFromUrl(thumbUrl, imgHandler);
        }
    }

    /**
     * 微信朋友圈分享 本地图片
     */
    private void shareMomentsLocalImage(ShareParams params, SucceedAndFailedHandler shareListener) {
        Bitmap bmp = params.getLocalBitmap();

        if (bmp == null) {
            if (shareListener != null) {
                shareListener.onFailure(-1);
            }
            return;
        }

        wechatMomentsShareImage(bmp, shareListener);
    }

    /**
     * 微信朋友圈分享 网路图片
     */
    private void shareMomentsNetworkImage(ShareParams params, final SucceedAndFailedHandler shareListener) {
        String shareImage = params.getNetworkImageUrl();

        if (TextUtils.isEmpty(shareImage)) {
            if (shareListener != null) {
                shareListener.onFailure(-1);
            }
            return;
        }

        NetworkHandler<Bitmap> imgHandler = new NetworkHandler<Bitmap>() {
            @Override
            public void onSuccess(Bitmap bitmap) {
                wechatMomentsShareImage(bitmap, shareListener);
            }

            @Override
            public void onFailure(int errorCode) {
                if (shareListener != null) {
                    shareListener.onFailure(-1);
                }
            }
        };

        OkHttpHelper.getInstance().requestBitmapFromUrl(shareImage, imgHandler);
    }

    /**
     * 微信朋友圈分享 在线链接
     */
    private void shareMomentsLink(final ShareParams params, final SucceedAndFailedHandler shareListener) {
        if (TextUtils.isEmpty(params.getLinkUrl())) {
            if (shareListener != null) {
                shareListener.onFailure(-1);
            }
            return;
        }

        // 缩略图
        String thumbUrl = params.getNetworkImageUrl();

        if (TextUtils.isEmpty(thumbUrl)) {
            wechatMomentsShareLink(getDefaultBitmap(), params, shareListener);
        } else {
            NetworkHandler<Bitmap> imgHandler = new NetworkHandler<Bitmap>() {
                @Override
                public void onSuccess(Bitmap thumbBitmap) {
                    wechatMomentsShareLink(thumbBitmap, params, shareListener);
                }

                @Override
                public void onFailure(int errorCode) {
                    wechatMomentsShareLink(getDefaultBitmap(), params, shareListener);
                }
            };

            OkHttpHelper.getInstance().requestBitmapFromUrl(thumbUrl, imgHandler);
        }
    }

    private void wechatShareLink(Bitmap bmp, ShareParams params, SucceedAndFailedHandler handler) {
        SendMessageToWX.Req req = new SendMessageToWX.Req();
        WXWebpageObject webPageObject = new WXWebpageObject();

        Bitmap thumbBit = Bitmap.createScaledBitmap(bmp, 100, 100, true);

        webPageObject.webpageUrl = params.getLinkUrl();
        WXMediaMessage msg = new WXMediaMessage(webPageObject);
        req.transaction = buildTransaction("webpage");
        msg.title = params.getTitle();
        msg.description = params.getText();
        msg.thumbData = ImageUtil.parseBitmapToBytes(thumbBit);

        req.message = msg;
        req.scene = SendMessageToWX.Req.WXSceneSession;

        api.sendReq(req);
    }

    private void wechatShareImage(SucceedAndFailedHandler handler, Bitmap bmp) {
        SendMessageToWX.Req req = new SendMessageToWX.Req();
        WXImageObject imageObject = new WXImageObject(bmp);
        WXMediaMessage msg = new WXMediaMessage(imageObject);

        msg.mediaObject = imageObject;

        Bitmap thumbBit = Bitmap.createScaledBitmap(bmp, 100, 100, true);
        msg.thumbData = ImageUtil.parseBitmapToBytes(thumbBit);

        req.transaction = buildTransaction("img");
        req.message = msg;
        req.scene = SendMessageToWX.Req.WXSceneSession;

        api.sendReq(req);
    }

    private void wechatMomentsShareLink(Bitmap bmp, ShareParams params, SucceedAndFailedHandler handler) {
        SendMessageToWX.Req req = new SendMessageToWX.Req();
        WXWebpageObject webPageObject = new WXWebpageObject();
        webPageObject.webpageUrl = params.getLinkUrl();
        WXMediaMessage msg = new WXMediaMessage(webPageObject);

        Bitmap thumbBit = Bitmap.createScaledBitmap(bmp, 100, 100, true);

        req.transaction = buildTransaction("webpage");
        msg.title = params.getTitle();
        msg.description = params.getText();
        msg.thumbData = ImageUtil.parseBitmapToBytes(thumbBit);
        req.message = msg;
        req.scene = SendMessageToWX.Req.WXSceneTimeline;

        api.sendReq(req);
    }

    private void wechatMomentsShareImage(Bitmap bmp, SucceedAndFailedHandler handler) {
        SendMessageToWX.Req req = new SendMessageToWX.Req();

        WXImageObject imageObject = new WXImageObject(bmp);
        WXMediaMessage msg = new WXMediaMessage(imageObject);
        msg.mediaObject = imageObject;

        Bitmap thumbBit = Bitmap.createScaledBitmap(bmp, 100, 100, true);

        msg.thumbData = ImageUtil.parseBitmapToBytes(thumbBit);
        req.transaction = buildTransaction("img");

        req.message = msg;
        req.scene = SendMessageToWX.Req.WXSceneTimeline;

        api.sendReq(req);
    }

    /**
     * 获取默认缩略图
     */
    private Bitmap getDefaultBitmap() {
        return BitmapFactory.decodeResource(GlobalConfig.getAppContext().getResources(), R.mipmap.ic_launcher);
    }

    private boolean isAvailable() {
        return api.isWXAppInstalled() && api.isWXAppSupportAPI();
    }

    private String buildTransaction(final String type) {
        return (type == null) ? String.valueOf(System.currentTimeMillis()) : type + System.currentTimeMillis();
    }
}

混淆代码:-keep class com.gjf.wc.model.** {*;}

参考链接

微信工具类封装参考自什么,集成微信登录只要三行代码 , 目前为止发现的封装最好的工具类!给作者大赞!

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

推荐阅读更多精彩内容