yhsd_api 0.0.3
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.
- checksums.yaml +7 -0
- data/.gitignore +15 -0
- data/.travis.yml +5 -0
- data/ChangeLog.md +54 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +242 -0
- data/Rakefile +2 -0
- data/lib/yhsd_api/configuration.rb +48 -0
- data/lib/yhsd_api/exception.rb +41 -0
- data/lib/yhsd_api/helper.rb +78 -0
- data/lib/yhsd_api/http.rb +135 -0
- data/lib/yhsd_api/private_app.rb +114 -0
- data/lib/yhsd_api/public_app.rb +124 -0
- data/lib/yhsd_api/resources/account.rb +25 -0
- data/lib/yhsd_api/resources/asset.rb +37 -0
- data/lib/yhsd_api/resources/base.rb +25 -0
- data/lib/yhsd_api/resources/city.rb +25 -0
- data/lib/yhsd_api/resources/country.rb +25 -0
- data/lib/yhsd_api/resources/customer.rb +43 -0
- data/lib/yhsd_api/resources/customer_address.rb +43 -0
- data/lib/yhsd_api/resources/district.rb +25 -0
- data/lib/yhsd_api/resources/metafield.rb +55 -0
- data/lib/yhsd_api/resources/open_payment.rb +31 -0
- data/lib/yhsd_api/resources/order.rb +31 -0
- data/lib/yhsd_api/resources/page.rb +43 -0
- data/lib/yhsd_api/resources/payment.rb +25 -0
- data/lib/yhsd_api/resources/payment_method.rb +25 -0
- data/lib/yhsd_api/resources/product.rb +43 -0
- data/lib/yhsd_api/resources/product_image.rb +43 -0
- data/lib/yhsd_api/resources/product_variant.rb +43 -0
- data/lib/yhsd_api/resources/province.rb +25 -0
- data/lib/yhsd_api/resources/redirect.rb +43 -0
- data/lib/yhsd_api/resources/script_tag.rb +43 -0
- data/lib/yhsd_api/resources/shipment.rb +37 -0
- data/lib/yhsd_api/resources/shipment_supplier.rb +25 -0
- data/lib/yhsd_api/resources/shop.rb +13 -0
- data/lib/yhsd_api/resources/theme.rb +37 -0
- data/lib/yhsd_api/resources/webhook.rb +45 -0
- data/lib/yhsd_api/resources.rb +2 -0
- data/lib/yhsd_api/version.rb +3 -0
- data/lib/yhsd_api.rb +16 -0
- data/spec/configuration_spec.rb +49 -0
- data/spec/helper_spec.rb +75 -0
- data/spec/private_app_spec.rb +68 -0
- data/spec/public_app_spec.rb +93 -0
- data/spec/resources/account_spec.rb +31 -0
- data/spec/resources/asset_spec.rb +56 -0
- data/spec/resources/city_spec.rb +30 -0
- data/spec/resources/country_spec.rb +28 -0
- data/spec/resources/customer_address_spec.rb +66 -0
- data/spec/resources/customer_spec.rb +67 -0
- data/spec/resources/district_spec.rb +31 -0
- data/spec/resources/metafield_spec.rb +79 -0
- data/spec/resources/open_payment_spec.rb +40 -0
- data/spec/resources/order_spec.rb +41 -0
- data/spec/resources/page_spec.rb +54 -0
- data/spec/resources/payment_method_spec.rb +28 -0
- data/spec/resources/payment_spec.rb +29 -0
- data/spec/resources/product_image_spec.rb +59 -0
- data/spec/resources/product_spec.rb +123 -0
- data/spec/resources/product_variant_spec.rb +74 -0
- data/spec/resources/province_spec.rb +29 -0
- data/spec/resources/redirect_spec.rb +58 -0
- data/spec/resources/script_tag_spec.rb +54 -0
- data/spec/resources/shipment_spec.rb +43 -0
- data/spec/resources/shipment_supplier_spec.rb +31 -0
- data/spec/resources/shop_spec.rb +18 -0
- data/spec/resources/theme_spec.rb +38 -0
- data/spec/resources/webhook_spec.rb +54 -0
- data/spec/spec_helper.rb +9 -0
- data/yhsd_api.gemspec +26 -0
- metadata +217 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 5b1916d01e246ed4dac2598fd229b84d692c39fa
|
|
4
|
+
data.tar.gz: 2ba0a91ef0824d7bb72663bd0319d9871bbf4327
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 10d5566ad6402f501fba2a275074fb6cb0ecaccd15d4b89706f09e28511eef9aab0104bcd29ee94e988a59205dc6791f71496c304b2ea60a25f4fbbcceca2165
|
|
7
|
+
data.tar.gz: 373540abd96aa6e84aeb3a14412b8f99b50012cfee0a0cbdc19410c04104e790a9a95dc9e9b5d8a2f2e9f3b8a8a750fe0024707d00d7e423c12683aad93a36f1
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/ChangeLog.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Yhsd-api-ruby Changes
|
|
2
|
+
next
|
|
3
|
+
-----------
|
|
4
|
+
-YhsdPublicApi and YhsdPrivateApi get post delete put function change url params to path
|
|
5
|
+
|
|
6
|
+
-FIX scope /r/n change to URI bug
|
|
7
|
+
|
|
8
|
+
0.0.2
|
|
9
|
+
-----------
|
|
10
|
+
|
|
11
|
+
- Add yhsd api resources
|
|
12
|
+
you can use like:
|
|
13
|
+
```ruby
|
|
14
|
+
#get the shop customers limit 50 and page 2 find id,name fields
|
|
15
|
+
params = {:fields => "id,name", :page => 2, :limit => 50}
|
|
16
|
+
YhsdApi::Customer.all(token, params)
|
|
17
|
+
|
|
18
|
+
#create a customer for your shop
|
|
19
|
+
params = {
|
|
20
|
+
"customer": {
|
|
21
|
+
"reg_type":"email",
|
|
22
|
+
"reg_identity": "for@example.com",
|
|
23
|
+
"password":"123456",
|
|
24
|
+
"notify_email":"for@example.com",
|
|
25
|
+
"notify_phone":"13632269380"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
YhsdApi::Customer.create(token, params)
|
|
29
|
+
|
|
30
|
+
#update the 1120 id customer
|
|
31
|
+
params = {
|
|
32
|
+
"customer": {
|
|
33
|
+
"notify_email":"new@example.com",
|
|
34
|
+
"notify_phone":"13632269381"
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
YhsdApi::Customer.update(token, 1120, params)
|
|
38
|
+
```
|
|
39
|
+
- Add call limit configure
|
|
40
|
+
you can open call limit configure by use
|
|
41
|
+
```ruby
|
|
42
|
+
YhsdApi.configure do |config|
|
|
43
|
+
config.call_limit_protect = true
|
|
44
|
+
end
|
|
45
|
+
```
|
|
46
|
+
this call limit is basic on shop token, so i advice open it in private app and close in public app , public app manage mutil shops, so may be some shop request api over call limit , other shop
|
|
47
|
+
will be affect
|
|
48
|
+
|
|
49
|
+
0.0.1
|
|
50
|
+
-----------
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
- Basic support yhsd api
|
|
54
|
+
- About how to use you can see [README.md](https://github.com/yeezon/yhsd-api-ruby/blob/master/README.md)
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Copyright (c) 2015 TODO: Write your name
|
|
2
|
+
|
|
3
|
+
MIT License
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
6
|
+
a copy of this software and associated documentation files (the
|
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
11
|
+
the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be
|
|
14
|
+
included in all copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
# yhsd-api-ruby
|
|
2
|
+
|
|
3
|
+
友好速搭应用开发 Ruby SDK
|
|
4
|
+
|
|
5
|
+
## 安装
|
|
6
|
+
|
|
7
|
+
在应用的gem file 中添加:
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
gem 'yhsd_api'
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
执行:
|
|
14
|
+
|
|
15
|
+
```ruby
|
|
16
|
+
$ bundle
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
或者直接使用命令行进行安装:
|
|
20
|
+
|
|
21
|
+
```ruby
|
|
22
|
+
$ gem install yhsd_api
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## 使用方法
|
|
26
|
+
|
|
27
|
+
###1,私有应用
|
|
28
|
+
|
|
29
|
+
配置私有应用的app_key, app_secret
|
|
30
|
+
|
|
31
|
+
```ruby
|
|
32
|
+
YhsdApi.configure do |config|
|
|
33
|
+
config.app_key = '配置你的app_key'
|
|
34
|
+
config.app_secret = '配置你的app_secret'
|
|
35
|
+
config.token_url = 'https://apps.youhaosuda.com/oauth2/token/'
|
|
36
|
+
config.api_url = 'https://api.youhaosuda.com/'
|
|
37
|
+
config.api_version = 'v1/'
|
|
38
|
+
end
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
获取友好速搭token
|
|
42
|
+
|
|
43
|
+
```ruby
|
|
44
|
+
YhsdApi::PrivateApp.generate_token
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
调用友好速搭api接口
|
|
48
|
+
|
|
49
|
+
```ruby
|
|
50
|
+
#get 接口调用
|
|
51
|
+
#url 需要访问的api接口的地址
|
|
52
|
+
#返回结果
|
|
53
|
+
#code :200
|
|
54
|
+
#body hash 数据
|
|
55
|
+
#header hash 数据
|
|
56
|
+
YhsdApi::PrivateApp.get(url)
|
|
57
|
+
|
|
58
|
+
#put 接口调用
|
|
59
|
+
#url 需要访问的api接口的地址
|
|
60
|
+
#params 参数
|
|
61
|
+
#返回结果
|
|
62
|
+
#code :200
|
|
63
|
+
#body hash 数据
|
|
64
|
+
#header hash 数据
|
|
65
|
+
YhsdApi::PrivateApp.put(url, params)
|
|
66
|
+
|
|
67
|
+
#post 接口调用
|
|
68
|
+
#url 需要访问的api接口的地址
|
|
69
|
+
#params 参数
|
|
70
|
+
#返回结果
|
|
71
|
+
#code :200
|
|
72
|
+
#body hash 数据
|
|
73
|
+
#header hash 数据
|
|
74
|
+
YhsdApi::PrivateApp.post(url, params)
|
|
75
|
+
|
|
76
|
+
#delete 接口调用
|
|
77
|
+
#url 需要访问的api接口的地址
|
|
78
|
+
#返回结果
|
|
79
|
+
#code :200
|
|
80
|
+
#body hash 数据
|
|
81
|
+
#header hash 数据
|
|
82
|
+
YhsdApi::PrivateApp.delete(url)
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
例子
|
|
86
|
+
```ruby
|
|
87
|
+
YhsdApi::PrivateApp.token = '获取到的token'
|
|
88
|
+
|
|
89
|
+
#get 接口调用
|
|
90
|
+
code, body, header = YhsdApi::PrivateApp.get("shop")
|
|
91
|
+
|
|
92
|
+
#put 接口调用
|
|
93
|
+
params = {
|
|
94
|
+
"redirect": {
|
|
95
|
+
"path": "/12345",
|
|
96
|
+
"target": "/blogs"
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
code, body, header = YhsdApi::PrivateApp.put("redirects/1", params)
|
|
100
|
+
|
|
101
|
+
#post 接口调用
|
|
102
|
+
params = {
|
|
103
|
+
"redirect": {
|
|
104
|
+
"path": "/12345",
|
|
105
|
+
"target": "/blogs"
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
code, body, header = YhsdApi::PrivateApp.put("redirects", params)
|
|
109
|
+
|
|
110
|
+
#delete 接口调用
|
|
111
|
+
code, body, header = YhsdApi::PrivateApp.delete("redirects/1")
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
友好速搭的token是不过期的,你也可以通过
|
|
115
|
+
|
|
116
|
+
```ruby
|
|
117
|
+
YhsdApi::PrivateApp.token = '你的私有应用token'
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
来进行指定token值,这样就不需要调用generate_token来获取token值了。
|
|
121
|
+
|
|
122
|
+
###2,开放应用
|
|
123
|
+
|
|
124
|
+
配置公有一用的app_key, app_secret
|
|
125
|
+
|
|
126
|
+
```ruby
|
|
127
|
+
YhsdApi.configure do |config|
|
|
128
|
+
config.app_key = '配置你的app_key'
|
|
129
|
+
config.app_secret = '配置你的app_secret'
|
|
130
|
+
config.scope = '配置你的应用scope'
|
|
131
|
+
config.auth_url = "https://apps.youhaosuda.com/oauth2/authorize/"
|
|
132
|
+
config.token_url = 'https://apps.youhaosuda.com/oauth2/token/'
|
|
133
|
+
config.api_url = 'https://api.youhaosuda.com/'
|
|
134
|
+
config.api_version = 'v1/'
|
|
135
|
+
end
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
友好速搭hmac验证,获取到参数后调用
|
|
139
|
+
|
|
140
|
+
```ruby
|
|
141
|
+
#true 表示验证正确 false 表示错误
|
|
142
|
+
#params 为获取到的所有参数
|
|
143
|
+
YhsdApi::PublicApp.verify_hmac(params)
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
友好速搭授权回调url获取
|
|
147
|
+
|
|
148
|
+
```ruby
|
|
149
|
+
#返回结果 友好速搭授权url
|
|
150
|
+
#redirect_url应用的跳转地址
|
|
151
|
+
#shop_key 友好速搭安装应用的店铺唯一key
|
|
152
|
+
#state 自定义的参数
|
|
153
|
+
YhsdApi::PublicApp.authorize_url(redirect_url, shop_key, state)
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
友好速搭店铺token获取
|
|
157
|
+
|
|
158
|
+
```ruby
|
|
159
|
+
#返回结果 店铺的开放应用token
|
|
160
|
+
#redirect_url 应用的跳转地址
|
|
161
|
+
#code友好速搭返回获取授权码的code
|
|
162
|
+
YhsdApi::PublicApp::generate_token(redirect_url, code)
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
调用友好速搭api接口
|
|
166
|
+
|
|
167
|
+
```ruby
|
|
168
|
+
#get 接口调用
|
|
169
|
+
#token 访问token
|
|
170
|
+
#url 需要访问的api接口的地址
|
|
171
|
+
#返回结果
|
|
172
|
+
#code :200
|
|
173
|
+
#body hash 数据
|
|
174
|
+
#header hash 数据
|
|
175
|
+
YhsdApi::PublicApp.get(token, url)
|
|
176
|
+
|
|
177
|
+
#put 接口调用
|
|
178
|
+
#token 访问token
|
|
179
|
+
#url 需要访问的api接口的地址
|
|
180
|
+
#params 参数
|
|
181
|
+
#返回结果
|
|
182
|
+
#code :200
|
|
183
|
+
#body hash 数据
|
|
184
|
+
#header hash 数据
|
|
185
|
+
YhsdApi::PublicApp.put(token, url, params)
|
|
186
|
+
|
|
187
|
+
#post 接口调用
|
|
188
|
+
#token 访问token
|
|
189
|
+
#url 需要访问的api接口的地址
|
|
190
|
+
#params 参数
|
|
191
|
+
#返回结果
|
|
192
|
+
#code :200
|
|
193
|
+
#body hash 数据
|
|
194
|
+
#header hash 数据
|
|
195
|
+
YhsdApi::PublicApp.post(token, url, params)
|
|
196
|
+
|
|
197
|
+
#delete 接口调用
|
|
198
|
+
#token 访问token
|
|
199
|
+
#url 需要访问的api接口的地址
|
|
200
|
+
#返回结果
|
|
201
|
+
#code :200
|
|
202
|
+
#body hash 数据
|
|
203
|
+
#header hash 数据
|
|
204
|
+
YhsdApi::PublicApp.delete(token, url)
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
例子
|
|
208
|
+
```ruby
|
|
209
|
+
token = '店铺的访问token'
|
|
210
|
+
|
|
211
|
+
#get 接口调用
|
|
212
|
+
code, body, header = YhsdApi::PublicApp.get(token, "shop")
|
|
213
|
+
|
|
214
|
+
#put 接口调用
|
|
215
|
+
params = {
|
|
216
|
+
"redirect": {
|
|
217
|
+
"path": "/12345",
|
|
218
|
+
"target": "/blogs"
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
code, body, header = YhsdApi::PublicApp.put(token, "redirects/1", params)
|
|
222
|
+
|
|
223
|
+
#post 接口调用
|
|
224
|
+
params = {
|
|
225
|
+
"redirect": {
|
|
226
|
+
"path": "/12345",
|
|
227
|
+
"target": "/blogs"
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
code, body, header = YhsdApi::PublicApp.put("token, "redirects", params)
|
|
231
|
+
|
|
232
|
+
#delete 接口调用
|
|
233
|
+
code, body, header = YhsdApi::PublicApp.delete(token, "redirects/1")
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
## 贡献
|
|
237
|
+
|
|
238
|
+
1. Fork it ( https://github.com/yeezon/yhsd-api-ruby/fork )
|
|
239
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
|
240
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
|
241
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
|
242
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
module YhsdApi
|
|
2
|
+
|
|
3
|
+
class Configuration
|
|
4
|
+
|
|
5
|
+
attr_accessor :app_key
|
|
6
|
+
attr_accessor :app_secret
|
|
7
|
+
attr_accessor :scope
|
|
8
|
+
attr_accessor :auth_url
|
|
9
|
+
attr_accessor :token_url
|
|
10
|
+
attr_accessor :api_url
|
|
11
|
+
attr_accessor :api_version
|
|
12
|
+
attr_accessor :call_limit_protect
|
|
13
|
+
|
|
14
|
+
def initialize
|
|
15
|
+
@auth_url = 'https://apps.youhaosuda.com/oauth2/authorize/'
|
|
16
|
+
@token_url = 'https://apps.youhaosuda.com/oauth2/token/'
|
|
17
|
+
@api_url = 'https://api.youhaosuda.com/'
|
|
18
|
+
@api_version = 'v1/'
|
|
19
|
+
@call_limit_protect = false
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def scope
|
|
23
|
+
@scope.to_s.gsub(/\s+/, "")
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def api_version
|
|
27
|
+
unless @api_version.end_with?("/")
|
|
28
|
+
@api_version.to_s + "/"
|
|
29
|
+
else
|
|
30
|
+
@api_version
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def self.configuration
|
|
37
|
+
@configuration ||= Configuration.new
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def self.configuration=(config)
|
|
41
|
+
@configuration = config
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def self.configure
|
|
45
|
+
yield configuration
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
module YhsdApi
|
|
2
|
+
|
|
3
|
+
class MissingToken < Exception
|
|
4
|
+
|
|
5
|
+
def initialize
|
|
6
|
+
super('token is empty.')
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
class MissingAppKey < Exception
|
|
12
|
+
|
|
13
|
+
def initialize
|
|
14
|
+
super('app key is empty.')
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
class MissingScope < Exception
|
|
20
|
+
|
|
21
|
+
def initialize
|
|
22
|
+
super('scope is empty.')
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
class MissingAppSecret < Exception
|
|
28
|
+
|
|
29
|
+
def initialize
|
|
30
|
+
super('app secret is empty.')
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
class MissingURI < Exception
|
|
36
|
+
def initialize
|
|
37
|
+
super('url is empty.')
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
module YhsdApi
|
|
2
|
+
|
|
3
|
+
class Helper
|
|
4
|
+
|
|
5
|
+
class << self
|
|
6
|
+
|
|
7
|
+
###
|
|
8
|
+
#私有APP 通过 app key 和 app secret 生成标准的 0auth2 头部内容
|
|
9
|
+
###
|
|
10
|
+
def authorization(key, secret)
|
|
11
|
+
content = "#{key}:#{secret}"
|
|
12
|
+
# 使用遵循 RFC 4648 的 Base64 编码函数
|
|
13
|
+
encode = Base64.urlsafe_encode64(content)
|
|
14
|
+
"Basic #{encode}"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
###
|
|
18
|
+
#通过app secret和友好速搭回传的参数,验证当前请求是否来自于友好速搭
|
|
19
|
+
###
|
|
20
|
+
def hmac_verify(secret, params = {})
|
|
21
|
+
raise 'secret can not be empty' if secret.to_s.empty?
|
|
22
|
+
if params.has_key?(:hmac)
|
|
23
|
+
hmac = params[:hmac].to_s
|
|
24
|
+
elsif params.has_key?("hmac")
|
|
25
|
+
hmac = params["hmac"].to_s
|
|
26
|
+
else
|
|
27
|
+
return false
|
|
28
|
+
end
|
|
29
|
+
return false if hmac.empty?
|
|
30
|
+
p = params.delete_if{|key, value| key.to_s == "hmac"}
|
|
31
|
+
str = p.keys.sort.map do |k|
|
|
32
|
+
"#{k.to_s}=#{params[k].to_s}"
|
|
33
|
+
end.join('&')
|
|
34
|
+
digest = OpenSSL::Digest.new('sha256')
|
|
35
|
+
hmac == OpenSSL::HMAC.hexdigest(digest, secret, str)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
###
|
|
39
|
+
#第三方App接入参数生成函数
|
|
40
|
+
###
|
|
41
|
+
def thirdapp_aes_encrypt(secret, data = {})
|
|
42
|
+
raise 'secret can not be empty' if secret.to_s.empty?
|
|
43
|
+
cipher = OpenSSL::Cipher::Cipher.new("aes-128-cbc")
|
|
44
|
+
cipher.encrypt
|
|
45
|
+
cipher.key = secret[0, 16]
|
|
46
|
+
cipher.iv = secret[16, 16]
|
|
47
|
+
ciphertext = cipher.update(data) + cipher.final
|
|
48
|
+
Base64.urlsafe_encode64(ciphertext)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
###
|
|
52
|
+
#友好速搭webhook通知验证
|
|
53
|
+
###
|
|
54
|
+
def webhook_verify(token, data, hmac)
|
|
55
|
+
digest = OpenSSL::Digest.new('sha256')
|
|
56
|
+
calculated_hmac = Base64.encode64(OpenSSL::HMAC.digest(digest, token, data)).strip
|
|
57
|
+
calculated_hmac == hmac
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def generate_hmac(secret, params = {})
|
|
61
|
+
raise 'secret can not be empty' if secret.to_s.empty?
|
|
62
|
+
str = params.keys.sort.map do |k|
|
|
63
|
+
"#{k.to_s}=#{params[k].to_s}"
|
|
64
|
+
end.join('&')
|
|
65
|
+
digest = OpenSSL::Digest.new('sha256')
|
|
66
|
+
OpenSSL::HMAC.hexdigest(digest, secret, str)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
###
|
|
70
|
+
#友好速搭开放支付回调验证
|
|
71
|
+
###
|
|
72
|
+
alias_method :openpayment_verify, :webhook_verify
|
|
73
|
+
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
end
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
require 'rest-client'
|
|
2
|
+
|
|
3
|
+
module YhsdApi
|
|
4
|
+
|
|
5
|
+
class HTTP
|
|
6
|
+
|
|
7
|
+
class << self
|
|
8
|
+
|
|
9
|
+
@@last_at = nil
|
|
10
|
+
@@limit = 0
|
|
11
|
+
@@total = 0
|
|
12
|
+
|
|
13
|
+
def get(url, opts = {})
|
|
14
|
+
validate_url(url)
|
|
15
|
+
|
|
16
|
+
req_headers = {}
|
|
17
|
+
|
|
18
|
+
if opts[:headers].is_a?(Hash)
|
|
19
|
+
req_headers.merge!(opts[:headers])
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
begin
|
|
23
|
+
begin_request if YhsdApi.configuration.call_limit_protect
|
|
24
|
+
response = RestClient.get(url.to_s, req_headers)
|
|
25
|
+
after_request(response.raw_headers) if YhsdApi.configuration.call_limit_protect
|
|
26
|
+
return response.code.to_i, response.body, response.raw_headers
|
|
27
|
+
rescue Exception => e
|
|
28
|
+
if e.class.to_s.split("::").first.to_s == 'RestClient'
|
|
29
|
+
return e.http_code.to_i, e.response, {}
|
|
30
|
+
else
|
|
31
|
+
raise e
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def post(url, req_body = nil, opts = {})
|
|
38
|
+
validate_url(url)
|
|
39
|
+
|
|
40
|
+
req_headers = {}
|
|
41
|
+
|
|
42
|
+
if opts[:headers].is_a?(Hash)
|
|
43
|
+
req_headers.merge!(opts[:headers])
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
begin
|
|
47
|
+
begin_request if YhsdApi.configuration.call_limit_protect
|
|
48
|
+
response = RestClient.post(url.to_s, req_body, req_headers)
|
|
49
|
+
after_request(response.raw_headers) if YhsdApi.configuration.call_limit_protect
|
|
50
|
+
return response.code.to_i, response.body, response.raw_headers
|
|
51
|
+
rescue Exception => e
|
|
52
|
+
if e.class.to_s.split("::").first.to_s == 'RestClient'
|
|
53
|
+
return e.http_code.to_i, e.response, {}
|
|
54
|
+
else
|
|
55
|
+
raise e
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def put(url, req_body = nil, opts = {})
|
|
62
|
+
validate_url(url)
|
|
63
|
+
|
|
64
|
+
req_headers = {}
|
|
65
|
+
|
|
66
|
+
if opts[:headers].is_a?(Hash)
|
|
67
|
+
req_headers.merge!(opts[:headers])
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
begin
|
|
71
|
+
begin_request if YhsdApi.configuration.call_limit_protect
|
|
72
|
+
response = RestClient.put(url.to_s, req_body, req_headers)
|
|
73
|
+
after_request(response.raw_headers) if YhsdApi.configuration.call_limit_protect
|
|
74
|
+
return response.code.to_i, response.body, response.raw_headers
|
|
75
|
+
rescue Exception => e
|
|
76
|
+
if e.class.to_s.split("::").first.to_s == 'RestClient'
|
|
77
|
+
return e.http_code.to_i, e.response, {}
|
|
78
|
+
else
|
|
79
|
+
raise e
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def delete(url, opts = {})
|
|
86
|
+
validate_url(url)
|
|
87
|
+
|
|
88
|
+
req_headers = {}
|
|
89
|
+
|
|
90
|
+
if opts[:headers].is_a?(Hash)
|
|
91
|
+
req_headers.merge!(opts[:headers])
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
begin
|
|
95
|
+
begin_request if YhsdApi.configuration.call_limit_protect
|
|
96
|
+
response = RestClient.delete(url.to_s, req_headers)
|
|
97
|
+
after_request(response.raw_headers) if YhsdApi.configuration.call_limit_protect
|
|
98
|
+
return response.code.to_i, response.body, response.raw_headers
|
|
99
|
+
rescue Exception => e
|
|
100
|
+
if e.class.to_s.split("::").first.to_s == 'RestClient'
|
|
101
|
+
return e.http_code.to_i, e.response, {}
|
|
102
|
+
else
|
|
103
|
+
raise e
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def validate_url(url)
|
|
110
|
+
raise MissingURI if url.to_s.empty?
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def after_request(header)
|
|
114
|
+
begin
|
|
115
|
+
if header && header.is_a?(Hash) && header.keys.include?("x-yhsd-shop-api-call-limit")
|
|
116
|
+
call_limit = header["x-yhsd-shop-api-call-limit"].first.split("/")
|
|
117
|
+
@@limit, @@total = call_limit[0].to_i, call_limit[1].to_i
|
|
118
|
+
@@last_at = Time.now.to_i
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def begin_request
|
|
124
|
+
if @@last_at
|
|
125
|
+
if Time.now.to_i - @@last_at <= 1000 && @@total - @@limit <= 2
|
|
126
|
+
sleep(1)
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
end
|