├── .gitignore ├── LICENSE ├── README.md ├── demo └── index.html ├── doc └── API.md ├── ionic ├── example │ ├── app │ │ ├── app.component.ts │ │ ├── app.html │ │ ├── app.module.ts │ │ ├── app.scss │ │ └── main.ts │ ├── assets │ │ ├── icon │ │ │ └── favicon.ico │ │ └── imgs │ │ │ └── logo.png │ ├── index.html │ ├── manifest.json │ ├── pages │ │ └── home │ │ │ ├── home.html │ │ │ ├── home.scss │ │ │ └── home.ts │ ├── service-worker.js │ └── theme │ │ └── variables.scss ├── index.ts └── jsms │ ├── index.d.ts │ ├── index.js │ ├── index.js.map │ ├── index.metadata.json │ └── package.json ├── package.json ├── plugin.xml ├── src ├── android │ ├── JSMSPlugin.java │ └── jsms_android-1.2.2.jar └── ios │ ├── JSMSConfig.plist │ ├── JsmsSDK │ ├── include │ │ ├── JSMSConstant.h │ │ └── JSMSSDK.h │ └── libsms-lib.a │ └── Plugins │ ├── JSMSPlugin.h │ └── JSMSPlugin.m └── www └── JSMSPlugin.js /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/android,objective-c,apachecordova 3 | 4 | ### Android ### 5 | # Built application files 6 | *.apk 7 | *.ap_ 8 | 9 | # Files for the ART/Dalvik VM 10 | *.dex 11 | 12 | # Java class files 13 | *.class 14 | 15 | # Generated files 16 | bin/ 17 | gen/ 18 | out/ 19 | 20 | # Gradle files 21 | .gradle/ 22 | build/ 23 | 24 | # Local configuration file (sdk path, etc) 25 | local.properties 26 | 27 | # Proguard folder generated by Eclipse 28 | proguard/ 29 | 30 | # Log Files 31 | *.log 32 | 33 | # Android Studio Navigation editor temp files 34 | .navigation/ 35 | 36 | # Android Studio captures folder 37 | captures/ 38 | 39 | # Intellij 40 | *.iml 41 | .idea/workspace.xml 42 | .idea/tasks.xml 43 | .idea/gradle.xml 44 | .idea/dictionaries 45 | .idea/libraries 46 | 47 | # Keystore files 48 | *.jks 49 | 50 | # External native build folder generated in Android Studio 2.2 and later 51 | .externalNativeBuild 52 | 53 | # Google Services (e.g. APIs or Firebase) 54 | google-services.json 55 | 56 | # Freeline 57 | freeline.py 58 | freeline/ 59 | freeline_project_description.json 60 | 61 | ### Android Patch ### 62 | gen-external-apklibs 63 | 64 | ### ApacheCordova ### 65 | # Apache Cordova generated files and directories 66 | bin/* 67 | !/plugins 68 | !/plugins/android.json 69 | !/plugins/fetch.json 70 | plugins/* 71 | platforms/* 72 | 73 | ### Objective-C ### 74 | # Xcode 75 | # 76 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 77 | 78 | ## Build generated 79 | DerivedData/ 80 | 81 | ## Various settings 82 | *.pbxuser 83 | !default.pbxuser 84 | *.mode1v3 85 | !default.mode1v3 86 | *.mode2v3 87 | !default.mode2v3 88 | *.perspectivev3 89 | !default.perspectivev3 90 | xcuserdata/ 91 | 92 | ## Other 93 | *.moved-aside 94 | *.xccheckout 95 | *.xcscmblueprint 96 | 97 | ## Obj-C/Swift specific 98 | *.hmap 99 | *.ipa 100 | *.dSYM.zip 101 | *.dSYM 102 | 103 | # CocoaPods 104 | # 105 | # We recommend against adding the Pods directory to your .gitignore. However 106 | # you should judge for yourself, the pros and cons are mentioned at: 107 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 108 | # 109 | # Pods/ 110 | 111 | # Carthage 112 | # 113 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 114 | # Carthage/Checkouts 115 | 116 | Carthage/Build 117 | 118 | # fastlane 119 | # 120 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 121 | # screenshots whenever they are needed. 122 | # For more information about the recommended setup visit: 123 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 124 | 125 | fastlane/report.xml 126 | fastlane/Preview.html 127 | fastlane/screenshots 128 | fastlane/test_output 129 | 130 | # Code Injection 131 | # 132 | # After new code Injection tools there's a generated folder /iOSInjectionProject 133 | # https://github.com/johnno1962/injectionforxcode 134 | 135 | iOSInjectionProject/ 136 | 137 | ### Objective-C Patch ### 138 | 139 | # End of https://www.gitignore.io/api/android,objective-c,apachecordova 140 | 141 | src/android/\.DS_Store 142 | 143 | \.DS_Store 144 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 极光开发者 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cordova-plugin-jsms 2 | 3 | [![release](https://img.shields.io/badge/release-1.2.0-blue.svg)](https://github.com/jpush/cordova-plugin-jsms/releases) 4 | [![platforms](https://img.shields.io/badge/platforms-iOS%7CAndroid-lightgrey.svg)](https://github.com/jpush/cordova-plugin-jsms) 5 | [![weibo](https://img.shields.io/badge/weibo-JPush-blue.svg)](http://weibo.com/jpush?refer_flag=1001030101_&is_all=1) 6 | 7 | 极光官方支持的 Cordova 短信验证码插件,支持 Android 和 iOS 平台。 8 | 9 | > 目前不提供免费使用,有意可联系官方[商务客服](https://www.jiguang.cn/sms)。 10 | 11 | 注意:从 v1.2.0 开始支持 cordova-android v7.0.0+ 和 ionic-native。因 cordova-android 从 v7.0.0 开始修改了项目结构,因此不兼容旧版本,升级时请注意。 12 | 13 | ## Install 14 | 15 | ```shell 16 | cordova plugin add cordova-plugin-jsms --variable APP_KEY=Your_App_KEY 17 | ``` 18 | 19 | 或 20 | 21 | ```shell 22 | cordova plugin add https://github.com/jpush/cordova-plugin-jsms.git --variable APP_KEY=Your_App_Key 23 | ``` 24 | 25 | 或下载到本地: 26 | 27 | ```shell 28 | cordova plugin add --variable APP_KEY=Your_App_Key 29 | ``` 30 | 31 | > [这里](http://docs.jiguang.cn/guideline/statistical_report/)了解如何获得 AppKey。 32 | 33 | 如果使用了 ionic,可以通过 npm 安装 @jiguang-ionic/jsms 适配 ionic-native。 34 | 35 | ```shell 36 | npm install --save @jiguang-ionic/jsms 37 | ``` 38 | 39 | 然后在 *app.module.ts* 中增加: 40 | 41 | ```js 42 | import { JSMS } from '@jiguang-ionic/jsms'; 43 | ... 44 | providers: [ 45 | ... 46 | JSMS, 47 | ... 48 | ] 49 | ``` 50 | 51 | 具体可参考 ./ionic/example 中的文件。 52 | 53 | ## API 54 | 55 | [API 文档](/doc/API.md) 56 | 57 | ## Support 58 | 59 | - [官网文档](http://docs.jiguang.cn/guideline/JSMS_guide/) 60 | - [极光社区](http://community.jiguang.cn/) 61 | 62 | ## Contribute 63 | 64 | Please contribute! [Look at the issues](https://github.com/jpush/cordova-plugin-jsms/issues). 65 | 66 | ## License 67 | 68 | MIT © [JiGuang](/LICENSE) 69 | -------------------------------------------------------------------------------- /demo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | JSMS PhoneGap Demo 6 | 7 | 8 | 11 | 12 | 13 | 59 | 60 | 61 | 62 | 68 |
69 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /doc/API.md: -------------------------------------------------------------------------------- 1 | # API 文档 2 | 3 | - [init](#init) 4 | - [setDebugMode](#setdebugmodeenable-boolean-success-function-error-function) 5 | - [getSmsCode](#getsmscodephonenumber-string-tempid-string-success-function-error-function) 6 | - [getVoiceCode](#getvoicecodephonenumber-string-languagecode-number-success-function-error-function) 7 | - [checkSmsCode](#checksmscodephonenumer-string-code-string-success-function-error-function) 8 | - [setIntervalTime](#setintervaltimeintervaltime-number-success-function-error-function) 9 | - [getIntervalTime](#getintervaltimesuccess-function) 10 | 11 | ## init() 12 | 13 | 初始化 JSMS SDK。 14 | 15 | ### 代码示例 16 | 17 | ```js 18 | window.jsms.init(); 19 | ``` 20 | 21 | ## setDebugMode(enable: boolean, success: function, error: function) 22 | 23 | (Android only)开启 debug 模式,将会打印 JSMS SDK 的相关日志。 24 | 25 | ### 参数说明 26 | 27 | - enable: 28 | - true: 开启; 29 | - false: 关闭。 30 | - success: 成功回调。 31 | - error: 错误回调。该 API 中仅当传入参数类型错误时报错。 32 | 33 | ### 代码示例 34 | 35 | ```js 36 | window.jsms.setDebugMode(true, () => { // success 37 | // do something. 38 | }, error => { 39 | let code = error.code 40 | let desc = error.description 41 | }); 42 | ``` 43 | 44 | ## getSmsCode(phoneNumber: string, tempId: string, success: function, error: function) 45 | 46 | 获取短信验证码。 47 | 48 | ### 参数说明 49 | 50 | - phoneNumber: 手机号码。目前仅支持国内号码。 51 | - tempId: 短信模板 id。可通过极光控制台进行管理。 52 | - success: 成功回调。 53 | - error: 错误回调。 54 | 55 | ### 代码示例 56 | 57 | ```js 58 | window.jsms.getSmsCode('18600001111', '1', () => { 59 | // do something. 60 | }, error => { 61 | let code = error.code 62 | let desc = error.description 63 | }) 64 | ``` 65 | 66 | ## getVoiceCode(phoneNumber: string, languageCode: number, success: function, error: function) 67 | 68 | 获取语音验证码。 69 | 70 | ### 参数说明 71 | 72 | - phoneNumber: 手机号码。目前仅支持国内号码。 73 | - languageCode: 指定语音验证码所用的语言。0:中文;1:英文。 74 | - success: 成功回调。 75 | - error: 错误回调。 76 | 77 | ### 代码示例 78 | 79 | ```js 80 | window.jsms.getVoiceCode('18600001111', 0, () => { 81 | // do something. 82 | }, error => { 83 | let code = error.code 84 | let desc = error.description 85 | }) 86 | ``` 87 | 88 | ## checkSmsCode(phoneNumer: string, code: string, success: function: error: function) 89 | 90 | 校验验证码是否正确。 91 | 92 | ### 参数说明 93 | 94 | - phoneNumber: 手机号码。目前仅支持国内号码。 95 | - code: 待校验的验证码。 96 | - success: 成功回调。 97 | - error: 错误回调。 98 | 99 | ### 代码示例 100 | 101 | ```js 102 | window.jsms.checkSmsCode('18600001111', '510002', () => { 103 | // 验证码正确。 104 | }, error => { 105 | let code = error.code 106 | let desc = error.description 107 | }) 108 | ``` 109 | 110 | ## setIntervalTime(intervalTime: number, success: function, error: function) 111 | 112 | 设置前后两次获取验证码的时间间隔,默认为 30 秒。 113 | 114 | ### 参数说明 115 | 116 | - intervalTime: 间隔时间,单位秒。 117 | - success: 成功回调。 118 | - error: 错误回调。 119 | 120 | ### 代码示例 121 | 122 | ```js 123 | window.jsms.setIntervalTime(60, () => { 124 | // success. 125 | }, error => { 126 | let code = error.code 127 | let desc = error.description 128 | }) 129 | ``` 130 | 131 | ## getIntervalTime(success: function) 132 | 133 | (Android only)获得当前设置的获取验证码时间间隔。 134 | 135 | ### 参数说明 136 | 137 | - success:成功回调。以参数形式返回时间间隔,单位秒。 138 | 139 | ### 代码示例 140 | 141 | ```js 142 | window.jsms.getIntervalTime(intervalTime => { 143 | // do something. 144 | }) 145 | ``` 146 | -------------------------------------------------------------------------------- /ionic/example/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { Platform } from 'ionic-angular'; 3 | import { StatusBar } from '@ionic-native/status-bar'; 4 | import { SplashScreen } from '@ionic-native/splash-screen'; 5 | import { JSMS } from '@jiguang-ionic/jsms' 6 | 7 | import { HomePage } from '../pages/home/home'; 8 | @Component({ 9 | templateUrl: 'app.html' 10 | }) 11 | export class MyApp { 12 | rootPage:any = HomePage; 13 | 14 | constructor(platform: Platform, statusBar: StatusBar, splashScreen: SplashScreen, jsms: JSMS) { 15 | platform.ready().then(() => { 16 | // Okay, so the platform is ready and our plugins are available. 17 | // Here you can do any higher level native things you might need. 18 | statusBar.styleDefault(); 19 | splashScreen.hide(); 20 | 21 | jsms.init(); 22 | jsms.setDebugMode(true); 23 | }); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /ionic/example/app/app.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ionic/example/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { BrowserModule } from '@angular/platform-browser'; 2 | import { ErrorHandler, NgModule } from '@angular/core'; 3 | import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular'; 4 | import { SplashScreen } from '@ionic-native/splash-screen'; 5 | import { StatusBar } from '@ionic-native/status-bar'; 6 | import { JSMS } from '@jiguang-ionic/jsms' 7 | 8 | import { MyApp } from './app.component'; 9 | import { HomePage } from '../pages/home/home'; 10 | 11 | @NgModule({ 12 | declarations: [ 13 | MyApp, 14 | HomePage 15 | ], 16 | imports: [ 17 | BrowserModule, 18 | IonicModule.forRoot(MyApp) 19 | ], 20 | bootstrap: [IonicApp], 21 | entryComponents: [ 22 | MyApp, 23 | HomePage 24 | ], 25 | providers: [ 26 | StatusBar, 27 | SplashScreen, 28 | JSMS, 29 | {provide: ErrorHandler, useClass: IonicErrorHandler} 30 | ] 31 | }) 32 | export class AppModule {} 33 | -------------------------------------------------------------------------------- /ionic/example/app/app.scss: -------------------------------------------------------------------------------- 1 | // http://ionicframework.com/docs/theming/ 2 | 3 | 4 | // App Global Sass 5 | // -------------------------------------------------- 6 | // Put style rules here that you want to apply globally. These 7 | // styles are for the entire app and not just one component. 8 | // Additionally, this file can be also used as an entry point 9 | // to import other Sass files to be included in the output CSS. 10 | // 11 | // Shared Sass variables, which can be used to adjust Ionic's 12 | // default Sass variables, belong in "theme/variables.scss". 13 | // 14 | // To declare rules for a specific mode, create a child rule 15 | // for the .md, .ios, or .wp mode classes. The mode class is 16 | // automatically applied to the element in the app. 17 | -------------------------------------------------------------------------------- /ionic/example/app/main.ts: -------------------------------------------------------------------------------- 1 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 2 | 3 | import { AppModule } from './app.module'; 4 | 5 | platformBrowserDynamic().bootstrapModule(AppModule); 6 | -------------------------------------------------------------------------------- /ionic/example/assets/icon/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jpush/cordova-plugin-jsms/0c065fc1d10ddda651bef9e4ed79950a68d56284/ionic/example/assets/icon/favicon.ico -------------------------------------------------------------------------------- /ionic/example/assets/imgs/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jpush/cordova-plugin-jsms/0c065fc1d10ddda651bef9e4ed79950a68d56284/ionic/example/assets/imgs/logo.png -------------------------------------------------------------------------------- /ionic/example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Ionic App 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /ionic/example/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Ionic", 3 | "short_name": "Ionic", 4 | "start_url": "index.html", 5 | "display": "standalone", 6 | "icons": [{ 7 | "src": "assets/imgs/logo.png", 8 | "sizes": "512x512", 9 | "type": "image/png" 10 | }], 11 | "background_color": "#4e8ef7", 12 | "theme_color": "#4e8ef7" 13 | } -------------------------------------------------------------------------------- /ionic/example/pages/home/home.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | JSMS Ionic Example 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | {{timer + 's'}} 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /ionic/example/pages/home/home.scss: -------------------------------------------------------------------------------- 1 | page-home { 2 | 3 | } 4 | -------------------------------------------------------------------------------- /ionic/example/pages/home/home.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { NavController, AlertController } from 'ionic-angular'; 3 | import { JSMS } from '@jiguang-ionic/jsms' 4 | 5 | @Component({ 6 | selector: 'page-home', 7 | templateUrl: 'home.html' 8 | }) 9 | 10 | export class HomePage { 11 | 12 | private timer = 30; 13 | private intervalId: number; 14 | 15 | constructor(public navCtrl: NavController, private alertCtrl: AlertController, private jsms: JSMS) { 16 | 17 | } 18 | 19 | /** 20 | * 获取短信验证码。 21 | */ 22 | getSmsCode(phoneNum: string) { 23 | if (!phoneNum) { 24 | this.alertCtrl.create({ 25 | subTitle: '手机号不能为空', 26 | buttons: ['OK'] 27 | }).present(); 28 | return; 29 | } 30 | 31 | this.jsms.getSmsCode(phoneNum, '1') // 这里设置短信内容模板为 '1'。 32 | .then(() => { 33 | this.alertCtrl.create({ 34 | subTitle: '短信验证码已发送', 35 | buttons: ['OK'] 36 | }).present(); 37 | 38 | this.intervalId = setInterval(() => { 39 | this.timer--; 40 | if (this.timer == 0) { 41 | clearInterval(this.intervalId); 42 | this.timer = 30; 43 | } 44 | }, 1000); 45 | }).catch(err => { 46 | alert(err.code + ': ' + err.description); 47 | }); 48 | } 49 | 50 | getVoiceCode(phoneNum: string) { 51 | if (!phoneNum) { 52 | this.alertCtrl.create({ 53 | subTitle: '手机号不能为空', 54 | buttons: ['OK'] 55 | }).present(); 56 | return; 57 | } 58 | 59 | this.jsms.getVoiceCode(phoneNum, 0) 60 | .then(() => { 61 | this.alertCtrl.create({ 62 | subTitle: '语音验证码已发送', 63 | buttons: ['OK'] 64 | }).present(); 65 | 66 | this.intervalId = setInterval(() => { 67 | this.timer--; 68 | if (this.timer == 0) { 69 | clearInterval(this.intervalId); 70 | this.timer = 30; 71 | } 72 | }, 1000); 73 | }).catch(err => { 74 | alert(err.code + ': ' + err.description); 75 | }); 76 | } 77 | 78 | checkCode(phoneNum: string, code: string) { 79 | if (!phoneNum) { // 这里只做简单的校验。 80 | this.alertCtrl.create({ 81 | subTitle: '手机号不能为空', 82 | buttons: ['OK'] 83 | }).present(); 84 | return; 85 | } 86 | 87 | if (!code) { 88 | this.alertCtrl.create({ 89 | subTitle: '验证码不能为空', 90 | buttons: ['OK'] 91 | }).present(); 92 | return; 93 | } 94 | 95 | this.jsms.checkSmsCode(phoneNum, code) 96 | .then(() => { 97 | this.alertCtrl.create({ 98 | subTitle: '正确', 99 | buttons: ['OK'] 100 | }).present(); 101 | 102 | clearInterval(this.intervalId); 103 | this.timer = 30; // 将倒计时重新置为 30s。 104 | }).catch(err => { 105 | alert(err.code + ': ' + err.description); 106 | }); 107 | } 108 | 109 | } 110 | -------------------------------------------------------------------------------- /ionic/example/service-worker.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Check out https://googlechromelabs.github.io/sw-toolbox/ for 3 | * more info on how to use sw-toolbox to custom configure your service worker. 4 | */ 5 | 6 | 7 | 'use strict'; 8 | importScripts('./build/sw-toolbox.js'); 9 | 10 | self.toolbox.options.cache = { 11 | name: 'ionic-cache' 12 | }; 13 | 14 | // pre-cache our key assets 15 | self.toolbox.precache( 16 | [ 17 | './build/main.js', 18 | './build/vendor.js', 19 | './build/main.css', 20 | './build/polyfills.js', 21 | 'index.html', 22 | 'manifest.json' 23 | ] 24 | ); 25 | 26 | // dynamically cache any other local assets 27 | self.toolbox.router.any('/*', self.toolbox.fastest); 28 | 29 | // for any other requests go to the network, cache, 30 | // and then only use that cached resource if your user goes offline 31 | self.toolbox.router.default = self.toolbox.networkFirst; 32 | -------------------------------------------------------------------------------- /ionic/example/theme/variables.scss: -------------------------------------------------------------------------------- 1 | // Ionic Variables and Theming. For more info, please see: 2 | // http://ionicframework.com/docs/theming/ 3 | 4 | // Font path is used to include ionicons, 5 | // roboto, and noto sans fonts 6 | $font-path: "../assets/fonts"; 7 | 8 | 9 | // The app direction is used to include 10 | // rtl styles in your app. For more info, please see: 11 | // http://ionicframework.com/docs/theming/rtl-support/ 12 | $app-direction: ltr; 13 | 14 | 15 | @import "ionic.globals"; 16 | 17 | 18 | // Shared Variables 19 | // -------------------------------------------------- 20 | // To customize the look and feel of this app, you can override 21 | // the Sass variables found in Ionic's source scss files. 22 | // To view all the possible Ionic variables, see: 23 | // http://ionicframework.com/docs/theming/overriding-ionic-variables/ 24 | 25 | 26 | 27 | 28 | // Named Color Variables 29 | // -------------------------------------------------- 30 | // Named colors makes it easy to reuse colors on various components. 31 | // It's highly recommended to change the default colors 32 | // to match your app's branding. Ionic uses a Sass map of 33 | // colors so you can add, rename and remove colors as needed. 34 | // The "primary" color is the only required color in the map. 35 | 36 | $colors: ( 37 | primary: #488aff, 38 | secondary: #32db64, 39 | danger: #f53d3d, 40 | light: #f4f4f4, 41 | dark: #222 42 | ); 43 | 44 | 45 | // App iOS Variables 46 | // -------------------------------------------------- 47 | // iOS only Sass variables can go here 48 | 49 | 50 | 51 | 52 | // App Material Design Variables 53 | // -------------------------------------------------- 54 | // Material Design only Sass variables can go here 55 | 56 | 57 | 58 | 59 | // App Windows Variables 60 | // -------------------------------------------------- 61 | // Windows only Sass variables can go here 62 | 63 | 64 | 65 | 66 | // App Theme 67 | // -------------------------------------------------- 68 | // Ionic apps can have different themes applied, which can 69 | // then be future customized. This import comes last 70 | // so that the above variables are used and Ionic's 71 | // default are overridden. 72 | 73 | @import "ionic.theme.default"; 74 | 75 | 76 | // Ionicons 77 | // -------------------------------------------------- 78 | // The premium icon font for Ionic. For more info, please see: 79 | // http://ionicframework.com/docs/ionicons/ 80 | 81 | @import "ionic.ionicons"; 82 | 83 | 84 | // Fonts 85 | // -------------------------------------------------- 86 | 87 | @import "roboto"; 88 | @import "noto-sans"; 89 | -------------------------------------------------------------------------------- /ionic/index.ts: -------------------------------------------------------------------------------- 1 | import { Plugin, Cordova, IonicNativePlugin } from '@ionic-native/core'; 2 | import { Injectable } from '@angular/core'; 3 | 4 | @Plugin({ 5 | pluginName: 'JSMS', 6 | plugin: 'cordova-plugin-jsms', 7 | pluginRef: 'plugins.jsms', 8 | repo: 'https://github.com/jpush/cordova-plugin-jsms', 9 | install: 'ionic cordova plugin add cordova-plugin-jsms --variable APP_KEY=your_app_key', 10 | installVariables: ['APP_KEY'], 11 | platforms: ['Android', 'iOS'] 12 | }) 13 | @Injectable() 14 | export class JSMS extends IonicNativePlugin { 15 | 16 | @Cordova() 17 | init(): Promise { return; }; 18 | 19 | @Cordova() 20 | setDebugMode(enable: boolean): Promise { return; } 21 | 22 | /** 23 | * 请求短信验证码。 24 | * @param phoneNumber 要接收短信验证码的手机号码。 25 | * @param tempId 短信模板 id。 26 | */ 27 | @Cordova() 28 | getSmsCode(phoneNumber: string, tempId: string): Promise { return; } 29 | 30 | /** 31 | * 请求语音验证码。 32 | * @param phoneNumber 要接收语音验证码的手机号码。 33 | * @param {number} languageCode:(可选)语言选项。0: 中文;1: 英文;2: 中英混合(中英混合仅支持 Android)。如果不填默认为中文。 34 | */ 35 | @Cordova() 36 | getVoiceCode(phoneNumber: string, languageCode: number): Promise { return; } 37 | 38 | /** 39 | * 验证验证码。 40 | * @param phoneNumber 接收验证码的手机号码。 41 | * @param code 待验证的验证码。 42 | */ 43 | @Cordova() 44 | checkSmsCode(phoneNumber: string, code: string): Promise { return; } 45 | 46 | /** 47 | * 设置前后两次获取验证码的时间间隔,默认 30 秒。 48 | * @param intervalTime 间隔时间,单位秒。 49 | */ 50 | @Cordova() 51 | setIntervalTime(intervalTime: number): Promise { return; } 52 | 53 | /** 54 | * (Android only)获取设置的前后两次获取短信验证码的时间间隔。 55 | */ 56 | @Cordova() 57 | getIntervalTime(): Promise { return; } 58 | } 59 | -------------------------------------------------------------------------------- /ionic/jsms/index.d.ts: -------------------------------------------------------------------------------- 1 | import { IonicNativePlugin } from '@ionic-native/core'; 2 | export declare class JSMS extends IonicNativePlugin { 3 | init(): Promise; 4 | setDebugMode(enable: boolean): Promise; 5 | /** 6 | * 请求短信验证码。 7 | * @param phoneNumber 要接收短信验证码的手机号码。 8 | * @param tempId 短信模板 id。 9 | */ 10 | getSmsCode(phoneNumber: string, tempId: string): Promise; 11 | /** 12 | * 请求语音验证码。 13 | * @param phoneNumber 要接收语音验证码的手机号码。 14 | * @param {number} languageCode:(可选)语言选项。0: 中文;1: 英文;2: 中英混合(中英混合仅支持 Android)。如果不填默认为中文。 15 | */ 16 | getVoiceCode(phoneNumber: string, languageCode: number): Promise; 17 | /** 18 | * 验证验证码。 19 | * @param phoneNumber 接收验证码的手机号码。 20 | * @param code 待验证的验证码。 21 | */ 22 | checkSmsCode(phoneNumber: string, code: string): Promise; 23 | /** 24 | * 设置前后两次获取验证码的时间间隔,默认 30 秒。 25 | * @param intervalTime 间隔时间,单位秒。 26 | */ 27 | setIntervalTime(intervalTime: number): Promise; 28 | /** 29 | * (Android only)获取设置的前后两次获取短信验证码的时间间隔。 30 | */ 31 | getIntervalTime(): Promise; 32 | } 33 | -------------------------------------------------------------------------------- /ionic/jsms/index.js: -------------------------------------------------------------------------------- 1 | var __extends = (this && this.__extends) || (function () { 2 | var extendStatics = Object.setPrototypeOf || 3 | ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || 4 | function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; 5 | return function (d, b) { 6 | extendStatics(d, b); 7 | function __() { this.constructor = d; } 8 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); 9 | }; 10 | })(); 11 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 12 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 13 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 14 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 15 | return c > 3 && r && Object.defineProperty(target, key, r), r; 16 | }; 17 | var __metadata = (this && this.__metadata) || function (k, v) { 18 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); 19 | }; 20 | import { Plugin, Cordova, IonicNativePlugin } from '@ionic-native/core'; 21 | import { Injectable } from '@angular/core'; 22 | var JSMS = (function (_super) { 23 | __extends(JSMS, _super); 24 | function JSMS() { 25 | return _super !== null && _super.apply(this, arguments) || this; 26 | } 27 | JSMS.prototype.init = function () { return; }; 28 | ; 29 | JSMS.prototype.setDebugMode = function (enable) { return; }; 30 | /** 31 | * 请求短信验证码。 32 | * @param phoneNumber 要接收短信验证码的手机号码。 33 | * @param tempId 短信模板 id。 34 | */ 35 | JSMS.prototype.getSmsCode = function (phoneNumber, tempId) { return; }; 36 | /** 37 | * 请求语音验证码。 38 | * @param phoneNumber 要接收语音验证码的手机号码。 39 | * @param {number} languageCode:(可选)语言选项。0: 中文;1: 英文;2: 中英混合(中英混合仅支持 Android)。如果不填默认为中文。 40 | */ 41 | JSMS.prototype.getVoiceCode = function (phoneNumber, languageCode) { return; }; 42 | /** 43 | * 验证验证码。 44 | * @param phoneNumber 接收验证码的手机号码。 45 | * @param code 待验证的验证码。 46 | */ 47 | JSMS.prototype.checkSmsCode = function (phoneNumber, code) { return; }; 48 | /** 49 | * 设置前后两次获取验证码的时间间隔,默认 30 秒。 50 | * @param intervalTime 间隔时间,单位秒。 51 | */ 52 | JSMS.prototype.setIntervalTime = function (intervalTime) { return; }; 53 | /** 54 | * (Android only)获取设置的前后两次获取短信验证码的时间间隔。 55 | */ 56 | JSMS.prototype.getIntervalTime = function () { return; }; 57 | JSMS.decorators = [ 58 | { type: Injectable }, 59 | ]; 60 | /** @nocollapse */ 61 | JSMS.ctorParameters = function () { return []; }; 62 | __decorate([ 63 | Cordova(), 64 | __metadata("design:type", Function), 65 | __metadata("design:paramtypes", []), 66 | __metadata("design:returntype", Promise) 67 | ], JSMS.prototype, "init", null); 68 | __decorate([ 69 | Cordova(), 70 | __metadata("design:type", Function), 71 | __metadata("design:paramtypes", [Boolean]), 72 | __metadata("design:returntype", Promise) 73 | ], JSMS.prototype, "setDebugMode", null); 74 | __decorate([ 75 | Cordova(), 76 | __metadata("design:type", Function), 77 | __metadata("design:paramtypes", [String, String]), 78 | __metadata("design:returntype", Promise) 79 | ], JSMS.prototype, "getSmsCode", null); 80 | __decorate([ 81 | Cordova(), 82 | __metadata("design:type", Function), 83 | __metadata("design:paramtypes", [String, Number]), 84 | __metadata("design:returntype", Promise) 85 | ], JSMS.prototype, "getVoiceCode", null); 86 | __decorate([ 87 | Cordova(), 88 | __metadata("design:type", Function), 89 | __metadata("design:paramtypes", [String, String]), 90 | __metadata("design:returntype", Promise) 91 | ], JSMS.prototype, "checkSmsCode", null); 92 | __decorate([ 93 | Cordova(), 94 | __metadata("design:type", Function), 95 | __metadata("design:paramtypes", [Number]), 96 | __metadata("design:returntype", Promise) 97 | ], JSMS.prototype, "setIntervalTime", null); 98 | __decorate([ 99 | Cordova(), 100 | __metadata("design:type", Function), 101 | __metadata("design:paramtypes", []), 102 | __metadata("design:returntype", Promise) 103 | ], JSMS.prototype, "getIntervalTime", null); 104 | JSMS = __decorate([ 105 | Plugin({ 106 | pluginName: 'JSMS', 107 | plugin: 'cordova-plugin-jsms', 108 | pluginRef: 'plugins.jsms', 109 | repo: 'https://github.com/jpush/cordova-plugin-jsms', 110 | install: 'ionic cordova plugin add cordova-plugin-jsms --variable APP_KEY=your_app_key', 111 | installVariables: ['APP_KEY'], 112 | platforms: ['Android', 'iOS'] 113 | }) 114 | ], JSMS); 115 | return JSMS; 116 | }(IonicNativePlugin)); 117 | export { JSMS }; 118 | //# sourceMappingURL=index.js.map -------------------------------------------------------------------------------- /ionic/jsms/index.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["../../../src/@ionic-native/plugins/jsms/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;AAAA,OAAO,EAAE,MAAA,EAAQ,OAAA,EAAS,iBAAA,EAAkB,MAAO,oBAAA,CAAqB;AACxE,OAAO,EAAE,UAAA,EAAW,MAAO,eAAA,CAAgB;AAY3C;IAA0B,wBAAiB;IAA3C;;IAkDA,CAAC;IA/CC,mBAAI,GAAJ,cAAuB,MAAM,CAAC,CAAC,CAAC;IAAA,CAAC;IAGjC,2BAAY,GAAZ,UAAa,MAAe,IAAkB,MAAM,CAAC,CAAC,CAAC;IAEvD;;;;OAIG;IAEH,yBAAU,GAAV,UAAW,WAAmB,EAAE,MAAc,IAAkB,MAAM,CAAC,CAAC,CAAC;IAEzE;;;;OAIG;IAEH,2BAAY,GAAZ,UAAa,WAAmB,EAAE,YAAoB,IAAkB,MAAM,CAAC,CAAC,CAAC;IAEjF;;;;OAIG;IAEH,2BAAY,GAAZ,UAAa,WAAmB,EAAE,IAAY,IAAkB,MAAM,CAAC,CAAC,CAAC;IAEzE;;;OAGG;IAEH,8BAAe,GAAf,UAAgB,YAAoB,IAAkB,MAAM,CAAC,CAAC,CAAC;IAE/D;;OAEG;IAEH,8BAAe,GAAf,cAAkC,MAAM,CAAC,CAAC,CAAC;IACtC,eAAU,GAA0B;QAC3C,EAAE,IAAI,EAAE,UAAU,EAAE;KACnB,CAAC;IACF,kBAAkB;IACX,mBAAc,GAAmE,cAAM,OAAA,EAC7F,EAD6F,CAC7F,CAAC;IA9CA;QADC,OAAO,EAAE;;;;oCACsB;IAGhC;QADC,OAAO,EAAE;;;;4CAC6C;IAQvD;QADC,OAAO,EAAE;;;;0CAC+D;IAQzE;QADC,OAAO,EAAE;;;;4CACuE;IAQjF;QADC,OAAO,EAAE;;;;4CAC+D;IAOzE;QADC,OAAO,EAAE;;;;+CACqD;IAM/D;QADC,OAAO,EAAE;;;;+CACiC;IA3ChC,IAAI;QAVhB,MAAM,CAAC;YACN,UAAU,EAAE,MAAM;YAClB,MAAM,EAAE,qBAAqB;YAC7B,SAAS,EAAE,cAAc;YACzB,IAAI,EAAE,8CAA8C;YACpD,OAAO,EAAE,8EAA8E;YACvF,gBAAgB,EAAE,CAAC,SAAS,CAAC;YAC7B,SAAS,EAAE,CAAC,SAAS,EAAE,KAAK,CAAC;SAC9B,CAAC;OAEW,IAAI,CAkDhB;IAAD,WAAC;CAlDD,AAkDC,CAlDyB,iBAAiB,GAkD1C;SAlDY,IAAI","file":"index.js","sourceRoot":"","sourcesContent":["import { Plugin, Cordova, IonicNativePlugin } from '@ionic-native/core';\nimport { Injectable } from '@angular/core';\n\n@Plugin({\n pluginName: 'JSMS',\n plugin: 'cordova-plugin-jsms',\n pluginRef: 'plugins.jsms',\n repo: 'https://github.com/jpush/cordova-plugin-jsms',\n install: 'ionic cordova plugin add cordova-plugin-jsms --variable APP_KEY=your_app_key',\n installVariables: ['APP_KEY'],\n platforms: ['Android', 'iOS']\n})\n\nexport class JSMS extends IonicNativePlugin {\n\n @Cordova()\n init(): Promise { return; };\n\n @Cordova()\n setDebugMode(enable: boolean): Promise { return; }\n\n /**\n * 请求短信验证码。\n * @param phoneNumber 要接收短信验证码的手机号码。\n * @param tempId 短信模板 id。\n */\n @Cordova()\n getSmsCode(phoneNumber: string, tempId: string): Promise { return; }\n\n /**\n * 请求语音验证码。\n * @param phoneNumber 要接收语音验证码的手机号码。\n * @param {number} languageCode:(可选)语言选项。0: 中文;1: 英文;2: 中英混合(中英混合仅支持 Android)。如果不填默认为中文。\n */\n @Cordova()\n getVoiceCode(phoneNumber: string, languageCode: number): Promise { return; }\n\n /**\n * 验证验证码。\n * @param phoneNumber 接收验证码的手机号码。\n * @param code 待验证的验证码。 \n */\n @Cordova()\n checkSmsCode(phoneNumber: string, code: string): Promise { return; }\n\n /**\n * 设置前后两次获取验证码的时间间隔,默认 30 秒。\n * @param intervalTime 间隔时间,单位秒。\n */\n @Cordova()\n setIntervalTime(intervalTime: number): Promise { return; }\n\n /**\n * (Android only)获取设置的前后两次获取短信验证码的时间间隔。\n */\n @Cordova()\n getIntervalTime(): Promise { return; }\nstatic decorators: DecoratorInvocation[] = [\n{ type: Injectable },\n];\n/** @nocollapse */\nstatic ctorParameters: () => ({type: any, decorators?: DecoratorInvocation[]}|null)[] = () => [\n];\n}\n\ninterface DecoratorInvocation {\n type: Function;\n args?: any[];\n}\n"]} -------------------------------------------------------------------------------- /ionic/jsms/index.metadata.json: -------------------------------------------------------------------------------- 1 | [{"__symbolic":"module","version":3,"metadata":{"JSMS":{"__symbolic":"class","extends":{"__symbolic":"reference","module":"@ionic-native/core","name":"IonicNativePlugin"},"decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@ionic-native/core","name":"Plugin"},"arguments":[{"pluginName":"JSMS","plugin":"cordova-plugin-jsms","pluginRef":"plugins.jsms","repo":"https://github.com/jpush/cordova-plugin-jsms","install":"ionic cordova plugin add cordova-plugin-jsms --variable APP_KEY=your_app_key","installVariables":["APP_KEY"],"platforms":["Android","iOS"]}]},{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Injectable"}}],"members":{"init":[{"__symbolic":"method","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@ionic-native/core","name":"Cordova"}}]}],"setDebugMode":[{"__symbolic":"method","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@ionic-native/core","name":"Cordova"}}]}],"getSmsCode":[{"__symbolic":"method","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@ionic-native/core","name":"Cordova"}}]}],"getVoiceCode":[{"__symbolic":"method","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@ionic-native/core","name":"Cordova"}}]}],"checkSmsCode":[{"__symbolic":"method","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@ionic-native/core","name":"Cordova"}}]}],"setIntervalTime":[{"__symbolic":"method","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@ionic-native/core","name":"Cordova"}}]}],"getIntervalTime":[{"__symbolic":"method","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@ionic-native/core","name":"Cordova"}}]}]}}}},{"__symbolic":"module","version":1,"metadata":{"JSMS":{"__symbolic":"class","extends":{"__symbolic":"reference","module":"@ionic-native/core","name":"IonicNativePlugin"},"decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@ionic-native/core","name":"Plugin"},"arguments":[{"pluginName":"JSMS","plugin":"cordova-plugin-jsms","pluginRef":"plugins.jsms","repo":"https://github.com/jpush/cordova-plugin-jsms","install":"ionic cordova plugin add cordova-plugin-jsms --variable APP_KEY=your_app_key","installVariables":["APP_KEY"],"platforms":["Android","iOS"]}]},{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Injectable"}}],"members":{"init":[{"__symbolic":"method","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@ionic-native/core","name":"Cordova"}}]}],"setDebugMode":[{"__symbolic":"method","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@ionic-native/core","name":"Cordova"}}]}],"getSmsCode":[{"__symbolic":"method","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@ionic-native/core","name":"Cordova"}}]}],"getVoiceCode":[{"__symbolic":"method","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@ionic-native/core","name":"Cordova"}}]}],"checkSmsCode":[{"__symbolic":"method","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@ionic-native/core","name":"Cordova"}}]}],"setIntervalTime":[{"__symbolic":"method","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@ionic-native/core","name":"Cordova"}}]}],"getIntervalTime":[{"__symbolic":"method","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@ionic-native/core","name":"Cordova"}}]}]}}}}] -------------------------------------------------------------------------------- /ionic/jsms/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@jiguang-ionic/jsms", 3 | "version": "1.0.0", 4 | "description": "JSMS support for ionic-native", 5 | "module": "index.js", 6 | "typings": "index.d.ts", 7 | "author": "hevin", 8 | "license": "MIT", 9 | "peerDependencies": { 10 | "@ionic-native/core": "^4.2.0", 11 | "@angular/core": "*", 12 | "rxjs": "^5.0.1" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "https://github.com/jpush/cordova-plugin-jsms" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cordova-plugin-jsms", 3 | "version": "1.2.1", 4 | "description": "JSMS for Cordova plugin.", 5 | "cordova": { 6 | "id": "cordova-plugin-jsms", 7 | "platforms": [ 8 | "ios", 9 | "android" 10 | ] 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "git+https://github.com/jpush/cordova-plugin-jsms.git" 15 | }, 16 | "keywords": [ 17 | "JPush", 18 | "sms", 19 | "jiguang", 20 | "jsms", 21 | "JSMS", 22 | "cordova-plugin-jsms", 23 | "cordova-plugin" 24 | ], 25 | "devDependencies": { 26 | "cordova-plugin-device": "*" 27 | }, 28 | "author": "JiGuang", 29 | "license": "MIT", 30 | "bugs": { 31 | "url": "https://github.com/jpush/cordova-plugin-jsms/issues" 32 | }, 33 | "homepage": "https://github.com/jpush/cordova-plugin-jsms#readme" 34 | } 35 | -------------------------------------------------------------------------------- /plugin.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | JSMS 8 | JSMS for Cordova plugin 9 | JiGuang 10 | JSMS,SMS,jsms,sms 11 | MIT License 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | $APP_KEY 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /src/android/JSMSPlugin.java: -------------------------------------------------------------------------------- 1 | package cn.jiguang.cordova.sms; 2 | 3 | import android.util.Log; 4 | 5 | import org.apache.cordova.CallbackContext; 6 | import org.apache.cordova.CordovaInterface; 7 | import org.apache.cordova.CordovaPlugin; 8 | import org.apache.cordova.CordovaWebView; 9 | import org.json.JSONArray; 10 | import org.json.JSONException; 11 | import org.json.JSONObject; 12 | 13 | import java.lang.reflect.Method; 14 | 15 | import cn.jpush.sms.SMSSDK; 16 | import cn.jpush.sms.listener.SmscheckListener; 17 | import cn.jpush.sms.listener.SmscodeListener; 18 | 19 | public class JSMSPlugin extends CordovaPlugin { 20 | 21 | private static final String TAG = JSMSPlugin.class.getSimpleName(); 22 | 23 | private final int ERR_CODE_PARAMETER = 1; // 参数错误。 24 | private final String ERR_DESC_PARAMETER = "Parameters error"; 25 | 26 | @Override 27 | public void initialize(CordovaInterface cordova, CordovaWebView webView) { 28 | super.initialize(cordova, webView); 29 | } 30 | 31 | @Override 32 | public boolean execute(final String action, final JSONArray data, 33 | final CallbackContext callbackContext) throws JSONException { 34 | cordova.getThreadPool().execute(new Runnable() { 35 | @Override 36 | public void run() { 37 | try { 38 | Method method = JSMSPlugin.class.getDeclaredMethod(action, 39 | JSONArray.class, CallbackContext.class); 40 | method.invoke(JSMSPlugin.this, data, callbackContext); 41 | } catch (Exception e) { 42 | Log.e(TAG, e.toString()); 43 | } 44 | } 45 | }); 46 | return true; 47 | } 48 | 49 | void init(JSONArray data, CallbackContext callback) { 50 | SMSSDK.getInstance().initSdk(cordova.getActivity()); 51 | } 52 | 53 | void setDebugMode(JSONArray data, CallbackContext callback) { 54 | boolean isDebug; // 默认不开启 55 | 56 | try { 57 | isDebug = data.getBoolean(0); 58 | } catch (JSONException e) { 59 | e.printStackTrace(); 60 | handleResult(ERR_CODE_PARAMETER, ERR_DESC_PARAMETER, callback); 61 | return; 62 | } 63 | 64 | SMSSDK.getInstance().setDebugMode(isDebug); 65 | callback.success(); 66 | } 67 | 68 | void getSmsCode(JSONArray data, final CallbackContext callback) { 69 | String phoneNum; 70 | String tempId; 71 | 72 | try { 73 | phoneNum = data.getString(0); 74 | tempId = data.getString(1); 75 | 76 | } catch (JSONException e) { 77 | e.printStackTrace(); 78 | handleResult(ERR_CODE_PARAMETER, ERR_DESC_PARAMETER, callback); 79 | return; 80 | } 81 | 82 | SMSSDK.getInstance().getSmsCode(phoneNum, tempId, new SmscodeListener() { 83 | @Override 84 | public void getCodeSuccess(String uuid) { 85 | callback.success(uuid); 86 | } 87 | 88 | @Override 89 | public void getCodeFail(int errorCode, String desc) { 90 | handleResult(errorCode, desc, callback); 91 | } 92 | }); 93 | } 94 | 95 | void getVoiceCode(JSONArray data, final CallbackContext callback) { 96 | String phoneNum; 97 | int language; 98 | 99 | try { 100 | phoneNum = data.getString(0); 101 | language = data.getInt(1); 102 | } catch (JSONException e) { 103 | e.printStackTrace(); 104 | handleResult(ERR_CODE_PARAMETER, ERR_DESC_PARAMETER, callback); 105 | return; 106 | } 107 | 108 | SMSSDK.getInstance().getVoiceCode(phoneNum, language, new SmscodeListener() { 109 | @Override 110 | public void getCodeSuccess(String uuid) { 111 | callback.success(uuid); // uuid: 本次操作的唯一标识。 112 | } 113 | 114 | @Override 115 | public void getCodeFail(int errCode, String desc) { 116 | handleResult(errCode, desc, callback); 117 | } 118 | }); 119 | } 120 | 121 | void checkSmsCode(JSONArray data, final CallbackContext callback) { 122 | String phoneNum; 123 | String code; 124 | 125 | try { 126 | phoneNum = data.getString(0); 127 | code = data.getString(1); 128 | } catch (JSONException e) { 129 | e.printStackTrace(); 130 | handleResult(ERR_CODE_PARAMETER, ERR_DESC_PARAMETER, callback); 131 | return; 132 | } 133 | 134 | SMSSDK.getInstance().checkSmsCode(phoneNum, code, new SmscheckListener() { 135 | @Override 136 | public void checkCodeSuccess(String code) { 137 | callback.success(code); // code:验证码信息。 138 | } 139 | 140 | @Override 141 | public void checkCodeFail(int errorCode, String desc) { 142 | callback.error(errorCode); 143 | handleResult(errorCode, desc, callback); 144 | } 145 | }); 146 | } 147 | 148 | void setIntervalTime(JSONArray data, CallbackContext callback) { 149 | long intervalTime; 150 | 151 | try { 152 | intervalTime = data.getLong(0); // JS 传过来的单位是秒。 153 | } catch (JSONException e) { 154 | e.printStackTrace(); 155 | handleResult(ERR_CODE_PARAMETER, ERR_DESC_PARAMETER, callback); 156 | return; 157 | } 158 | 159 | SMSSDK.getInstance().setIntervalTime(intervalTime * 1000); // 秒转毫秒。 160 | callback.success(); 161 | } 162 | 163 | void getIntervalTime(JSONArray data, CallbackContext callback) { 164 | long internalTime = SMSSDK.getInstance().getIntervalTime() / 1000; // 毫秒转秒。 165 | callback.success((int) internalTime); 166 | } 167 | 168 | private void handleResult(int status, String desc, CallbackContext callback) { 169 | if (status == 0) { // success 170 | callback.success(); 171 | } else { // error 172 | JSONObject errorJson = new JSONObject(); 173 | try { 174 | errorJson.put("code", status); 175 | errorJson.put("description", desc); 176 | } catch (JSONException e) { 177 | e.printStackTrace(); 178 | } 179 | callback.error(errorJson); 180 | } 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /src/android/jsms_android-1.2.2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jpush/cordova-plugin-jsms/0c065fc1d10ddda651bef9e4ed79950a68d56284/src/android/jsms_android-1.2.2.jar -------------------------------------------------------------------------------- /src/ios/JSMSConfig.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | APP_KEY 6 | 94426bda4a12dd1fe5221375 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/ios/JsmsSDK/include/JSMSConstant.h: -------------------------------------------------------------------------------- 1 | // 2 | // JSMSConstant.h 3 | // JSms-test 4 | // 5 | // Created by jpush on 16/3/28. 6 | // Copyright © 2016年 HXHG. All rights reserved. 7 | // 8 | 9 | #define JSMS_VERSION_NUMBER 1.4.0 10 | 11 | #ifndef JSMSConstant_h 12 | #define JSMSConstant_h 13 | 14 | 15 | typedef NS_ENUM(int, JSMSAuthCodeRequestError) { 16 | //获取验证码uuid错误,验证码验证失败 17 | JSMSAuthCodeRequestGetUuidError = 2993, 18 | //参数为空 19 | JSMSAuthCodeRequestParameterError = 2994, 20 | //两次请求不超过最小时间间隔 21 | JSMSAuthCodeRequestFrequentError = 2996, 22 | //号码改变,请首先获取验证码 23 | JSMSAuthCodePhoneNumberChangedError = 2997, 24 | //其他错误 25 | JSMSAuthCodeRequestOtherError = 2999, 26 | //手机号不合法 27 | JSMSAuthCodeRequestInvalidMobile = 4204, 28 | //body为空 29 | JSMSAuthCodeRequestEmptyBody = 4001, 30 | //无效的appKey 31 | JSMSAuthCodeRequestInvalidAppkey = 4002, 32 | //无效的来源 33 | JSMSAuthCodeRequestInvalidPlatform = 4003, 34 | //body解密失败 35 | JSMSAuthCodeRequestDecryptAesBodyFailed = 4004, 36 | //aes key解密失败 37 | JSMSAuthCodeRequestDecryptAesKeyFailed = 4005, 38 | //时间戳转化失败 39 | JSMSAuthCodeRequestTimestampConvertFailed = 4006, 40 | //body格式不正确 41 | JSMSAuthCodeRequestBadFormatterBody = 4007, 42 | //无效的时间戳 43 | JSMSAuthCodeRequestInvalidTimestamp = 4008, 44 | //没有短信验证权限 45 | JSMSAuthCodeRequestNoSmscodeAuth = 4009, 46 | //请求超频 47 | JSMSAuthCodeRequestOutOfFreg = 4011, 48 | //api不存在 49 | JSMSAuthCodeRequestApiNotFound = 4012, 50 | //模板不存在 51 | JSMSAuthCodeRequestTempNotFound = 4013, 52 | //空的extra 53 | JSMSAuthCodeRequestEmptyExtra = 4014, 54 | //验证码错误 55 | JSMSAuthCodeRequestWrongCode = 4015, 56 | //余额不足 57 | JSMSAuthCodeRequestNoMoney = 4016, 58 | //过期验证码 59 | JSMSAuthCodeRequestExpiredCode = 4017, 60 | //已经验证过 61 | JSMSAuthCodeRequestAlreadyVerified = 4018, 62 | //服务器错误 63 | JSMSAuthCodeRequestSeverInternalError = 5000, 64 | 65 | }; 66 | 67 | 68 | typedef NS_OPTIONS(NSUInteger, JSMSLanguageOptions) { 69 | JSMSLanguage_zh_Hans = 1 << 0, //中文 70 | JSMSLanguage_en = 1 << 1 //英文 71 | }; 72 | 73 | 74 | #endif /* JSMSConstant_h */ 75 | 76 | -------------------------------------------------------------------------------- /src/ios/JsmsSDK/include/JSMSSDK.h: -------------------------------------------------------------------------------- 1 | // 2 | // JSMSSDK.h 3 | // 4 | // 5 | // Created by jpush on 16/3/28. 6 | // Copyright © 2016年 HXHG. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "JSMSConstant.h" 11 | 12 | /*! 13 | * @abstract 异步回调 block 14 | * 15 | * @discussion 获取验证码和验证验证码结果都会通过这个block返回 16 | * 17 | * - 如果调用出错,则error不为空,可根据 error.code 来获取错误码。该错误码 JSMS 相关文档里有详细的定义 http://docs.jiguang.cn/guideline/iOS_SMS_SDK/。 18 | * - 如果返回正常,则error为空。具体查看相关接口说明。 19 | * 20 | */ 21 | typedef void (^JSMSCompletionHandler)(id _Nullable resultObject, NSError *_Nullable error); 22 | 23 | @interface JSMSSDK : NSObject 24 | 25 | /** 26 | * 初始化SDK 27 | * 28 | * @param appkey appkey 29 | */ 30 | + (void)registerWithAppKey:(NSString * _Nonnull)appKey; 31 | 32 | /** 33 | * 获取短信验证码 (最小间隔时间内只能调用一次) 34 | * 35 | * @param number 手机号码 36 | * @param templateID 短信模板ID 37 | * @param handler 服务器返回状态,成功时 error 为空 resultObject 为 @"success" 38 | */ 39 | + (void)getVerificationCodeWithPhoneNumber:(NSString * _Nonnull)number 40 | andTemplateID:(NSString * _Nonnull)templateID 41 | completionHandler:(JSMSCompletionHandler _Nonnull)handler; 42 | 43 | /** 44 | * 获取语音验证码 (v1.2.0 新增接口) 45 | * 46 | * @param number 手机号码 47 | * @param handler 服务器返回状态,成功时 error 为空 resultObject 为 @"success" 48 | * @discussion 默认中文播报。设置其它播报语言请调用getVoiceVerificationCodeWithPhoneNumber:languageOptions:completionHandler:方法 49 | */ 50 | + (void)getVoiceVerificationCodeWithPhoneNumber:(NSString * _Nonnull)number 51 | completionHandler:(JSMSCompletionHandler _Nonnull)handler; 52 | 53 | 54 | /** 55 | * 获取语音验证码 (v1.4.0 新增接口) 56 | * 57 | * @param number 手机号码 58 | * @param number 播报语言。参数无效时,默认中文播报 59 | * @param handler 服务器返回状态,成功时 error 为空 resultObject 为 @"success" 60 | */ 61 | + (void)getVoiceVerificationCodeWithPhoneNumber:(NSString * _Nonnull)number 62 | languageOptions:(JSMSLanguageOptions)options 63 | completionHandler:(JSMSCompletionHandler _Nonnull)handler; 64 | 65 | /** 66 | * 验证验证码 67 | * 68 | * @param number 手机号码 69 | * @param vCode (短信/语音)验证码 70 | * @param handler 服务器返回状态,,成功时 error 为空 resultObject 为 @"success" 71 | */ 72 | + (void)commitWithPhoneNumber:(NSString * _Nonnull)number 73 | verificationCode:(NSString * _Nonnull)vCode 74 | completionHandler:(JSMSCompletionHandler _Nonnull)handler; 75 | 76 | /** 77 | * 设置获取验证码的时间间隔 (有效间隔 0~3600s) 78 | * 在设置间隔时间内只能发送一次获取验证码的请求,SDK 默认是30s 79 | * @param seconds 时间间隔 80 | */ 81 | + (void)setMinimumTimeInterval:(NSTimeInterval)seconds; 82 | 83 | 84 | 85 | 86 | 87 | @end 88 | -------------------------------------------------------------------------------- /src/ios/JsmsSDK/libsms-lib.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jpush/cordova-plugin-jsms/0c065fc1d10ddda651bef9e4ed79950a68d56284/src/ios/JsmsSDK/libsms-lib.a -------------------------------------------------------------------------------- /src/ios/Plugins/JSMSPlugin.h: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // Created by 57380422@qq.com on 2016.07.18. 4 | // 5 | // 6 | 7 | #import 8 | 9 | #define kJPushPluginReceiveNotification @"JPushPluginReceiveNofication" 10 | 11 | @interface JSMSPlugin : CDVPlugin{ 12 | 13 | } 14 | 15 | -(void)setup:(CDVInvokedUrlCommand*)command; 16 | -(void)getSmsCode:(CDVInvokedUrlCommand*)command; 17 | -(void)getVoiceCode:(CDVInvokedUrlCommand*)command; 18 | -(void)setIntervalTime:(CDVInvokedUrlCommand*)command; 19 | -(void)checkSmsCode:(CDVInvokedUrlCommand*)command; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /src/ios/Plugins/JSMSPlugin.m: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // Created by 57380422@qq.com on 2016.07.18. 4 | // 5 | // 6 | 7 | 8 | #import 9 | #import "JSMSPlugin.h" 10 | #import "JSMSSDK.h" 11 | 12 | 13 | #define WEAK_SELF(weakSelf) __weak __typeof(&*self)weakSelf = self; 14 | 15 | static NSString *const APP_KEY = @"APP_KEY"; 16 | static NSString *const JSMSConfigFileName = @"JSMSConfig"; 17 | static NSString *const KEY_ERRORCODE = @"errorCode"; 18 | static NSString *const KEY_ERRORDESCRIP = @"errorDscription"; 19 | 20 | @implementation JSMSPlugin 21 | 22 | 23 | -(void)initial:(CDVInvokedUrlCommand*)command{ 24 | //do nithng,because Cordova plugin use lazy load mode. 25 | } 26 | 27 | #ifdef __CORDOVA_4_0_0 28 | 29 | - (void)pluginInitialize { 30 | NSLog(@"### pluginInitialize "); 31 | } 32 | 33 | #else 34 | 35 | - (CDVPlugin*)initWithWebView:(UIWebView*)theWebView{ 36 | NSLog(@"### initWithWebView "); 37 | if (self=[super initWithWebView:theWebView]) { 38 | } 39 | return self; 40 | } 41 | 42 | #endif 43 | 44 | -(void)setup:(CDVInvokedUrlCommand*)command { 45 | [self registerAppkey]; 46 | } 47 | 48 | -(void)getSmsCode:(CDVInvokedUrlCommand*)command{ 49 | NSString *phoneNumber = [command argumentAtIndex:0]; 50 | NSString *templateId = [command argumentAtIndex:1]; 51 | WEAK_SELF(weakSelf); 52 | [JSMSSDK getVerificationCodeWithPhoneNumber:phoneNumber andTemplateID:templateId completionHandler:^(id resultObject, NSError *error) { 53 | [weakSelf handleResultWithValue:resultObject command:command error:error log:@"get sms code"]; 54 | }]; 55 | } 56 | 57 | -(void)getVoiceCode:(CDVInvokedUrlCommand*)command{ 58 | NSString *phoneNumber = [command argumentAtIndex:0]; 59 | WEAK_SELF(weakSelf); 60 | [JSMSSDK getVoiceVerificationCodeWithPhoneNumber:phoneNumber completionHandler:^(id _Nullable resultObject, NSError * _Nullable error) { 61 | [weakSelf handleResultWithValue:resultObject command:command error:error log:@"get voice code"]; 62 | }]; 63 | } 64 | 65 | -(void)setIntervalTime:(CDVInvokedUrlCommand*)command{ 66 | NSTimeInterval timeInterval = ((NSNumber*)[command argumentAtIndex:0]).doubleValue; 67 | [JSMSSDK setMinimumTimeInterval:timeInterval]; 68 | } 69 | 70 | -(void)checkSmsCode:(CDVInvokedUrlCommand*)command{ 71 | NSString *phoneNumber = [command argumentAtIndex:0]; 72 | NSString *code = [command argumentAtIndex:1]; 73 | WEAK_SELF(weakSelf); 74 | [JSMSSDK commitWithPhoneNumber:phoneNumber verificationCode:code completionHandler:^(id resultObject, NSError *error) { 75 | [weakSelf handleResultWithValue:resultObject command:command error:error log:@"verification code"]; 76 | }]; 77 | } 78 | 79 | #pragma mark- 内部方法 80 | - (void)registerAppkey{ 81 | 82 | NSString *path = [[NSBundle mainBundle] pathForResource:JSMSConfigFileName ofType:@"plist"]; 83 | 84 | if (path == nil) { 85 | NSLog(@"error: JSMSConfig.plist not found"); 86 | assert(0); 87 | } 88 | 89 | NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithContentsOfFile:path]; 90 | NSString *appkey = dict[APP_KEY]; 91 | 92 | if (!appkey || appkey.length == 0) { 93 | NSLog(@"error: app key not found in JSMSConfig.plist "); 94 | assert(0); 95 | } 96 | 97 | [JSMSSDK registerWithAppKey:appkey]; 98 | 99 | } 100 | 101 | -(void)handleResultWithValue:(id)value command:(CDVInvokedUrlCommand*)command error:(NSError*)error log:(NSString*)log{ 102 | 103 | CDVPluginResult *result = nil; 104 | 105 | if (error == nil) { 106 | CDVCommandStatus status = CDVCommandStatus_OK; 107 | 108 | if ([value isKindOfClass:[NSString class]]) { 109 | value = [value stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; 110 | } else if ([value isKindOfClass:[NSNull class]]) { 111 | value = nil; 112 | } 113 | 114 | if ([value isKindOfClass:[NSObject class]]) { 115 | result = [CDVPluginResult resultWithStatus:status messageAsString:value]; 116 | } else { 117 | NSLog(@"JSMSPlugin Log: Cordova callback block returned unrecognized type: %@", NSStringFromClass([value class])); 118 | result = nil; 119 | } 120 | 121 | if (result != nil) { 122 | if (log) { 123 | NSLog(@"JSMSPlugin Log: %@ succeeded",log); 124 | } 125 | }else{ 126 | if (log) { 127 | NSLog(@"JSMSPlugin Log: %@ failed",log); 128 | } 129 | result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR]; 130 | } 131 | 132 | }else{ 133 | if (log) { 134 | NSLog(@"JSMSPlugin Log: %@ failed",log); 135 | } 136 | NSMutableDictionary * dict = [NSMutableDictionary new]; 137 | [dict setValue:[NSNumber numberWithLong:error.code] forKey:KEY_ERRORCODE]; 138 | [dict setValue:error.debugDescription forKey:KEY_ERRORDESCRIP]; 139 | result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dict]; 140 | } 141 | 142 | WEAK_SELF(weakSelf); 143 | [weakSelf.commandDelegate sendPluginResult:result callbackId:command.callbackId]; 144 | } 145 | 146 | @end 147 | -------------------------------------------------------------------------------- /www/JSMSPlugin.js: -------------------------------------------------------------------------------- 1 | var exec = require('cordova/exec') 2 | 3 | var PLUGIN_NAME = 'JSMSPlugin' 4 | 5 | var JSMSPlugin = function () {} 6 | 7 | JSMSPlugin.prototype.init = function () { 8 | if (device.platform === 'iOS') { 9 | exec(null, null, PLUGIN_NAME, 'setup', []) 10 | } else if (device.platform === 'Android') { 11 | exec(null, null, PLUGIN_NAME, 'init', []) 12 | } 13 | } 14 | 15 | /** 16 | * 开启 Debug 模式(Android only)。 17 | */ 18 | JSMSPlugin.prototype.setDebugMode = function (enable, successCallback, errorCallback) { 19 | if (device.platform === 'Android') { 20 | exec(successCallback, errorCallback, PLUGIN_NAME, 'setDebugMode', [enable]) 21 | } 22 | } 23 | 24 | /** 25 | * 请求获取短信验证码。 26 | * @param {String} phoneNum:表示要接收短信验证码的手机号。 27 | * @param {String} tempId:表示短信模板 ID。 28 | */ 29 | JSMSPlugin.prototype.getSmsCode = function (phoneNum, tempId, successCallback, errorCallback) { 30 | exec(successCallback, errorCallback, PLUGIN_NAME, 'getSmsCode', [phoneNum, tempId]) 31 | } 32 | 33 | /** 34 | * 获取语音验证码。 35 | * @param {String} phoneNum: 待接受语音验证码的手机号码。 36 | * @param {number} languageCode:(可选)语言选项。0: 中文;1: 英文;2: 中英混合。如果不填默认为中文。 37 | */ 38 | JSMSPlugin.prototype.getVoiceCode = function (phoneNum, languageCode, successCallback, errorCallback) { 39 | exec(successCallback, errorCallback, PLUGIN_NAME, 'getVoiceCode', [phoneNum, languageCode]) 40 | } 41 | 42 | /** 43 | * 检查验证码是否正确。 44 | * @param {String} phoneNum:表示要接收验证码的手机号。 45 | * @param {String} code:表示用户输入的验证码。 46 | */ 47 | JSMSPlugin.prototype.checkSmsCode = function (phoneNum, code, successCallback, errorCallback) { 48 | exec(successCallback, errorCallback, PLUGIN_NAME, 'checkSmsCode', [phoneNum, code]) 49 | } 50 | 51 | /** 52 | * 设置前后两次获取验证码的时间间隔(单位秒),默认 30 秒。 53 | * @param {number} 前后两次获取验证码的时间间隔(单位秒)。 54 | */ 55 | JSMSPlugin.prototype.setIntervalTime = function (intervalTime, successCallback, errorCallback) { 56 | exec(successCallback, errorCallback, PLUGIN_NAME, 'setIntervalTime', [intervalTime]) 57 | } 58 | 59 | /** 60 | * (Android only)获取当前设置的时间间隔(单位秒)。 61 | * 62 | * @param {function} successCallback = function (internalTime: number) {} 以参数形式返回间隔时间。 63 | */ 64 | JSMSPlugin.prototype.getIntervalTime = function (successCallback, errorCallback) { 65 | if (device.platform === 'Android') { 66 | exec(successCallback, errorCallback, PLUGIN_NAME, 'getIntervalTime', []) 67 | } 68 | } 69 | 70 | if (!window.plugins) { 71 | window.plugins = {} 72 | } 73 | 74 | if (!window.plugins.jsms) { 75 | window.plugins.jsms = new JSMSPlugin() 76 | } 77 | 78 | module.exports = new JSMSPlugin() 79 | --------------------------------------------------------------------------------