Commit f6f90316 by lra

阿里大鱼短信发送优化和语音验证码 语音通知添加

parent c2aa3091
...@@ -30,49 +30,103 @@ class SmsSender ...@@ -30,49 +30,103 @@ class SmsSender
SOURCES = %w(taobao zucp) SOURCES = %w(taobao zucp)
attr_accessor :source, :template_code attr_accessor :source, :source_config, :template_code, :attrs
def initialize(options = {}) def initialize(opts = {})
options[:source] = redis.get('sms:source') || SOURCES.first if options[:source].blank? self.attrs = HashWithIndifferentAccess.new(opts)
return unless options[:source].in?(SOURCES)
if load_config.present? && load_config[options[:source]].present? assign_source
options = load_config[options[:source]].merge(options) extend_attrs
end return unless attrs[:source]
options = HashWithIndifferentAccess.new(options)
if options[:source].eql? 'zucp' send("#{attrs[:source].to_s}_init")
@source = "Sms/#{attrs[:source]}".camelize.constantize.new(attrs)
end
if options[:template_code].present? def assign_source
templates = backend(I18n.locale => {'sms_zucp_templates' => load_config[:zucp][:templates]}) return if attrs[:source]
I18n.backend = I18n::Backend::Chain.new(templates)
options.merge!(content: I18n.t("sms_zucp_templates.#{options[:template_code].to_s.gsub('.', '_')}", options[:content_params])) attrs[:source] = redis.get('sms:source') || SOURCES.first
end return unless attrs[:source].in?(SOURCES)
end
elsif options[:source].eql? 'taobao' def extend_attrs
return unless load_config.present?
if options[:template_code].present? self.source_config = load_config[attrs[:source]]
options.merge!(sms_template_code: load_config[:taobao][:templates][options[:template_code].to_s.gsub('.', '_')]) return unless source_config.present?
options.merge!(sms_param: options[:content_params])
end
end self.attrs = source_config.merge(attrs)
end
def zucp_init
return unless attrs[:template_code].present?
return unless source_config.present?
@source = "Sms/#{options[:source]}".camelize.constantize.new(options) templates = backend(I18n.locale => {
'sms_zucp_templates' => source_config[:templates]
})
I18n.backend = I18n::Backend::Chain.new(templates)
zucp_template_code = "sms_zucp_templates.#{attrs[:template_code].to_s.gsub('.', '_')}"
attrs.merge!(content: I18n.t(zucp_template_code, attrs[:content_params]))
end
def taobao_init
return unless attrs[:template_code].present?
return unless source_config.present?
template_code = attrs[:template_code].to_s.gsub('.', '_')
taobao_template_code = source_config[:templates][template_code] rescue nil
attrs.merge!({
template_code: taobao_template_code,
param: attrs[:content_params]
})
end end
def singleSend(number) def singleSend(number)
return unless @source return unless @source
return unless number.present?
@source.singleSend(number) numbers = number_regroup(number)
return unless numbers.present?
@source.single_send(numbers)
end end
def batchSend(numbers) def batchSend(numbers)
return unless @source return unless @source
_numbers = numbers.is_a?(String) ? numbers.split(',') : (numbers.is_a?(Array) ? numbers : [])
_numbers = _numbers.compact.uniq numbers = number_regroup(numbers)
@source.batchSend(_numbers) return unless numbers.present?
@source.batch_send(numbers)
end
# 语音验证码
def text_to_voice_verify(number)
return unless @source
numbers = number_regroup(number)
return unless numbers.present?
@source.tts_num_singlecall(numbers, 'verify')
end
# 语音通知
def text_to_voice_notify(number)
return unless @source
numbers = number_regroup(number)
return unless numbers.present?
@source.tts_num_singlecall(numbers, 'notify')
end
def number_regroup(number)
return number.split(',') if number.is_a?(String)
return number if number.is_a?(Array)
[]
end end
protected protected
...@@ -90,7 +144,8 @@ if defined? ::Rails ...@@ -90,7 +144,8 @@ if defined? ::Rails
module Rails module Rails
class Railtie < ::Rails::Railtie class Railtie < ::Rails::Railtie
rake_tasks do rake_tasks do
load "tasks/sms.rake" # import "/Users/lihui/workplace/demo/rails/gems/sms/lib/tasks/sms.rake"
load 'tasks/sms.rake'
end end
end end
end end
......
...@@ -5,62 +5,91 @@ require 'net/http' ...@@ -5,62 +5,91 @@ require 'net/http'
module Sms module Sms
class Taobao class Taobao
attr_accessor :app_secret, :app_key, :sms_free_sign_name, :sms_template_code, :sms_param attr_accessor :app_secret, :app_key,
:sms_free_sign_name, :called_show_verify_nums, :called_show_notify_nums,
:template_code, :param,
:custom_params, :request_params
def initialize(options = {}) def initialize(options = {})
self.app_secret = options[:app_secret] options.each{|k, v|
self.app_key = options[:app_key] next unless respond_to?(k)
self.sms_free_sign_name = options[:sms_free_sign_name] self.send("#{k.to_s}=", v)
self.sms_template_code = options[:sms_template_code] }
self.sms_param = options[:sms_param] || {}
end end
def singleSend(number) def single_send(number)
send(number.split) sms_num_send(number.split)
end end
def batchSend(numbers) def batch_send(numbers)
send(numbers) sms_num_send(numbers)
end end
def defaultParams(numbers) def public_params
{ {
method: 'alibaba.aliqin.fc.sms.num.send', app_key: self.app_key,
app_key: self.app_key, timestamp: Time.now.strftime("%Y-%m-%d %H:%M:%S"),
timestamp: Time.now.strftime("%Y-%m-%d %H:%M:%S"), format: 'json',
format: 'json', v: 2.0,
v: 2.0, sign_method: 'md5',
sign_method: 'md5',
sms_type: 'normal',
sms_free_sign_name: self.sms_free_sign_name,
rec_num: numbers.join(','),
sms_param: self.sms_param.to_json,
sms_template_code: self.sms_template_code
} }
end end
def generate_sign(params) def extend_params
str = params.to_a.map{|m| m.map(&:to_s).join }.sort.join params = public_params.merge(self.custom_params)
self.request_params = params.merge(sign: generate_sign(params))
end
def generate_sign(opts = {})
str = opts.to_a.map{|m| m.map(&:to_s).join }.sort.join
Digest::MD5.hexdigest("#{app_secret.to_s}#{str}#{app_secret.to_s}").upcase Digest::MD5.hexdigest("#{app_secret.to_s}#{str}#{app_secret.to_s}").upcase
end end
def send(numbers) def sms_num_send(numbers)
params = defaultParams(numbers) self.custom_params = {
params = params.merge(sign: generate_sign(params)) method: 'alibaba.aliqin.fc.sms.num.send',
data = request_api(params) rec_num: numbers.join(','),
data = JSON.parse(data.body) sms_param: param.to_json,
puts "data ************* #{data}" sms_template_code: template_code,
if data['alibaba_aliqin_fc_sms_num_send_response']['result']['success'] sms_type: 'normal',
data sms_free_sign_name: self.sms_free_sign_name
else }
false
end post
rescue => e
false
end end
def request_api(params) def tts_num_singlecall(numbers, type = 'notify')
Net::HTTP.post_form(URI.parse('http://gw.api.taobao.com/router/rest'), params) called_show_nums = send("called_show_#{type}_nums")
size = called_show_nums.size
self.custom_params = {
method: 'alibaba.aliqin.fc.tts.num.singlecall',
called_num: numbers.join(','),
called_show_num: called_show_nums[rand(1..size)],
tts_param: param.to_json,
tts_code: template_code
}
post
end
def post
res = Net::HTTP.post_form(URI.parse('http://gw.api.taobao.com/router/rest'), extend_params)
puts "#{request_params[:method]} request params: #{request_params.inspect}"
data = res.body
data = JSON.parse(data) if data.is_a? String
puts "#{request_params[:method]} request result: #{data.inspect}"
result = HashWithIndifferentAccess.new data
keys = result.keys
return if 'error_response'.in?(keys)
key = "#{request_params[:method].gsub(/\./, '_')}_response"
return unless key.in?(keys) && keys.size == 1
result[key][:err_code].to_i.zero?
end end
end end
......
module Sms module Sms
VERSION = "0.1.0" VERSION = "0.1.1"
end end
...@@ -39,7 +39,7 @@ module Sms ...@@ -39,7 +39,7 @@ module Sms
end end
# 批量发送 numbers是个数组 # 批量发送 numbers是个数组
def batchSend(numbers) def batch_send(numbers)
params = defaultParams(numbers) params = defaultParams(numbers)
data = send(params) data = send(params)
puts "data ************* #{data}" puts "data ************* #{data}"
...@@ -55,7 +55,7 @@ module Sms ...@@ -55,7 +55,7 @@ module Sms
end end
# 单次发送(用户名,密码,接收方号码,内容) # 单次发送(用户名,密码,接收方号码,内容)
def singleSend(number) def single_send(number)
params = defaultParams(number.split) params = defaultParams(number.split)
data = send(params) data = send(params)
# VcoolineLog::SmsApi.add("sms api singleSend data: #{data}") # VcoolineLog::SmsApi.add("sms api singleSend data: #{data}")
......
namespace :sms do namespace :sms do
desc 'create default sms config file'
task :create_default_config_file do task :create_default_config_file do
unless File.exist?("#{::Rails.root}/config/sms.yml") unless File.exist?("#{::Rails.root}/config/sms.yml")
FileUtils.cp(File.expand_path("../../templates/sms.yml", __FILE__), "#{::Rails.root}/config/sms.yml") FileUtils.cp(File.expand_path("../../templates/sms.yml", __FILE__), "#{::Rails.root}/config/sms.yml")
......
...@@ -12,6 +12,12 @@ defaults: &defaults ...@@ -12,6 +12,12 @@ defaults: &defaults
app_secret: xxxx app_secret: xxxx
app_key: xxxx app_key: xxxx
sms_free_sign_name: xxxx sms_free_sign_name: xxxx
called_show_verify_nums:
- xxx1
- xxx2
called_show_notify_nums:
- xxx1
- xxx2
templates: templates:
devise_supplier_applies_otp_code_confirm: xxxx devise_supplier_applies_otp_code_confirm: xxxx
devise_passwords_otp_code_confirm: xxxx devise_passwords_otp_code_confirm: xxxx
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment