Face à de nouveaux besoins, nous devons créer une fonction de connexion par code scan WeChat. Cet article est écrit en même temps que mon processus de codage. J'espère qu'il pourra aider les personnes dans le besoin et moi-même qui utiliserons à nouveau cette fonction à l'avenir.
La première chose qui me vient à l'esprit, ce sont les différents articles de Baidu. Bien sûr, il est indispensable de se rendre sur la plateforme développeur pour demander un AppID et une clé. Après l'inscription, vous constaterez qu'il vous faut créer une application et la consulter (officiel site Web, organigramme et autres informations), en pensant d'abord à en écrire une. La démo est en cours de développement, cela n'a pas besoin d'être si compliqué,
Grâce à un article, j'ai découvert que WeChat avait toujours un compte de test -> Le processus de fonctionnement détaillé de connexion au code de numérisation WeChat (développement de la plate-forme publique WeChat)
n'est pas dans mon cœur, j'ai écrit la logique selon les articles relativement clairs existants -> Développement Android Android Connexion par code QR à numérisation tierce WeChat intégrée - détails super invincibles
Après avoir entré l'AppID et la clé de test pour lesquels j'ai postulé, je ne peux pas accéder à la méthode onAuthGotQrcode lorsque je rappelle. Voir oauth.auth() pour obtenir la méthode du code QR et renvoyer True, et accéder directement à la méthode onAuthFinish. À l'intérieur, ce n'est pas ridicule, l'AppID et la clé sont demandés, la logique du code fait également référence à de nombreux articles, il n'y a aucun problème en théorie, et la méthode d'acquisition renvoie également True, mais l'erreur suivante est signalée à chaque fois - >
E/MicroMsg.SDK.GetQRCodeResult : resp errcode = -21
E/MicroMsg.SDK.GetQRCodeTask : onPostExecute, échec de l'obtention du qrcode, OAuthErrCode = OAuthErrCode : -1
Si vous rencontrez un problème, vous pouvez le résoudre. Allez dans le document pour trouver le code d'erreur -21 -1. Je ne le trouve pas, mmp, allez sur Baidu pour ce genre d'erreur, j'ai trouvé que beaucoup de gens l'ont rencontré , et aucun d'entre eux n'a donné de solution, mais il y a un article L'erreur est similaire à la mienne, et la solution est également donnée ->
Android obtient le code QR WeChat DiffDevOAuth.auth
Effectivement, il n'y a pas de solution. Le document indique également que les lettres majuscules et minuscules du champ sont erronées et que le nom du paramètre est erroné. Je les ai vérifiés, mais l'erreur montre que l'acquisition du QR Le code a échoué. Il existe de nombreuses raisons à l'échec. Peut-être que nous ne sommes pas causés par le même problème.
Après une recherche approfondie sur Internet, j'ai trouvé un problème qui pourrait expliquer le passé. WeChat est divisé en plates-formes publiques et plates-formes ouvertes. Est-il possible que ce soit le problème, vous devez postuler pour l'application tôt ou tard, donc vous devrait postuler en premier, ici vous devez faire attention, si vous postulez, vous avez besoin d'informations sur l'entreprise (vous devrez peut-être payer des frais sur le compte de l'entreprise pour vérification), un site Web officiel sérieux, un organigramme de l'APP, Pour vous préparer à l'avance, puis attendez jusqu'à quelques jours jusqu'à ce que l'identité officielle et la clé soient publiées.
Après environ trois ou quatre jours, l'examen de la demande a réussi, mais pour demander une connexion WeChat, vous devez passer par une certification de qualification de développeur, les frais d'examen sont de 300 yuans et vous devez remplir diverses informations sur l'entreprise, la licence commerciale, code de crédit, etc.
La génération de la clé doit également être liée à la vérification du code scan WeChat de la carte bancaire de l'administrateur
Après environ quatre ou cinq jours, j'ai finalement obtenu l'AppID et le mot de passe, et j'ai également ouvert l'autorisation de connexion WeChat. Le moment excitant est arrivé. J'ai mis les données sérieuses dans la logique et le code QR s'affiche normalement ! Obtenir des données utilisateur est également normal !
Résumé :
L'AppID et la clé de test appliqués par la plate-forme publique WeChat ne peuvent pas être utilisés pour des opérations sur la plate-forme ouverte WeChat, telles que la connexion au code de numérisation de l'APP, le paiement, etc.
Ensuite, je publierai mon code source (mon code suivant fonctionne normalement, si nécessaire, remplacez simplement appID et appsecret, et d'autres tests logiques sont disponibles), essayez d'écrire des commentaires détaillés ou utilisez le lien que j'ai posté ci-dessus OK
Les dépendances d’importation sont essentielles
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:+'
utiliser
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 peut être directement copié et utilisé par la méthode ci-dessus
/**
* 微信扫码登录,工具类
* */
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×tamp=%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;
}
}
}