smart_sms 0.0.3 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,7 +7,11 @@ module SmartSms
7
7
 
8
8
  source_root File.expand_path(File.join(File.dirname(__FILE__), 'templates'))
9
9
 
10
- desc 'Generates (but does not run) a migration to add a message table.'
10
+ desc <<-EOF
11
+ Generates (but does not run) a migration to add a messages table.
12
+ You need to set `store_sms_in_local` to `true` in your config file
13
+ before running this command
14
+ EOF
11
15
 
12
16
  def create_migration_file
13
17
  add_smart_sms_migration('create_smart_sms_messages') if SmartSMS.config.store_sms_in_local
@@ -18,10 +22,11 @@ module SmartSms
18
22
  end
19
23
 
20
24
  protected
25
+
21
26
  def add_smart_sms_migration(template)
22
27
  migration_dir = File.expand_path('db/migrate')
23
28
 
24
- if !self.class.migration_exists?(migration_dir, template)
29
+ unless self.class.migration_exists?(migration_dir, template)
25
30
  migration_template "#{template}.rb", "db/migrate/#{template}.rb"
26
31
  end
27
32
  end
@@ -12,4 +12,4 @@ SmartSMS.configure do |config|
12
12
  # config.default_interval = 1.day
13
13
  # config.store_sms_in_local = false
14
14
  # config.verification_code_algorithm = :simple
15
- end
15
+ end
data/lib/smart_sms.rb CHANGED
@@ -6,7 +6,7 @@ require 'smart_sms/helpers/verification_code'
6
6
  require 'smart_sms/message_service'
7
7
  require 'smart_sms/account'
8
8
 
9
- if !defined? ActiveRecord
9
+ unless defined? ActiveRecord
10
10
  begin
11
11
  require 'active_record'
12
12
  rescue LoadError; end
@@ -32,4 +32,4 @@ require 'smart_sms/has_sms_verification'
32
32
 
33
33
  ActiveSupport.on_load(:active_record) do
34
34
  include SmartSMS::HasSmsVerification
35
- end
35
+ end
@@ -1,8 +1,10 @@
1
- #encoding: utf-8
1
+ # encoding: utf-8
2
2
 
3
3
  module SmartSMS
4
+ # Module that handle user information
5
+ #
4
6
  module Account
5
- extend self
7
+ module_function
6
8
 
7
9
  # 获取用户信息
8
10
  def info
@@ -13,8 +15,8 @@ module SmartSMS
13
15
  # emergency_contact: 紧急联系人
14
16
  # emergency_mobile: 紧急联系人手机号
15
17
  # alarm_balance: 短信余额提醒阈值。一天只提示一次
16
- def set options = {}
18
+ def set(options = {})
17
19
  Request.post 'user/set.json', options
18
20
  end
19
21
  end
20
- end
22
+ end
@@ -1,9 +1,8 @@
1
- #encoding: utf-8
1
+ # encoding: utf-8
2
2
  require 'active_support/configurable'
3
3
  require 'active_support/core_ext'
4
4
 
5
5
  module SmartSMS
6
-
7
6
  # Configures global settings for SmartSMS
8
7
  # SmartSMS.configure do |config|
9
8
  # config.api_key = 'd63124354422b046081a44466'
@@ -17,6 +16,8 @@ module SmartSMS
17
16
  @config
18
17
  end
19
18
 
19
+ # Configuration class
20
+ #
20
21
  class Configuration #:nodoc:
21
22
  include ActiveSupport::Configurable
22
23
  config_accessor :api_key # 授权 API KEY
@@ -45,4 +46,4 @@ module SmartSMS
45
46
  config.store_sms_in_local = false
46
47
  config.verification_code_algorithm = :simple
47
48
  end
48
- end
49
+ end
@@ -2,23 +2,25 @@
2
2
  require File.expand_path(File.join(File.dirname(__FILE__), 'model/message'))
3
3
 
4
4
  module SmartSMS
5
+ # Module that will be hooked into ActiveRecord to provide magic methods
6
+ #
5
7
  module HasSmsVerification
6
-
7
8
  def self.included(base)
8
9
  base.send :extend, ClassMethods
9
10
  end
10
11
 
12
+ # Class methods that will be extended
11
13
  module ClassMethods
12
14
 
13
15
  # 在您的Model里面声明这个方法, 以添加SMS短信验证功能
14
16
  # moible_column: mobile 绑定的字段, 用于发送短信
15
- # verification_column: 验证绑定的字段, 用于判断是否以验证
17
+ # verification_column: 验证绑定的字段, 用于判断是否已验证
16
18
  #
17
19
  # Options:
18
20
  # :class_name 自定义的Message类名称. 默认是 `::SmartSMS::Message`
19
21
  # :messages 自定义的Message关联名称. 默认是 `:versions`.
20
22
  #
21
- def has_sms_verification moible_column = :phone, verification_column = :verified_at, options = {}
23
+ def has_sms_verification(moible_column = :phone, verification_column = :verified_at, options = {})
22
24
  send :include, InstanceMethods
23
25
 
24
26
  # 用于判断是否已经验证的字段, Datetime 类型, 例如 :verified_at
@@ -40,33 +42,34 @@ module SmartSMS
40
42
  self.message_class_name = options[:class_name] || '::SmartSMS::Message'
41
43
 
42
44
  if ::ActiveRecord::VERSION::MAJOR >= 4 # Rails 4 里面, 在 `has_many` 声明中定义order lambda的语法
43
- has_many self.messages_association_name,
44
- lambda { order("send_time ASC") },
45
- :class_name => self.message_class_name, :as => :smsable
45
+ has_many messages_association_name,
46
+ -> { order('send_time ASC') },
47
+ class_name: message_class_name,
48
+ as: :smsable
46
49
  else
47
- has_many self.messages_association_name,
48
- :class_name => self.message_class_name,
49
- :as => :smsable,
50
- :order => "send_time ASC"
50
+ has_many messages_association_name,
51
+ class_name: message_class_name,
52
+ as: :smsable,
53
+ order: 'send_time ASC'
51
54
  end
52
55
 
53
56
  end
54
57
  end
55
58
 
59
+ # Instance methods
56
60
  module InstanceMethods
57
-
58
61
  # 非安全verify!方法, 验证成功后会存储成功的结果到数据表中
59
- def verify! code
62
+ def verify!(code)
60
63
  result = verify code
61
64
  if result
62
- self.send("#{self.class.sms_verification_column}=", Time.now)
63
- self.save(validate: false)
65
+ send("#{self.class.sms_verification_column}=", Time.now)
66
+ save(validate: false)
64
67
  end
65
68
  end
66
69
 
67
70
  # 安全verify方法, 用于校验短信验证码是否正确, 返回: true 或 false
68
71
  #
69
- def verify code
72
+ def verify(code)
70
73
  sms = latest_message
71
74
  return false if sms.blank?
72
75
  if SmartSMS.config.store_sms_in_local
@@ -90,16 +93,16 @@ module SmartSMS
90
93
  #
91
94
  def latest_message
92
95
  end_time = Time.now
93
- start_time = end_time - SmartSMS.config.expires_in # the verification code will be expired within 1 hour
96
+ start_time = end_time - SmartSMS.config.expires_in
94
97
  if SmartSMS.config.store_sms_in_local
95
- self.send(self.class.messages_association_name)
96
- .where("send_time >= ? and send_time <= ?", start_time, end_time)
97
- .last
98
+ send(self.class.messages_association_name)
99
+ .where('send_time >= ? and send_time <= ?', start_time, end_time)
100
+ .last
98
101
  else
99
102
  result = SmartSMS.find(
100
103
  start_time: start_time,
101
104
  end_time: end_time,
102
- mobile: self.send(self.class.sms_mobile_column),
105
+ mobile: send(self.class.sms_mobile_column),
103
106
  page_size: 1
104
107
  )
105
108
  result['sms'].first
@@ -108,27 +111,29 @@ module SmartSMS
108
111
 
109
112
  # 发送短信至手机
110
113
  #
111
- def deliver text = SmartSMS::VerificationCode.random
112
- result = SmartSMS.deliver self.send(self.class.sms_mobile_column), text
114
+ def deliver(text = SmartSMS::VerificationCode.random)
115
+ result = SmartSMS.deliver send(self.class.sms_mobile_column), text
113
116
  if result['code'] == 0
114
117
  sms = SmartSMS.find_by_sid(result['result']['sid'])['sms']
115
- if SmartSMS.config.store_sms_in_local
116
- message = self.send(self.messages_association_name).build sms
117
- message.code = text
118
- message.save
119
- else
120
- sms
121
- end
118
+ save_or_return_message sms, text
122
119
  else
123
- self.errors.add :deliver, result
120
+ errors.add :deliver, result
124
121
  false
125
122
  end
126
123
  end
127
124
 
128
- def deliver_fake_sms text = SmartSMS::VerificationCode.random
129
- sms = SmartSMS::FakeSMS.build_fake_sms self.send(self.class.sms_mobile_column), text, SmartSMS.config.company
125
+ def deliver_fake_sms(text = SmartSMS::VerificationCode.random)
126
+ mobile = send(self.class.sms_mobile_column)
127
+ company = SmartSMS.config.company
128
+ sms = SmartSMS::FakeSMS.build_fake_sms mobile, text, company
129
+ save_or_return_message sms, text
130
+ end
131
+
132
+ private
133
+
134
+ def save_or_return_message(sms, text)
130
135
  if SmartSMS.config.store_sms_in_local
131
- message = self.send(self.messages_association_name).build sms
136
+ message = send(self.class.messages_association_name).build sms
132
137
  message.code = text
133
138
  message.save
134
139
  else
@@ -138,4 +143,4 @@ module SmartSMS
138
143
  end
139
144
  end
140
145
  end
141
- end
146
+ end
@@ -1,22 +1,23 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module SmartSMS
4
+ # This will generate fake sms
5
+ #
4
6
  module FakeSMS
5
- extend self
7
+ module_function
6
8
 
7
- def build_fake_sms mobile, code, company
9
+ def build_fake_sms(mobile, code, company)
8
10
  {
9
- "sid" => SecureRandom.uuid,
10
- "mobile" => mobile,
11
- "send_time" => Time.zone.now,
12
- "text" => "您的验证码是#{code}。如非本人操作,请忽略本短信【#{company}】",
13
- "send_status" => "SUCCESS",
14
- "report_status" => "UNKNOWN",
15
- "fee" => 1,
16
- "user_receive_time" => nil,
17
- "error_msg" => nil
11
+ 'sid' => SecureRandom.uuid,
12
+ 'mobile' => mobile,
13
+ 'send_time' => Time.zone.now,
14
+ 'text' => "您的验证码是#{code}。如非本人操作,请忽略本短信【#{company}】",
15
+ 'send_status' => 'SUCCESS',
16
+ 'report_status' => 'UNKNOWN',
17
+ 'fee' => 1,
18
+ 'user_receive_time' => nil,
19
+ 'error_msg' => nil
18
20
  }
19
21
  end
20
-
21
22
  end
22
- end
23
+ end
@@ -1,32 +1,40 @@
1
1
  require 'securerandom'
2
2
 
3
3
  module SmartSMS
4
+ # This module provides some methods to generate random verification code
5
+ # Algorithm:
6
+ # short: Generate short code with 4 numbers
7
+ # simple: Generate simple code with 6 numbers
8
+ # middle: Generate middle complex code of 6 charactors with mixed numbers and letters
9
+ # complex: Generate complex code of 8 charactors with mixed numbers, letters or special charactors
4
10
  module VerificationCode
5
- extend self
11
+ module_function
6
12
 
7
- REGISTERED_ALGORITHMS = [:simple, :middle, :complex]
13
+ REGISTERED_ALGORITHMS = [:short, :simple, :middle, :complex]
8
14
 
9
- def random algorithm = ''
15
+ def random(algorithm = '')
10
16
  algorithm = SmartSMS.config.verification_code_algorithm if algorithm.blank?
11
17
  if REGISTERED_ALGORITHMS.include? algorithm
12
18
  SmartSMS::VerificationCode.send algorithm
13
19
  else
14
- raise NoMethodError
20
+ fail NoMethodError
15
21
  end
16
22
  end
17
23
 
18
- private
24
+ def short
25
+ SecureRandom.random_number.to_s.slice(-4..-1)
26
+ end
19
27
 
20
28
  def simple
21
29
  SecureRandom.random_number.to_s.slice(-6..-1)
22
30
  end
23
31
 
24
32
  def middle
25
- SecureRandom.base64.gsub!(/[^0-9a-zA-Z]/,'').slice(1..6).downcase
33
+ SecureRandom.base64.gsub!(/[^0-9a-zA-Z]/, '').slice(1..6).downcase
26
34
  end
27
35
 
28
36
  def complex
29
37
  SecureRandom.base64.slice(1..8).downcase
30
38
  end
31
39
  end
32
- end
40
+ end
@@ -1,13 +1,13 @@
1
1
  module SmartSMS
2
+ # Message service: methods that are used to manage messages
2
3
  module MessageService
3
-
4
4
  def self.included(base)
5
5
  base.send :extend, ClassMethods
6
6
  end
7
7
 
8
+ # Class methods
8
9
  module ClassMethods
9
-
10
- DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S"
10
+ DATETIME_FORMAT = '%Y-%m-%d %H:%M:%S'
11
11
 
12
12
  # 发送短信到手机, 默认使用模板发送, 提供通用接口支持
13
13
  # phone: 需要接受短信的手机号码
@@ -16,7 +16,7 @@ module SmartSMS
16
16
  # Options:
17
17
  # :method 如若要使用通用短信接口, 需要 :method => :general
18
18
  # :tpl_id 选择发送短信的模板, 默认是2
19
- def deliver phone, content, options = {}
19
+ def deliver(phone, content, options = {})
20
20
  if options[:method] == :general
21
21
  Request.post 'sms/send.json', mobile: phone, text: content, extend: options[:extend]
22
22
  else
@@ -29,20 +29,20 @@ module SmartSMS
29
29
 
30
30
  # 根据sid来查询短信记录
31
31
  #
32
- def find_by_sid sid
32
+ def find_by_sid(sid)
33
33
  Request.post 'sms/get.json', sid: sid
34
34
  end
35
35
 
36
36
  # 参见 `find_messages` 方法
37
- def find options = {}
37
+ def find(options = {})
38
38
  find_messages 'sms/get.json', options
39
39
  end
40
40
 
41
- def get_black_word text = ''
41
+ def get_black_word(text = '')
42
42
  Request.post 'sms/get_black_word.json', text: text
43
43
  end
44
44
 
45
- def get_reply options = {}
45
+ def get_reply(options = {})
46
46
  find_messages 'sms/get_reply.json', options
47
47
  end
48
48
 
@@ -55,7 +55,7 @@ module SmartSMS
55
55
  # page_size: 每页个数,最大100个
56
56
  # mobile: 接收短信的手机号
57
57
  #
58
- def find_messages api, options = {}
58
+ def find_messages(api, options = {})
59
59
  options[:end_time] = Time.now if options[:end_time].blank?
60
60
  options[:start_time] = options[:end_time] - SmartSMS.config.default_interval if options[:start_time].blank?
61
61
  options[:end_time] = parse_time(options[:end_time])
@@ -65,21 +65,23 @@ module SmartSMS
65
65
  Request.post api, options
66
66
  end
67
67
 
68
- def parse_time time = ''
68
+ def parse_time(time = '')
69
69
  if time.present? && time.is_a?(Time)
70
70
  time.strftime DATETIME_FORMAT
71
+ elsif time.is_a? String
72
+ time
71
73
  else
72
74
  ''
73
75
  end
74
76
  end
75
77
 
76
- def parse_content options = {}
78
+ def parse_content(options = {})
77
79
  options[:code] ||= ''
78
80
  options[:company] ||= SmartSMS.config.company
79
81
  SmartSMS.config.template_value.map do |key|
80
- "##{key.to_s}#=#{options[key]}"
82
+ "##{key}#=#{options[key]}"
81
83
  end.join('&')
82
84
  end
83
85
  end
84
86
  end
85
- end
87
+ end
@@ -1,4 +1,6 @@
1
1
  module SmartSMS
2
+ # Message model to store sms messages
3
+ #
2
4
  class Message < ::ActiveRecord::Base
3
5
  self.table_name = 'smart_sms_messages'
4
6
  belongs_to :smsable, polymorphic: true
@@ -3,17 +3,16 @@ require 'net/http'
3
3
  require 'active_support/json'
4
4
 
5
5
  module SmartSMS
6
+ # Module that manage requests
6
7
  module Request
7
- extend self
8
-
9
- def post api, options = {}
8
+ def post(api, options = {})
10
9
  options[:apikey] = SmartSMS.config.api_key
11
10
  uri = URI.join(base_url, api)
12
11
  res = Net::HTTP.post_form(uri, options)
13
12
  result res.body
14
13
  end
15
14
 
16
- def get api, options = {}
15
+ def get(api, options = {})
17
16
  options[:apikey] = SmartSMS.config.api_key
18
17
  uri = URI.join(base_url, api)
19
18
  result Net::HTTP.get(uri, options)
@@ -21,20 +20,22 @@ module SmartSMS
21
20
 
22
21
  private
23
22
 
24
- def result body
23
+ def result(body)
25
24
  begin
26
25
  ActiveSupport::JSON.decode body
27
26
  rescue => e
28
27
  {
29
28
  code: 502,
30
- msg: "内容解析错误",
29
+ msg: '内容解析错误',
31
30
  detail: e.to_s
32
31
  }
33
32
  end
34
33
  end
35
34
 
36
35
  def base_url
37
- "http://yunpian.com/#{SmartSMS.config.api_version.to_s}/"
36
+ "http://yunpian.com/#{SmartSMS.config.api_version}/"
38
37
  end
38
+
39
+ module_function :post, :get, :result, :base_url
39
40
  end
40
- end
41
+ end