Erweiterte WeChat-Scancode-Anmeldung für Android

Da wir auf neue Bedürfnisse stoßen, müssen wir eine WeChat-Scancode-Anmeldefunktion erstellen. Dieser Artikel wurde zusammen mit meinem Codierungsprozess geschrieben. Ich hoffe, dass er Menschen in Not und mir selbst helfen kann, die diese Funktion in Zukunft erneut nutzen werden.

Das erste, was mir in den Sinn kommt, sind die verschiedenen Artikel von Baidu. Natürlich ist es wichtig, auf die Entwicklerplattform zu gehen, um eine AppID und einen Schlüssel zu beantragen. Nach der Registrierung werden Sie feststellen, dass Sie einen Antrag erstellen und überprüfen müssen (offiziell). Website, Flussdiagramm und andere Informationen), denken Sie darüber nach, zuerst eines zu schreiben. Die Demo wird entwickelt, es muss nicht so mühsam sein,

Durch einen Artikel habe ich herausgefunden, dass WeChat immer noch über ein Testkonto verfügt -> WeChat-Scancode-Login-Detaillierter Betriebsprozess (Entwicklung der öffentlichen WeChat-Plattform)
liegt mir nicht am Herzen, ich habe die Logik gemäß den vorhandenen relativ klaren Artikeln geschrieben -> Android Android-Entwicklung integriertes WeChat QR-Code-Login zum Scannen von Drittanbietern – super unbesiegbare Details

Nachdem ich die von mir beantragte Test-AppID und den beantragten Schlüssel eingegeben habe, kann ich beim Rückruf nicht zur Methode onAuthGotQrcode wechseln. Sehen Sie sich oauth.auth() an, um die QR-Code-Methode abzurufen und True zurückzugeben, und gehen Sie direkt zur Methode onAuthFinish Jedes Mal. Im Inneren ist es nicht lächerlich, die AppID und der Schlüssel werden beantragt, die Codelogik bezieht sich auch auf viele Artikel, es gibt theoretisch kein Problem und die Erfassungsmethode gibt auch True zurück, aber jedes Mal wird der folgende Fehler gemeldet: >
E/MicroMsg.SDK.GetQRCodeResult: resp errcode = -21
E/MicroMsg.SDK.GetQRCodeTask: onPostExecute, qrcode abrufen fehlgeschlagen, OAuthErrCode = OAuthErrCode:-1

Wenn Sie auf ein Problem stoßen, können Sie es lösen. Gehen Sie zum Dokument, um den Fehlercode -21 -1 zu finden. Ich kann ihn nicht finden, mmp, gehen Sie zu Baidu für diese Art von Fehler, ich habe festgestellt, dass viele Leute darauf gestoßen sind , und keiner von ihnen hat eine Lösung gegeben, aber es gibt einen Artikel. Der Fehler ähnelt meinem, und die Lösung wird auch angegeben ->
Android erhält den WeChat-QR-Code DiffDevOAuth.auth

Tatsächlich gibt es keine Lösung. Das Dokument besagt auch, dass die Groß- und Kleinbuchstaben des Felds falsch sind und der Parametername falsch ist. Ich habe diese überprüft, aber es ist aus dem Fehler ersichtlich, dass der QR erfasst wurde Code ist fehlgeschlagen. Es gibt viele Gründe für den Fehler. Möglicherweise liegt uns nicht das gleiche Problem zugrunde

Nach einer pauschalen Suche im Internet bin ich auf ein Problem gestoßen, das die Vergangenheit erklären könnte. WeChat ist in öffentliche Plattformen und offene Plattformen unterteilt. Ist es möglich, dass dies das Problem ist, muss man früher oder später einen Antrag stellen, also man Sie sollten sich zuerst bewerben. Hier müssen Sie darauf achten. Wenn Sie sich bewerben, benötigen Sie Unternehmensinformationen (möglicherweise müssen Sie zur Überprüfung eine Gebühr auf das Unternehmenskonto zahlen), eine seriöse offizielle Website und ein APP-Flussdiagramm. Bereiten Sie sich im Voraus vor und warten Sie Bis der offizielle Ausweis und der Schlüssel in ein paar Tagen herauskommen.

Nach etwa drei oder vier Tagen war die Bewerbungsprüfung erfolgreich, aber um sich für die WeChat-Anmeldung zu bewerben, müssen Sie die Entwicklerqualifikationszertifizierung durchlaufen, die Prüfungsgebühr beträgt 300 Yuan und Sie müssen verschiedene Informationen zum Unternehmen, zur Geschäftslizenz usw. ausfüllen. Kreditcode usw.

Die Generierung des Schlüssels muss auch an die WeChat-Scancode-Verifizierung der Bankkarte des Administrators gebunden sein

Nach etwa vier oder fünf Tagen habe ich endlich die AppID und das Passwort erhalten und die WeChat-Anmeldeberechtigung geöffnet. Der aufregende Moment ist gekommen. Ich habe die seriösen Daten in die Logik eingefügt und der QR-Code wird normal angezeigt! Auch das Abrufen von Benutzerdaten ist normal!

Zusammenfassung:
Die von der öffentlichen WeChat-Plattform angewendete Test-AppID und der Testschlüssel können nicht für Vorgänge auf der offenen WeChat-Plattform verwendet werden, wie z. B. APP-Scancode-Anmeldung, Zahlung usw.

Als nächstes werde ich meinen Quellcode veröffentlichen (mein folgender Code läuft normal, wenn nötig, ersetzen Sie einfach appID und appsecret, und andere Logiktests sind verfügbar), versuche, detaillierte Kommentare zu schreiben, oder verwende den Link, den ich oben gepostet habe

Importabhängigkeiten sind unerlässlich

    implementation 'com.squareup.okhttp3:okhttp:3.12.0'
    implementation 'com.google.code.gson:gson:2.8.9'

    //微信登录
    implementation 'com.tencent.mm.opensdk:wechat-sdk-android:+'

verwenden

        WxQUtils().create(object : WxQUtils.OnMListener {
            override fun onQSuccess(b: Bitmap?) {
                //获取二维码成功,给ImageView 赋值
                ivQe?.setImageBitmap(b)
            }

            override fun onUSuccess(b: WxQUtils.WxQBean) {
                //获取用户信息成功
                runOnUiThread {
                    Toast.makeText(this@WxLoginActivity, b.nickname, Toast.LENGTH_SHORT).show()
                }
            }

            override fun onError(msg: String?) {
                //出错了
                runOnUiThread { Toast.makeText(this@WxLoginActivity, msg, Toast.LENGTH_SHORT).show() }
            }
        })

WxQUtils können direkt kopiert und mit der oben genannten Methode verwendet werden

/**
 * 微信扫码登录,工具类
 * */
public class WxQUtils implements OAuthListener{

    //获取微信二维码需要用到的对象
    private static IDiffDevOAuth oauth = null;
    //时间转换格式
    private static final String TIME_FORMAT = "yyyyMMddHHmmss";
    //开放平台创建应用产生的AppID
    private static final String appID = "xxxxxxxxxxxxxxxxxxxx";
    //开放平台创建应用产生的密钥
    private static final String appsecret = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";

    public void create(OnMListener listener){
        mOnListener = listener;
        //初始化获取二维码的对象
        oauth = DiffDevOAuthFactory.getDiffDevOAuth();
        //开始获取数据(第一步)
        getAccessToken();
    }

    private  void getAccessToken() {
        //第一步请求
        OkHttpClient client = new OkHttpClient();
        Request.Builder builder = new Request.Builder();
        String getAccessToken = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appID + "&secret=" + appsecret;
        Request request1 = builder.get().url(getAccessToken)
                .build();

        client.newCall(request1).enqueue(new Callback() {
            @Override
            public void onFailure(@NonNull Call call, @NonNull IOException e) {
                  mOnListener.onError("第一步网络请求出错~");
            }

            @Override
            public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
                ResponseBody mBean = response.body();
                if (mBean != null){
                    String res = mBean.string();//请求成功时返回的东西
                    WxQBean mData = new Gson().fromJson(res,WxQBean.class);
                    if (mData.getAccess_token() != null && !"".equals(mData.getAccess_token() )){
                        //拿到第一步数据,开始第二步
                        getTicket(mData.getAccess_token() );
                    }
                }
            }
        });
    }

    private  void getTicket(String l){
        //第二步网络请求
        OkHttpClient client = new OkHttpClient();
        Request.Builder builder = new Request.Builder();
        Request request1 = builder.get().url("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + l + "&type=2")
                .build();
        client.newCall(request1).enqueue(new Callback() {
            @Override
            public void onFailure(@NonNull Call call, @NonNull IOException e) {
                mOnListener.onError("第二步网络请求出错~");
            }

            @Override
            public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
                ResponseBody mBean = response.body();
                if (mBean != null){
                    //拿到数据进行数据组合
                    String res = mBean.string();//请求成功时返回的东西
                    WxQBean mData = new Gson().fromJson(res,WxQBean.class);
                    if (mData.getTicket() != null){
                        StringBuilder str  = new StringBuilder();
                        Random random = new Random();
                        for (int i = 0; i < 8; i++){
                            str.append(random.nextInt(10));
                        }
                        String noncestr = str.toString();
                        String timeStamp = new SimpleDateFormat(TIME_FORMAT).format(new Date());

                        String string1 = String.format("appid=%s&noncestr=%s&sdk_ticket=%s&timestamp=%s", appID, noncestr, mData.getTicket(), timeStamp);
                        String sha = EncryptUtils.getSHA(string1);
                        //开始进行第三步
                        sign(noncestr,timeStamp,sha);
                    }
                }
            }
        });
    }

    private  void sign(String noncestr, String timeStamp, String sha){
        if (oauth != null){
            oauth.removeAllListeners();
            oauth.stopAuth();
            oauth.detach();
            //第四步,获取二维码,获取到的二维码从回调(onAuthGotQrcode)里面显示
            Boolean s = oauth.auth(appID,"snsapi_userinfo",noncestr,timeStamp,sha,WxQUtils.this);
        }
    }

    private void getUserData(String c){
        //开始第五步
        OkHttpClient client = new OkHttpClient();
        Request.Builder builder = new Request.Builder();
        Request request1 = builder.get().url("https://api.weixin.qq.com/sns/oauth2/access_token?appid="+ appID
                        +"&secret=" + appsecret + "&code=" +c+ "&grant_type=authorization_code")
                .build();
        client.newCall(request1).enqueue(new Callback() {
            @Override
            public void onFailure(@NonNull Call call, @NonNull IOException e) {
                mOnListener.onError("第五步网络请求出错~");
            }

            @Override
            public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
                ResponseBody mBean = response.body();
                if (mBean != null){
                    String res = mBean.string();//请求成功时返回的东西
                    WxQBean mData = new Gson().fromJson(res,WxQBean.class);
                    if (mData.getOpenid() != null && !Objects.equals(mData.getOpenid(), "") &&
                            mData.getAccess_token() != null && !Objects.equals(mData.getAccess_token(), "")){
                        //拿到数据,最后一步获取用户信息
                        getUserInfo(mData.getOpenid(),mData.getAccess_token());
                    }
                }
            }
        });
    }


    private void getUserInfo(String openID, String aToken){
        //获取用户信息
        OkHttpClient client = new OkHttpClient();
        Request.Builder builder = new Request.Builder();
        Request request1 = builder.get().url("https://api.weixin.qq.com/sns/userinfo?access_token=" +aToken+"&openid=" + openID)
                .build();
        client.newCall(request1).enqueue(new Callback() {
            @Override
            public void onFailure(@NonNull Call call, @NonNull IOException e) {
                mOnListener.onError("获取用户信息网络请求出错~");
            }

            @Override
            public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
                ResponseBody mBean = response.body();
                if (mBean != null){
                    String res = mBean.string();//请求成功时返回的东西
                    WxQBean mData = new Gson().fromJson(res,WxQBean.class);
                    mOnListener.onUSuccess(mData);
                }
            }
        });
    }


    @Override
    public void onAuthGotQrcode(String s, byte[] bytes) {
        //获取二维码图片。并显示出来,用户扫码二维码之后从回调(onAuthFinish)显示
        Bitmap bmp = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
        mOnListener.onQSuccess(bmp);
    }

    @Override
    public void onQrcodeScanned() {
    }

    @Override
    public void onAuthFinish(OAuthErrCode oAuthErrCode, String s) {
        //用户授权成功之后可以从这里拿到数据,或者错误信息
        //获取用户信息 第五步
        getUserData(s);
    }


    public interface OnMListener{
        void onQSuccess(Bitmap b); //获取二维码成功
        void onUSuccess(WxQBean b); //获取用户信息成功
        void onError(String msg); //失败
    }

    private static OnMListener mOnListener;


    //相关数据
    public static class WxQBean {
        private String access_token;
        private int expires_in;
        private String refresh_token;
        private String openid;
        private String scope;
        private String unionid;
        private String nickname;
        private int sex;
        private String language;
        private String city;
        private String province;
        private String country;
        private String headimgurl;
        private List<String> privilege;
        private int errcode;
        private String errmsg;
        private String ticket;

        public String getAccess_token() {
            return access_token;
        }

        public void setAccess_token(String access_token) {
            this.access_token = access_token;
        }

        public int getExpires_in() {
            return expires_in;
        }

        public void setExpires_in(int expires_in) {
            this.expires_in = expires_in;
        }

        public String getRefresh_token() {
            return refresh_token;
        }

        public void setRefresh_token(String refresh_token) {
            this.refresh_token = refresh_token;
        }

        public String getOpenid() {
            return openid;
        }

        public void setOpenid(String openid) {
            this.openid = openid;
        }

        public String getScope() {
            return scope;
        }

        public void setScope(String scope) {
            this.scope = scope;
        }

        public String getUnionid() {
            return unionid;
        }

        public void setUnionid(String unionid) {
            this.unionid = unionid;
        }

        public String getNickname() {
            return nickname;
        }

        public void setNickname(String nickname) {
            this.nickname = nickname;
        }

        public int getSex() {
            return sex;
        }

        public void setSex(int sex) {
            this.sex = sex;
        }

        public String getLanguage() {
            return language;
        }

        public void setLanguage(String language) {
            this.language = language;
        }

        public String getCity() {
            return city;
        }

        public void setCity(String city) {
            this.city = city;
        }

        public String getProvince() {
            return province;
        }

        public void setProvince(String province) {
            this.province = province;
        }

        public String getCountry() {
            return country;
        }

        public void setCountry(String country) {
            this.country = country;
        }

        public String getHeadimgurl() {
            return headimgurl;
        }

        public void setHeadimgurl(String headimgurl) {
            this.headimgurl = headimgurl;
        }

        public List<String> getPrivilege() {
            return privilege;
        }

        public void setPrivilege(List<String> privilege) {
            this.privilege = privilege;
        }

        public int getErrcode() {
            return errcode;
        }

        public void setErrcode(int errcode) {
            this.errcode = errcode;
        }

        public String getErrmsg() {
            return errmsg;
        }

        public void setErrmsg(String errmsg) {
            this.errmsg = errmsg;
        }

        public String getTicket() {
            return ticket;
        }

        public void setTicket(String ticket) {
            this.ticket = ticket;
        }

    }


    //工具
    private static class EncryptUtils {

        public static String getSHA(String info) {
            byte[] digesta = null;
            try {
                // 得到一个SHA-1的消息摘要
                MessageDigest alga = MessageDigest.getInstance("SHA-1");
                // 添加要进行计算摘要的信息
                alga.update(info.getBytes());
                // 得到该摘要
                digesta = alga.digest();
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
            // 将摘要转为字符串
            String rs = byte2hex(digesta);
            return rs;
        }

        private static String byte2hex(byte[] b) {
            String hs = "";
            String stmp = "";
            for (byte aB : b) {
                stmp = (Integer.toHexString(aB & 0XFF));
                if (stmp.length() == 1) {
                    hs = hs + "0" + stmp;
                } else {
                    hs = hs + stmp;
                }
            }
            return hs;
        }
    }
}

Supongo que te gusta

Origin blog.csdn.net/As_thin/article/details/131984390
Recomendado
Clasificación