DCloud_UNI_CHB
DCloud_UNI_CHB
  • 发布:2016-06-07 10:14
  • 更新:2 天前
  • 阅读:9819

监听短信验证码并自动提交表单

分类:Native.js

目前很多App都选择使用手机号注册或手机号加动态验证码登录的方式,此时用户需要等待短信验证码,然后手动填写,再点击注册或登录按钮,完成注册登录操作。

本文介绍如何利用native.js,实现系统监听短信验证码并帮助用户自动填写验证码输入框,自动提交登录表单。

备注:目前仅支持Android平台

代码主要分为两个部分:

  • 标准短信监听部分
  • 个性短信内容及登录界面适配部分

标准短信监听部分
该部分为标准函数,开发者基本无需修改;

var callbacks = [];  
var receiver;  
var filter;  
var main;  
var isInit = false;  
var isRegistered = false;  
var isOlderVersion = false;  

//plusReady封装,若使用mui,可直接使用mui.plusReady()方法;  
var plusReady = function(){  
     if (window.plus) {  
        callback();  
    } else {  
        document.addEventListener("plusready", function() {  
            callback();  
        }, false);  
    }  
}  

/**  
* 初始化  
*/  
var init = function(callback) {  
    //仅支持Android版本  
    if (plus.os.name !== 'Android') {  
        return;  
    }  
    try {  
        var version = plus.runtime.innerVersion.split('.');  
        isOlderVersion = parseInt(version[version.length - 1]) < 22298;  
        main = plus.android.runtimeMainActivity();  
        var Intent = plus.android.importClass('android.content.Intent');  
        var IntentFilter = plus.android.importClass('android.content.IntentFilter');  
        var SmsMessage = plus.android.importClass('android.telephony.SmsMessage');  
        var receiverClass = 'io.dcloud.feature.internal.reflect.BroadcastReceiver';  
        if (isOlderVersion) {  
            receiverClass = 'io.dcloud.feature.internal.a.a';  
        }  
        filter = new IntentFilter();  
        var onReceiveCallback = function(context, intent) {  
            try {  
                var action = intent.getAction();  
                if (action == "android.provider.Telephony.SMS_RECEIVED") {  
                    var pdus = intent.getSerializableExtra("pdus");  
                    var msgs = [];  
                    for (var i = 0, len = pdus.length; i < len; i++) {  
                        msgs.push(SmsMessage.createFromPdu(pdus[i]));  
                    }  
                    for (var i = 0, len = callbacks.length; i < len; i++) {  
                        callbacks[i](msgs);  
                    }  
                }  
            } catch (e) {}  
        }  
        receiver = plus.android.implements(receiverClass, {  
            a: onReceiveCallback,  
            onReceive: onReceiveCallback  
        });  
        filter.addAction("android.provider.Telephony.SMS_RECEIVED");  
        callback && callback();  
    } catch (e) {}  
}  

//注册短信监听  
var register = function(callback) {  
    callbacks.push(callback);  
    if (!isInit) {  
        isInit = isRegistered = true;  
        plusReady(function() {  
            init(function() {  
                setTimeout(function() {  
                    //                  console.log('registerReceiver');  
                    try {  
                        if (isOlderVersion) {  
                            main.a(receiver, filter);  
                        } else {  
                            main.registerReceiver(receiver, filter); //注册监听  
                        }  
                    } catch (e) {}  
                }, 300);  
            });  
        });  
    } else if (!isRegistered) {  
        //      console.log('registerReceiver');  
        try {  
            if (isOlderVersion) {  
                main.a(receiver, filter);  
            } else {  
                main.registerReceiver(receiver, filter); //注册监听  
            }  
        } catch (e) {}  
    }  
};  
//注销监听,在登录成功或从登录页跳转到其它页面后调用  
var unregister = function(callback, remove) {  
    for (var i = 0, len = callbacks.length; i < len; i++) {  
        if (callbacks[i] === callback) {  
            callbacks.splice(i, 1);  
        }  
    }  
    if (remove && !callbacks.length) {  
        if (main && isRegistered) {  
            try {  
                if (isOlderVersion) {  
                    main.a(receiver);  
                } else {  
                    main.unregisterReceiver(receiver);  
                }  
            } catch (e) {}  
            isRegistered = false;  
            //          console.log('unregisterReceiver');  
        }  
    }  
};  

个性短信内容及登录界面适配部分
这部分开发者需要根据具体App或登录页面,修改短信匹配内容和验证码输入框选择器,参考如下注释

//验证码匹配规则,需要根据实际站点匹配  
var codeRegex = /[0-9]{6}/g;  

var handleSMS = function(msgs) {  
    for (var i = 0, len = msgs.length; i < len; i++) {  
        var content = msgs[i].getDisplayMessageBody();  
        //匹配短信内容,若短信内容包含“XX网”,则认为初步匹配成功  
        if (~content.indexOf('XX网')) {  
            //匹配验证码规则,比如包含6位数字  
            var matches = content.match(codeRegex);  
            if (matches && matches.length) {  
                var code = matches[0];  
                //验证码输入框控件,需根据实际页面修改选择器  
                var codeElem = document.querySelector('.login-view form input[type="password"]');  
                if (codeElem) {  
                    codeElem.value = code;  

                    //TODO 这里可以取消短信监听  

                    //模拟表单提交,需根据实际页面修改选择器  
                    document.querySelector('.login-view form button[type="submit"]').click();  
                    plus.nativeUI.toast('获取短信验证码成功,自动登录..');  

                }  
                break;  
            }  
        }  
    }  
};  

//登录页面注册短信监听事件  
register(handleSMS);  
15 关注 分享
赵梦欢 明峰 埃文 smileboyi wfc1870 草原狼 1046545451@qq.com 2523732076@qq.com 帅帅的让我疯狂 DCloud_UNI_Trust lhyh 菜鸡 水灵退散 潇洒哥gg 老哥教教我

要回复文章请先登录注册

347900574@qq.com

347900574@qq.com

回复 xiaoqianYang: 方法可以。第四点会遇到一个小坑,小米5s 手机上。就是只开启短信读取还不行,后来加上了彩信的读取才OK。其它手机没试过。
2 天前
347900574@qq.com

347900574@qq.com

回复 博博科技: 这个不用下载的,创建mui 项目里会自带。
2 天前
博博科技

博博科技

回复 xiaoqianYang: 请问common.js 在哪下载?
2019-03-15 21:21
281768790@qq.com

281768790@qq.com

这个可以读取得到发送短信的人的号码吗?
2019-01-28 16:16
xiaoqianYang

xiaoqianYang

1、页面引入common.js 2、在plusReady的function中加入参数callback; 3、在给app添加模块<uses-permission android:name=\"android.permission.READ_SMS\"/> 4、把自己的手机短信设置为允许第三方应用读取
2018-10-29 17:39
yesterdream

yesterdream

回复 lcc.c@qq.com: 问下调试你直接用这个代码就可以了么?我的onReceiveCallback 一直执行不了。。好头大
2018-08-29 15:10
lcc.c@qq.com

lcc.c@qq.com

2018.8.23测试,开发真机调试没问题,云打包apk安装就不行了
尝试以下方法:
1.系统设置中短彩权限也给了
2.打包时设置<uses-permission android:name=\"android.permission.READ_SMS\"/>

依然不行
2018-08-23 19:41
15198039147@163.com

15198039147@163.com

请问要怎样做才能支持ios呢
2018-07-27 15:08
菜鸡

菜鸡

厉害了~给你点个赞~
2017-12-07 09:23
1149143846@qq.com

1149143846@qq.com

报错 callback 找不到的话,加参数就可以了。
2017-12-01 11:52
ladesign

ladesign

mark
2017-09-20 14:57
逸风

逸风

mak 留用
2017-02-10 16:24
Element

Element

2333
2017-01-13 09:21
1245241215@qq.com

1245241215@qq.com

问题解决,native所有权限给上可以了
2016-12-19 15:06
1245241215@qq.com

1245241215@qq.com

回复 running: 请问您打包成APK在手机上可以运行吗?我的打包出来进不了onReceiveCallback这个函数
2016-12-19 13:08
1245241215@qq.com

1245241215@qq.com

手机插上USB真机运行的时候在Hbuilder这个软件里可以获取到验证码,进入了onReceiveCallback这个函数,但是打包成apk他就不行了,程序进不了onReceiveCallback这个函数这个函数,请问一下为什么,权限什么的都给了。
2016-12-19 13:06
278996335@qq.com

278996335@qq.com

为什么只支持Android???这个代码在ios上能用么?
2016-11-23 20:18
淡忘

淡忘

我这 也是 onReceiveCallback 没有执行 能回复下吗
2016-11-09 09:54
草原狼

草原狼

这个代码在ios上能用么?
2016-10-30 17:41
草原狼

草原狼

我把你的代码给复制粘贴了一下 报错 callback 找不到,你不是说这部分不用改么?能不能封装的彻底点,引入一个文件,就可以直接使用。只留一个register ,unregister ,
2016-10-28 16:42
lifeworld

lifeworld

onReceiveCallback 没有执行到是什么原因呢
2016-08-29 11:51
running

running

回复 DCloud_UNI_CHB: 问题解决,是要加这么一个权限 "<uses-permission android:name=\"android.permission.READ_SMS\"/>"
2016-07-26 16:05
我的一沓

我的一沓

回复 我的一沓: 测试时应用并没有请求相关权限(比如读取短信),所以以为是已经有了该权限,后来手动赋予了读取短信权限,可以监听了
2016-07-07 18:30
我的一沓

我的一沓

var plusReady = function(){
原来是这里忘记参数callback了,怪不得没注册成功。
但重点是,无论是真机测试还是云打包,都没有任何反应啊,当然我只是在一台手机(系统MIUI 8)上测试过。关于SMS的权限都给了,后来甚至把全部权限都给了,还是没效果。
2016-07-07 11:19
DCloud_UNI_CHB

DCloud_UNI_CHB (作者)

回复 running: Native.js权限也分配了吧?
2016-07-05 18:32
running

running

有问题,发现在开发时直接usb安装是可以的,云打包成apk就不行了,无效;短彩权限也给了
2016-07-04 14:22