aliyun-rails 0.1.17 → 0.1.20

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.
@@ -1,166 +1,166 @@
1
- # frozen_string_literal: true
2
-
3
- require "faraday"
4
- require "securerandom"
5
- require "active_support/all"
6
- require "net/http"
7
-
8
- module Net::HTTPHeader
9
- def capitalize(name)
10
- name
11
- end
12
- private :capitalize
13
- end
14
-
15
- module Aliyun
16
- module Connector
17
- class ROAClient
18
- attr_accessor :endpoint, :api_version, :access_key_id,
19
- :access_key_secret, :security_token, :hostname, :opts
20
-
21
- def initialize(config)
22
- validate config
23
-
24
- self.endpoint = config[:endpoint]
25
- self.api_version = config[:api_version]
26
- self.access_key_id = config[:access_key_id] || Aliyun.access_key_id
27
- self.access_key_secret = config[:access_key_secret] || Aliyun.access_key_secret
28
- self.security_token = config[:security_token]
29
- end
30
-
31
- def request(method:, uri:, params: {}, body: {}, headers: {}, options: {})
32
- # :"Content-Type" => "application/json" to "content-type" => "application/json"
33
- headers.deep_transform_keys! { |key| key.to_s.downcase }
34
- mix_headers = default_headers.merge(headers)
35
-
36
- response = connection.send(method.downcase) do |request|
37
- request.url uri, params
38
- if body
39
- if mix_headers["content-type"].start_with? "application/json"
40
- request_body = body.to_json
41
- elsif mix_headers["content-type"].start_with? "application/x-www-form-urlencoded"
42
- request_body = URI.encode_www_form(body)
43
- else
44
- request_body = body
45
- end
46
- mix_headers["content-md5"] = Digest::MD5.base64digest request_body
47
- mix_headers["content-length"] = request_body.length.to_s
48
- request.body = request_body
49
- end
50
- string2sign = string_to_sign(method, uri, mix_headers, params)
51
- mix_headers[:authorization] = authorization(string2sign)
52
- mix_headers.each { |key, value| request.headers[key] = value }
53
- end
54
-
55
- return response if options.has_key? :raw_body
56
-
57
- response_content_type = response.headers["Content-Type"] || ""
58
- if response_content_type.start_with?("application/json")
59
- if response.status >= 400
60
- result = JSON.parse(response.body)
61
- raise StandardError, "code: #{response.status}, #{result['Message']} requestid: #{result['RequestId']}"
62
- end
63
- end
64
-
65
- if response_content_type.start_with?("text/xml")
66
- result = Hash.from_xml(response.body)
67
- raise ACSError, result["Error"] if result["Error"]
68
- end
69
-
70
- response
71
- end
72
-
73
- def connection(adapter = Faraday.default_adapter)
74
- Faraday.new(url: self.endpoint) { |f| f.adapter adapter }
75
- end
76
-
77
- def get(uri: "", headers: {}, params: {}, options: {})
78
- request(method: :get, uri: uri, params: params, body: {}, headers: headers, options: options)
79
- end
80
-
81
- def post(uri: "", headers: {}, params: {}, body: {}, options: {})
82
- request(method: :post, uri: uri, params: params, body: body, headers: headers, options: options)
83
- end
84
-
85
- def put(uri: "", headers: {}, params: {}, body: {}, options: {})
86
- request(method: :put, uri: uri, params: params, body: body, headers: headers, options: options)
87
- end
88
-
89
- def delete(uri: "", headers: {}, params: {}, options: {})
90
- request(method: :delete, uri: uri, params: params, body: {}, headers: headers, options: options)
91
- end
92
-
93
- def default_headers
94
- default_headers = {
95
- "accept" => "application/json",
96
- "date" => Time.now.httpdate,
97
- "host" => URI(self.endpoint).host,
98
- "x-acs-signature-nonce" => SecureRandom.hex(16),
99
- "x-acs-signature-method" => "HMAC-SHA1",
100
- "x-acs-signature-version" => "1.0",
101
- "x-acs-version" => self.api_version,
102
- "x-sdk-client" => "RUBY(#{RUBY_VERSION})", # FIXME: 如何获取Gem的名称和版本号
103
- "user-agent" => DEFAULT_UA
104
- }
105
- if self.security_token
106
- default_headers["x-acs-accesskey-id"] = self.access_key_id
107
- default_headers["x-acs-security-token"] = self.security_token
108
- end
109
- default_headers
110
- end
111
-
112
- private
113
- def string_to_sign(method, uri, headers, query = {})
114
- header_string = [
115
- method,
116
- headers["accept"],
117
- headers["content-md5"] || "",
118
- headers["content-type"] || "",
119
- headers["date"],
120
- ].join("\n")
121
- "#{header_string}\n#{canonicalized_headers(headers)}#{canonicalized_resource(uri, query)}"
122
- end
123
-
124
- def canonicalized_headers(headers)
125
- headers.keys.select { |key| key.to_s.start_with? "x-acs-" }
126
- .sort.map { |key| "#{key}:#{headers[key].strip}\n" }.join
127
- end
128
-
129
- def canonicalized_resource(uri, query_hash = {})
130
- query_string = query_hash.sort.map { |key, value| "#{key}=#{value}" }.join("&")
131
- query_string.empty? ? uri : "#{uri}?#{query_string}"
132
- end
133
-
134
- def authorization(string_to_sign)
135
- "acs #{self.access_key_id}:#{signature(string_to_sign)}"
136
- end
137
-
138
- def signature(string_to_sign)
139
- Base64.encode64(OpenSSL::HMAC.digest("sha1", self.access_key_secret, string_to_sign)).strip
140
- end
141
-
142
- def validate(config)
143
- raise ArgumentError, 'must pass "config"' unless config
144
- raise ArgumentError, 'must pass "config[:endpoint]"' unless config[:endpoint]
145
- unless config[:endpoint].start_with?("http://") || config[:endpoint].start_with?("https://")
146
- raise ArgumentError, '"config.endpoint" must starts with \'https://\' or \'http://\'.'
147
- end
148
- raise ArgumentError, 'must pass "config[:api_version]"' unless config[:api_version]
149
- raise ArgumentError, 'must pass "config[:access_key_id]"' unless config[:access_key_id]
150
- raise ArgumentError, 'must pass "config[:access_key_secret]"' unless config[:access_key_secret]
151
- end
152
-
153
- class ACSError < StandardError
154
- attr_accessor :code
155
-
156
- def initialize(error)
157
- self.code = error["Code"]
158
- message = error["Message"]
159
- host_id = error["HostId"]
160
- request_id = error["RequestId"]
161
- super("#{message} host_id: #{host_id}, request_id: #{request_id}")
162
- end
163
- end
164
- end
165
- end
166
- end
1
+ # frozen_string_literal: true
2
+
3
+ require "faraday"
4
+ require "securerandom"
5
+ require "active_support/all"
6
+ require "net/http"
7
+
8
+ module Net::HTTPHeader
9
+ def capitalize(name)
10
+ name
11
+ end
12
+ private :capitalize
13
+ end
14
+
15
+ module Aliyun
16
+ module Connector
17
+ class ROAClient
18
+ attr_accessor :endpoint, :api_version, :access_key_id,
19
+ :access_key_secret, :security_token, :hostname, :opts
20
+
21
+ def initialize(config)
22
+ validate config
23
+
24
+ self.endpoint = config[:endpoint]
25
+ self.api_version = config[:api_version]
26
+ self.access_key_id = config[:access_key_id]
27
+ self.access_key_secret = config[:access_key_secret]
28
+ self.security_token = config[:security_token]
29
+ end
30
+
31
+ def request(method:, uri:, params: {}, body: {}, headers: {}, options: {})
32
+ # :"Content-Type" => "application/json" to "content-type" => "application/json"
33
+ headers.deep_transform_keys! { |key| key.to_s.downcase }
34
+ mix_headers = default_headers.merge(headers)
35
+
36
+ response = connection.send(method.downcase) do |request|
37
+ request.url uri, params
38
+ if body
39
+ if mix_headers["content-type"].start_with? "application/json"
40
+ request_body = body.to_json
41
+ elsif mix_headers["content-type"].start_with? "application/x-www-form-urlencoded"
42
+ request_body = URI.encode_www_form(body)
43
+ else
44
+ request_body = body
45
+ end
46
+ mix_headers["content-md5"] = Digest::MD5.base64digest request_body
47
+ mix_headers["content-length"] = request_body.length.to_s
48
+ request.body = request_body
49
+ end
50
+ string2sign = string_to_sign(method, uri, mix_headers, params)
51
+ mix_headers[:authorization] = authorization(string2sign)
52
+ mix_headers.each { |key, value| request.headers[key] = value }
53
+ end
54
+
55
+ return response if options.has_key? :raw_body
56
+
57
+ response_content_type = response.headers["Content-Type"] || ""
58
+ if response_content_type.start_with?("application/json")
59
+ if response.status >= 400
60
+ result = JSON.parse(response.body)
61
+ raise StandardError, "code: #{response.status}, #{result['Message']} requestid: #{result['RequestId']}"
62
+ end
63
+ end
64
+
65
+ if response_content_type.start_with?("text/xml")
66
+ result = Hash.from_xml(response.body)
67
+ raise ACSError, result["Error"] if result["Error"]
68
+ end
69
+
70
+ response
71
+ end
72
+
73
+ def connection(adapter = Faraday.default_adapter)
74
+ Faraday.new(url: self.endpoint) { |f| f.adapter adapter }
75
+ end
76
+
77
+ def get(uri: "", headers: {}, params: {}, options: {})
78
+ request(method: :get, uri: uri, params: params, body: {}, headers: headers, options: options)
79
+ end
80
+
81
+ def post(uri: "", headers: {}, params: {}, body: {}, options: {})
82
+ request(method: :post, uri: uri, params: params, body: body, headers: headers, options: options)
83
+ end
84
+
85
+ def put(uri: "", headers: {}, params: {}, body: {}, options: {})
86
+ request(method: :put, uri: uri, params: params, body: body, headers: headers, options: options)
87
+ end
88
+
89
+ def delete(uri: "", headers: {}, params: {}, options: {})
90
+ request(method: :delete, uri: uri, params: params, body: {}, headers: headers, options: options)
91
+ end
92
+
93
+ def default_headers
94
+ default_headers = {
95
+ "accept" => "application/json",
96
+ "date" => Time.now.httpdate,
97
+ "host" => URI(self.endpoint).host,
98
+ "x-acs-signature-nonce" => SecureRandom.hex(16),
99
+ "x-acs-signature-method" => "HMAC-SHA1",
100
+ "x-acs-signature-version" => "1.0",
101
+ "x-acs-version" => self.api_version,
102
+ "x-sdk-client" => "RUBY(#{RUBY_VERSION})", # FIXME: 如何获取Gem的名称和版本号
103
+ "user-agent" => DEFAULT_UA
104
+ }
105
+ if self.security_token
106
+ default_headers["x-acs-accesskey-id"] = self.access_key_id
107
+ default_headers["x-acs-security-token"] = self.security_token
108
+ end
109
+ default_headers
110
+ end
111
+
112
+ private
113
+ def string_to_sign(method, uri, headers, query = {})
114
+ header_string = [
115
+ method,
116
+ headers["accept"],
117
+ headers["content-md5"] || "",
118
+ headers["content-type"] || "",
119
+ headers["date"],
120
+ ].join("\n")
121
+ "#{header_string}\n#{canonicalized_headers(headers)}#{canonicalized_resource(uri, query)}"
122
+ end
123
+
124
+ def canonicalized_headers(headers)
125
+ headers.keys.select { |key| key.to_s.start_with? "x-acs-" }
126
+ .sort.map { |key| "#{key}:#{headers[key].strip}\n" }.join
127
+ end
128
+
129
+ def canonicalized_resource(uri, query_hash = {})
130
+ query_string = query_hash.sort.map { |key, value| "#{key}=#{value}" }.join("&")
131
+ query_string.empty? ? uri : "#{uri}?#{query_string}"
132
+ end
133
+
134
+ def authorization(string_to_sign)
135
+ "acs #{self.access_key_id}:#{signature(string_to_sign)}"
136
+ end
137
+
138
+ def signature(string_to_sign)
139
+ Base64.encode64(OpenSSL::HMAC.digest("sha1", self.access_key_secret, string_to_sign)).strip
140
+ end
141
+
142
+ def validate(config)
143
+ raise ArgumentError, 'must pass "config"' unless config
144
+ raise ArgumentError, 'must pass "config[:endpoint]"' unless config[:endpoint]
145
+ unless config[:endpoint].start_with?("http://") || config[:endpoint].start_with?("https://")
146
+ raise ArgumentError, '"config.endpoint" must starts with \'https://\' or \'http://\'.'
147
+ end
148
+ raise ArgumentError, 'must pass "config[:api_version]"' unless config[:api_version]
149
+ raise ArgumentError, 'must pass "config[:access_key_id]"' unless config[:access_key_id]
150
+ raise ArgumentError, 'must pass "config[:access_key_secret]"' unless config[:access_key_secret]
151
+ end
152
+
153
+ class ACSError < StandardError
154
+ attr_accessor :code
155
+
156
+ def initialize(error)
157
+ self.code = error["Code"]
158
+ message = error["Message"]
159
+ host_id = error["HostId"]
160
+ request_id = error["RequestId"]
161
+ super("#{message} host_id: #{host_id}, request_id: #{request_id}")
162
+ end
163
+ end
164
+ end
165
+ end
166
+ end
@@ -1,116 +1,148 @@
1
- # frozen_string_literal: true
2
-
3
- require "set"
4
- require "openssl"
5
- require "faraday"
6
- require "erb"
7
- require "active_support/all"
8
-
9
- module Aliyun
10
- module Connector
11
- class RPCClient
12
- attr_accessor :endpoint, :api_version, :access_key_id, :access_key_secret,
13
- :security_token, :codes, :opts, :verbose
14
-
15
- # 对象初始化属性
16
- def initialize(config = {}, verbose = false)
17
- validate config
18
-
19
- self.endpoint = config[:endpoint]
20
- self.api_version = config[:api_version]
21
- self.access_key_id = config[:access_key_id] || Aliyun.access_key_id
22
- self.access_key_secret = config[:access_key_secret] || Aliyun.access_key_secret
23
- self.security_token = config[:security_token]
24
- self.opts = config[:opts] || {}
25
- self.verbose = verbose.instance_of?(TrueClass) && verbose
26
-
27
- self.codes = Set.new [200, "200", "OK", "Success"]
28
- self.codes.merge config[:codes] if config[:codes]
29
- end
30
-
31
- # 通用请求接口
32
- def request(action:, params: {}, opts: {})
33
- opts = self.opts.merge(opts)
34
- action = action.upcase_first if opts[:format_action]
35
- params = format_params(params) unless opts[:format_params]
36
- defaults = default_params
37
- params = { Action: action }.merge(defaults).merge(params)
38
- method = (opts[:method] || "GET").upcase
39
- sign = "#{method}&#{encode('/')}&#{encode(params.to_query)}"
40
- secret = "#{self.access_key_secret}&"
41
- signature = Base64.encode64(OpenSSL::HMAC.digest("sha1", secret, sign)).strip
42
- params["Signature"] = signature
43
-
44
- # 转换为 query 样式
45
- query_string = params.to_query
46
-
47
- # 特殊处理 POST
48
- uri = opts[:method] == "POST" ? "/" : "/?#{query_string}"
49
-
50
- # 初始化会话
51
- response = connection.send(method.downcase, uri) do |r|
52
- if opts[:method] == "POST"
53
- r.headers["Content-Type"] = "application/x-www-form-urlencoded"
54
- r.body = query_string
55
- end
56
- r.headers["User-Agent"] = DEFAULT_UA
57
- end
58
-
59
- # 解析接口响应
60
- response_body = JSON.parse(response.body)
61
- if response_body["Code"] && !response_body["Code"].to_s.empty? && !self.codes.include?(response_body["Code"])
62
- raise StandardError, "Code: #{response_body['Code']}, Message: #{response_body['Message']}, URL: #{uri}"
63
- end
64
-
65
- response_body
66
- end
67
-
68
- private
69
- def connection(adapter = Faraday.default_adapter)
70
- Faraday.new(url: self.endpoint) { |f| f.adapter adapter }
71
- end
72
-
73
- # 设置缺省参数
74
- def default_params
75
- params = {
76
- Format: "JSON",
77
- SignatureMethod: "HMAC-SHA1",
78
- SignatureNonce: SecureRandom.hex(8),
79
- SignatureVersion: "1.0",
80
- Timestamp: Time.now.utc.strftime("%Y-%m-%dT%H:%M:%SZ"),
81
- AccessKeyId: self.access_key_id,
82
- Version: self.api_version,
83
- }
84
- params[:SecurityToken] = self.security_token if self.security_token.present?
85
- params
86
- end
87
-
88
- # 消息签名需要
89
- def encode(input)
90
- ERB::Util.url_encode input
91
- end
92
-
93
- # 转换 HASH key 样式
94
- def format_params(param_hash)
95
- param_hash.keys.each { |key| param_hash[(key.to_s.upcase_first).to_sym] = param_hash.delete key }
96
- param_hash
97
- end
98
-
99
- def validate(config = {})
100
- config.with_indifferent_access
101
- raise ArgumentError, 'must pass "config"' unless config
102
- raise ArgumentError, 'must pass "config[:endpoint]"' unless config[:endpoint]
103
- unless config[:endpoint].match?(/^http[s]?:/i)
104
- raise ArgumentError, '"config.endpoint" must starts with \'https://\' or \'http://\'.'
105
- end
106
- raise ArgumentError, 'must pass "config[:api_version]"' unless config[:api_version]
107
- unless config[:access_key_id] || Aliyun.access_key_id
108
- raise ArgumentError, 'must pass "config[:access_key_id]" or define "Aliyun.access_key_id"'
109
- end
110
- unless config[:access_key_secret] || Aliyun.access_key_secret
111
- raise ArgumentError, 'must pass "config[:access_key_secret]" or define "Aliyun.access_key_secret"'
112
- end
113
- end
114
- end
115
- end
116
- end
1
+ require "set"
2
+ require "openssl"
3
+ require "faraday"
4
+ require "active_support/all"
5
+
6
+ module Aliyun
7
+ module Connector
8
+ class RPCClient
9
+
10
+ attr_accessor :endpoint, :api_version, :access_key_id, :access_key_secret,
11
+ :security_token, :codes, :opts, :verbose
12
+
13
+ # 对象初始化属性
14
+ def initialize(config, verbose = false)
15
+
16
+ validate config
17
+
18
+ self.endpoint = config[:endpoint]
19
+ self.api_version = config[:api_version]
20
+ self.access_key_id = config[:access_key_id] || Aliyun.access_key_id
21
+ self.access_key_secret = config[:access_key_secret] || Aliyun.access_key_secret
22
+ self.security_token = config[:security_token]
23
+ self.opts = config[:opts] || {}
24
+ self.verbose = verbose.instance_of?(TrueClass) && verbose
25
+
26
+ self.codes = Set.new [200, "200", "OK", "Success"]
27
+ self.codes.merge config[:codes] if config[:codes]
28
+ end
29
+
30
+ # 通用请求接口
31
+ def request(action:, params: {}, opts: {})
32
+ opts = self.opts.merge(opts)
33
+ action = action.upcase_first if opts[:format_action]
34
+ params = format_params(params) unless opts[:format_params]
35
+ defaults = default_params
36
+ params = { Action: action }.merge(defaults).merge(params)
37
+ method = (opts[:method] || "GET").upcase
38
+ normalized = normalize(params)
39
+ canonicalized = canonicalize(normalized)
40
+ string_to_sign = "#{method}&#{encode('/')}&#{encode(canonicalized)}"
41
+ secret = "#{self.access_key_secret}&"
42
+ signature = Base64.encode64(OpenSSL::HMAC.digest("sha1", secret, string_to_sign)).strip
43
+ normalized.push(["Signature", encode(signature)])
44
+
45
+ # 转换为 query 样式
46
+ querystring = canonicalize(normalized)
47
+
48
+ # 特殊处理 POST
49
+ uri = opts[:method] == "POST" ? "/" : "/?#{querystring}"
50
+
51
+ # 初始化会话
52
+ response = connection.send(method.downcase, uri) do |request|
53
+ if opts[:method] == "POST"
54
+ request.headers["Content-Type"] = "application/x-www-form-urlencoded"
55
+ request.body = querystring
56
+ end
57
+ request.headers["User-Agent"] = DEFAULT_UA
58
+ end
59
+
60
+ # 解析接口响应
61
+ response_body = JSON.parse(response.body)
62
+ if response_body["Code"] && !response_body["Code"].to_s.empty? && !self.codes.include?(response_body["Code"])
63
+ raise StandardError, "Code: #{response_body['Code']}, Message: #{response_body['Message']}, URL: #{uri}"
64
+ end
65
+
66
+ response_body
67
+ end
68
+
69
+ private
70
+ def connection(adapter = Faraday.default_adapter)
71
+ Faraday.new(url: self.endpoint) { |f| f.adapter adapter }
72
+ end
73
+
74
+ # 设置缺省参数
75
+ def default_params
76
+ default_params = {
77
+ "Format" => "JSON",
78
+ "SignatureMethod" => "HMAC-SHA1",
79
+ "SignatureNonce" => SecureRandom.hex(16),
80
+ "SignatureVersion" => "1.0",
81
+ "Timestamp" => Time.now.utc.strftime("%Y-%m-%dT%H:%M:%SZ"),
82
+ "AccessKeyId" => self.access_key_id,
83
+ "Version" => self.api_version,
84
+ }
85
+ default_params["SecurityToken"] = self.security_token if self.security_token
86
+ default_params
87
+ end
88
+
89
+ # 消息签名需要
90
+ def encode(string)
91
+ ERB::Util.url_encode(string)
92
+ end
93
+
94
+ # 转换 HASH key 样式
95
+ def format_params(param_hash)
96
+ param_hash.keys.each { |key| param_hash[(key.to_s.upcase_first).to_sym] = param_hash.delete key }
97
+ param_hash
98
+ end
99
+
100
+ def replace_repeat_list(target, key, repeat)
101
+ repeat.each_with_index do |item, index|
102
+ if item && item.instance_of?(Hash)
103
+ item.each_key { |k| target["#{key}.#{index.next}.#{k}"] = item[k] }
104
+ else
105
+ target["#{key}.#{index.next}"] = item
106
+ end
107
+ end
108
+ target
109
+ end
110
+
111
+ def flat_params(params)
112
+ target = {}
113
+ params.each do |key, value|
114
+ if value.instance_of?(Array)
115
+ replace_repeat_list(target, key, value)
116
+ else
117
+ target[key.to_s] = value
118
+ end
119
+ end
120
+ target
121
+ end
122
+
123
+ def normalize(params)
124
+ flat_params(params).sort.to_h.map { |key, value| [encode(key), encode(value)] }
125
+ end
126
+
127
+ def canonicalize(normalized)
128
+ normalized.map { |element| "#{element.first}=#{element.last}" }.join("&")
129
+ end
130
+
131
+ def validate(config = {})
132
+ config.with_indifferent_access
133
+ raise ArgumentError, 'must pass "config"' unless config
134
+ raise ArgumentError, 'must pass "config[:endpoint]"' unless config[:endpoint]
135
+ unless config[:endpoint].match?(/^http[s]?:/i)
136
+ raise ArgumentError, '"config.endpoint" must starts with \'https://\' or \'http://\'.'
137
+ end
138
+ raise ArgumentError, 'must pass "config[:api_version]"' unless config[:api_version]
139
+ unless config[:access_key_id] || Aliyun.access_key_id
140
+ raise ArgumentError, 'must pass "config[:access_key_id]" or define "Aliyun.access_key_id"'
141
+ end
142
+ unless config[:access_key_secret] || Aliyun.access_key_secret
143
+ raise ArgumentError, 'must pass "config[:access_key_secret]" or define "Aliyun.access_key_secret"'
144
+ end
145
+ end
146
+ end
147
+ end
148
+ end
data/lib/aliyun/dysms.rb CHANGED
@@ -1,25 +1,25 @@
1
- # frozen_string_literal: true
2
-
3
- module Aliyun
4
- class Dysms < Aliyun::Connector::RPCClient
5
- # 本产品(Dysmsapi/2017-05-25)的OpenAPI采用RPC签名风格,签名细节参见签名机制说明。
6
- # 我们已经为开发者封装了常见编程语言的SDK,开发者可通过下载SDK直接调用本产品OpenAPI而无需关心技术细节。
7
- def initialize(config = {}, verbose = nil)
8
- config[:endpoint] ||= "http://dysmsapi.aliyuncs.com"
9
- config[:api_version] ||= "2017-05-25"
10
- super(config, verbose)
11
- end
12
-
13
- # 发送短信,发送前要申请短信签名和短信模板,并确保签名和模板已审核通过。
14
- def send_sms(phone_numbers, template_code, template_param, sign_name = "")
15
- params = {
16
- PhoneNumbers: phone_numbers,
17
- SignName: sign_name,
18
- TemplateCode: template_code,
19
- TemplateParam: template_param.to_json
20
- }
21
- opts = { method: "POST", timeout: 15000 }
22
- request(action: "SendSms", params: params, opts: opts)
23
- end
24
- end
25
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Aliyun
4
+ class Dysms < Aliyun::Connector::RPCClient
5
+ # 本产品(Dysmsapi/2017-05-25)的OpenAPI采用RPC签名风格,签名细节参见签名机制说明。
6
+ # 我们已经为开发者封装了常见编程语言的SDK,开发者可通过下载SDK直接调用本产品OpenAPI而无需关心技术细节。
7
+ def initialize(config = {}, verbose = nil)
8
+ config[:endpoint] ||= "http://dysmsapi.aliyuncs.com"
9
+ config[:api_version] ||= "2017-05-25"
10
+ super(config, verbose)
11
+ end
12
+
13
+ # 发送短信,发送前要申请短信签名和短信模板,并确保签名和模板已审核通过。
14
+ def send_sms(phone_numbers, template_code, template_param, sign_name = "")
15
+ params = {
16
+ PhoneNumbers: phone_numbers,
17
+ SignName: sign_name,
18
+ TemplateCode: template_code,
19
+ TemplateParam: template_param.to_json
20
+ }
21
+ opts = { method: "POST", timeout: 15000 }
22
+ request(action: "SendSms", params: params, opts: opts)
23
+ end
24
+ end
25
+ end