# phone-account **Repository Path**: xiaolinlu/phone-account ## Basic Information - **Project Name**: phone-account - **Description**: No description available - **Primary Language**: Unknown - **License**: GPL-3.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2024-08-11 - **Last Updated**: 2024-08-11 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README **Accounts-Phone** ========================= 适用于 Meteor 的基于手机和一次性密码(OTP)的登录方式。 ## 安装 在 Meteor 应用程序目录中,输入: ``` meteor npm install --save libphonenumber-js meteor add settlin:accounts-phone ``` `libphonenumber-js`被`Accounts.sanitizePhone()`使用。我没有将其作为依赖项包含在内,这样如果有人覆盖了`sanitizePhone`函数,就不会白白添加这个库。 ## 数据库 按照当前`accounts-password`所使用的`emails`字段的方式,我们在用户文档中使用`phones`字段:`{phones: [{number, verified: false}]}`。一次性密码(OTP)存储在`services.phone.otp`中。 你需要在集合上创建一个索引,以确保性能: ``` Meteor.otps.rawCollection().createIndex({phone: 1, purpose: 1}, {unique: true, name: 'phoneAndPurpose'}); ``` ## 流程 使用一个简单的 Meteor 方法: ```javascript function sendOtpViaSms(otp) {.....} // 用于发送短信的函数 Meteor.methods({ // 用于 sendOtpForLogin: function(toPhone) { if (Meteor.isClient) return null; // OTP 必须在服务器上生成,绝不能透露给客户端 check(toPhone, String); // 发送 OTP 作为短信 let otp = Math.round(Random.fraction() * 100000); // Accounts.setPhoneOtp 在`__otps`集合中设置 OTP:{phone, otp, purpose: '__login__'}。 Accounts.setPhoneOtp(toPhone, otp); }, }); ``` 在需要时使用这个方法发送 OTP。接下来,从用户那里获取 OTP 并调用: ``` Meteor.loginWithPhone({phone, otp}, callback); ``` 这个方法与其他任何`Meteor.loginWith`方法的工作方式相同。 ## 简单的 API ### 服务器端 ```javascript Meteor.otps; // 包含 OTP 的集合,形式为{phone, otp, purpose, createdAt},通过以下方式创建索引:Meteor.otps._ensureIndex({phone: 1, purpose: 1}, {unique: true, name: 'phoneAndPurpose'}); // 在客户端不可用 /** * @summary 为用户设置 OTP。 * @locus 服务器端 * @param {String} userId 要更新的用户 ID。 * @param {String} otp OTP。 * @returns {Void} null。 */ Accounts.setPhoneOtp = function(userId, otp) {...}; /** * @summary 为用户添加一个电话号码。使用这个方法而不是直接更新数据库。如果有不同的用户拥有相同的电话号码,操作将失败。 * @locus 服务器端 * @param {String} userId 要更新的用户 ID。 * @param {String} newPhone 用户的新电话号码。 * @param {Boolean} [verified] 可选 - 是否将新电话号码标记为已验证。默认为 false。 * @returns {Void} null。 */ Accounts.addPhone = function(userId, newPhone, verified) {...}; /** * @summary 为用户删除一个电话号码。使用这个方法而不是直接更新数据库。 * @locus 服务器端 * @param {String} userId 要更新的用户 ID。 * @param {String} phone 要删除的电话号码。 * @returns {Void} null。 */ Accounts.removePhone = function(userId, phone) {...}; /** * @summary 通过电话号码搜索找到用户。如果找到多个用户则抛出错误。 * @param {String} phone 电话号码。 * @return {Object} 用户文档。 */ Accounts.findUserByPhone = function(phone) {...}; /** * @summary 使用密码登录用户。印度电话号码在没有“91”的情况下也可以接受。对于其他国家,需要国家代码。使用 https://github.com/halt-hammerzeit/libphonenumber-js。 * @locus 服务器端 * @param {String} phone 电话号码。 * @return {String} 经过清理的电话号码。针对印度电话号码进行了调整,但也适用于其他国家。 */ Accounts.sanitizePhone = function(phone) {...}; ``` ### 客户端 ```javascript /** * @summary 使用密码登录用户。 * @locus 客户端 * @param {Object} options 包含 phone、otp 和可选的 expectedUserId。 * @param {Function} [callback] 可选的回调函数。成功时不带参数调用,失败时带一个`Error`参数调用。 * @return {Void} null。 */ Meteor.loginWithPhone = function({ phone, otp, expectedUserId // 可选。这个电话号码对应的预期用户 ID。在电话号码可能不唯一的情况下,有时我们可能需要检查登录是针对预期的旧用户还是新用户,所以这个参数是必要的。 }, callback) {...}; /** * @summary 使用密码登录用户。印度电话号码在没有“91”的情况下也可以接受。对于其他国家,需要国家代码。使用 https://github.com/halt-hammerzeit/libphonenumber-js,作为动态导入。 * @locus 服务器端 * @param {String} phone 电话号码。 * @return {String} 经过清理的电话号码。针对印度电话号码进行了调整,但也适用于其他国家。 */ Accounts.sanitizePhone = async function(phone) {...}; ``` 如果你需要手机+密码登录,请使用。