Skip to content

Instantly share code, notes, and snippets.

@songjiz
Created May 1, 2020 15:02
Show Gist options
  • Save songjiz/c04f4f5b47f40ef2e2f32489b0ea2bcd to your computer and use it in GitHub Desktop.
Save songjiz/c04f4f5b47f40ef2e2f32489b0ea2bcd to your computer and use it in GitHub Desktop.
require 'base64'
require 'json'
require 'net/https'
require 'openssl'
require 'securerandom'
require 'time'
require 'uri'
module Aliyun
class SMS
class Error < StandardError
attr_reader :code, :message
attr_reader :request_id, :recommend
attr_reader :host_id
def initialize(code:, message:, **options)
@code = code
@message = message
@request_id = options[:request_id]
@recommend = options[:recommend]
@host_id = options[:host_id]
end
end
API_ENDPOINT = 'https://dysmsapi.aliyuncs.com'
attr_accessor :access_key_id, :access_key_secret
attr_accessor :signature_method, :signature_version
attr_accessor :region_id, :format
attr_accessor :sign_name, :version
def initialize(access_key_id:, access_key_secret:, **options)
@access_key_id = access_key_id
@access_key_secret = access_key_secret
@region_id = options[:region_id] || 'cn-hangzhou'
@format = options[:format] || 'json'
@signature_method = options[:signature_method] || 'HMAC-SHA1'
@signature_version = options[:signature_version] || '1.0'
@version = options[:version] || '2017-05-25'
@sign_name = options[:sign_name]
end
def deliver(phone_numbers:, template_code:, template_param: {}, sms_up_extend_code: nil, out_id: nil, sign_name: nil)
params = {
'PhoneNumbers' => Array(phone_numbers).join(','),
'SignName' => sign_name || self.sign_name,
'TemplateCode' => template_code,
'TemplateParam' => JSON.dump(template_param),
'Action' => 'SendSms',
'OutId' => out_id || '',
'SmsUpExtendCode' => sms_up_extend_code || '',
}
http_get API_ENDPOINT, params
end
def lookup(phone_number:, send_date: nil, biz_id: nil, page: 1, page_size: 50)
params = {
'CurrentPage' => page,
'PageSize' => page_size,
'PhoneNumber' => phone_number,
'SendDate' => Time.parse((send_date || Time.now).to_s).strftime('%Y%m%d'),
'Action' => 'QuerySendDetails',
'BizId' => biz_id || ''
}
http_get API_ENDPOINT, params
end
private
def default_params
{
'AccessKeyId' => access_key_id,
'RegionId' => region_id,
'Format' => format,
'SignatureMethod' => signature_method,
'SignatureVersion' => signature_version,
'SignatureNonce' => generate_nonce,
'Timestamp' => Time.now.utc.iso8601,
'Version' => version
}
end
def generate_nonce
SecureRandom.uuid.downcase
end
def generate_signature(params, http_method = 'GET')
ksorted = params.sort
query = URI.encode_www_form(ksorted)
plain = "#{http_method}&#{URI.encode_www_form_component('/')}&#{URI.encode_www_form_component(query)}"
base64 = Base64.encode64(OpenSSL::HMAC.digest('sha1', access_key_secret + '&', plain))
base64.chomp
end
def build_http(uri)
Net::HTTP.new(uri.host, uri.port).tap do |http|
http.use_ssl = uri.scheme == 'https'
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
http.set_debug_output $stdout
end
end
def http_get(endpoint, params)
params = params.merge(default_params)
params['Signature'] = generate_signature(params)
uri = URI(endpoint)
uri.query = URI.encode_www_form(params)
http = build_http(uri)
req = Net::HTTP::Get.new(uri.request_uri)
res = http.request(req)
result = JSON.parse(res.body)
if res.code == '200' && result['Code'] == 'OK'
block_given? ? yield(result) : result
else
raise Error.new(
code: result['Code'],
message: result['Message'],
request_id: result['RequestId'],
recommend: result['Recommend'],
host_id: result['HostId']
)
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment