woocommerce_api 1.0.3 → 1.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.
data/README.md CHANGED
@@ -41,22 +41,23 @@ woocommerce = WooCommerce::API.new(
41
41
 
42
42
  #### Args options
43
43
 
44
- | Option | Type | Required | Description |
45
- | ------------ | -------- | -------- | --------------------------------------------------------------------------------------------------- |
46
- | `version` | `String` | no | API version, default is `v3` |
47
- | `verify_ssl` | `Bool` | no | Verify SSL when connect, use this option as `false` when need to test with self-signed certificates |
44
+ | Option | Type | Required | Description |
45
+ | ------------------ | -------- | -------- | ------------------------------------------------------------------------------------------------------------ |
46
+ | `version` | `String` | no | API version, default is `v3` |
47
+ | `verify_ssl` | `Bool` | no | Verify SSL when connect, use this option as `false` when need to test with self-signed certificates |
48
+ | `signature_method` | `String` | no | Signature method used for oAuth requests, works with `HMAC-SHA1` and `HMAC-SHA256`, default is `HMAC-SHA256` |
48
49
 
49
50
  ## Methods
50
51
 
51
- | Params | Type | Description |
52
- | ---------- | ---------- | ------------------------------------------------------------ |
53
- | `endpoint` | `String` | WooCommerce API endpoint, example: `customers` or `order/12` |
54
- | `data` | `Object` | JS object, will be converted to JSON |
55
- | `callback` | `Function` | Callback function. Returns `err`, `data` and `res` |
52
+ | Params | Type | Description |
53
+ | ---------- | -------- | ------------------------------------------------------------ |
54
+ | `endpoint` | `String` | WooCommerce API endpoint, example: `customers` or `order/12` |
55
+ | `data` | `Hash` | Only for POST and PUT, data that will be converted to JSON |
56
+ | `query` | `Hash` | Only for GET and DELETE, request query string |
56
57
 
57
58
  ### GET
58
59
 
59
- - `.get(endpoint)`
60
+ - `.get(endpoint, query)`
60
61
 
61
62
  ### POST
62
63
 
@@ -68,7 +69,7 @@ woocommerce = WooCommerce::API.new(
68
69
 
69
70
  ### DELETE
70
71
 
71
- - `.delete(endpoint)`
72
+ - `.delete(endpoint, query)`
72
73
 
73
74
  #### Response
74
75
 
@@ -92,6 +93,7 @@ puts response.headers["x-wc-totalpages"] # Total of pages
92
93
 
93
94
  ## Release History
94
95
 
96
+ - 2015-08-27 - 1.1.0 - Added `query` argument for GET and DELETE methods, reduced chance of nonce collisions and added support for urls including ports
95
97
  - 2015-08-27 - 1.0.3 - Encode all % characters in query string for OAuth 1.0a.
96
98
  - 2015-08-12 - 1.0.2 - Fixed the release date.
97
99
  - 2015-08-12 - 1.0.1 - Escaped oauth_signature in url query string.
@@ -14,11 +14,16 @@ module WooCommerce
14
14
  @consumer_secret = consumer_secret
15
15
 
16
16
  # Optional args
17
- defaults = {version: "v3", verify_ssl: true}
17
+ defaults = {
18
+ version: "v3",
19
+ verify_ssl: true,
20
+ signature_method: "HMAC-SHA256"
21
+ }
18
22
  args = defaults.merge(args)
19
23
 
20
24
  @version = args[:version]
21
25
  @verify_ssl = args[:verify_ssl] == true
26
+ @signature_method = args[:signature_method]
22
27
 
23
28
  # Internal args
24
29
  @is_ssl = @url.start_with? "https"
@@ -27,10 +32,11 @@ module WooCommerce
27
32
  # Public: GET requests.
28
33
  #
29
34
  # endpoint - A String naming the request endpoint.
35
+ # query - A Hash with query params.
30
36
  #
31
37
  # Returns the request Hash.
32
- def get endpoint
33
- do_request :get, endpoint
38
+ def get endpoint, query = nil
39
+ do_request :get, add_query_params(endpoint, query)
34
40
  end
35
41
 
36
42
  # Public: POST requests.
@@ -56,38 +62,52 @@ module WooCommerce
56
62
  # Public: DELETE requests.
57
63
  #
58
64
  # endpoint - A String naming the request endpoint.
65
+ # query - A Hash with query params.
59
66
  #
60
67
  # Returns the request Hash.
61
- def delete endpoint
62
- do_request :delete, endpoint
68
+ def delete endpoint, query = nil
69
+ do_request :delete, add_query_params(endpoint, query)
63
70
  end
64
71
 
65
72
  protected
66
73
 
74
+ # Internal: Appends data as query params onto an endpoint
75
+ #
76
+ # endpoint - A String naming the request endpoint.
77
+ # data - A hash of data to flatten and append
78
+ #
79
+ # Returns an endpoint string with the data appended
80
+ def add_query_params endpoint, data
81
+ return endpoint if data.nil? || data.empty?
82
+
83
+ endpoint += '?' unless endpoint.include? '?'
84
+ endpoint += '&' unless endpoint.end_with? '?'
85
+ endpoint + URI.encode(flatten_hash(data).join('&'))
86
+ end
87
+
67
88
  # Internal: Get URL for requests
68
89
  #
69
90
  # endpoint - A String naming the request endpoint.
91
+ # method - The method used in the url (for oauth querys)
70
92
  #
71
93
  # Returns the endpoint String.
72
- def get_url endpoint
94
+ def get_url endpoint, method
73
95
  url = @url
74
- if !url.end_with? "/"
75
- url = "#{url}/"
76
- end
96
+ url = "#{url}/" unless url.end_with? "/"
97
+ url = "#{url}wc-api/#{@version}/#{endpoint}"
77
98
 
78
- "#{url}wc-api/#{@version}/#{endpoint}"
99
+ @is_ssl ? url : oauth_url(url, method)
79
100
  end
80
101
 
81
102
  # Internal: Requests default options.
82
103
  #
83
- # method - A String maning the request method
104
+ # method - A String naming the request method
84
105
  # endpoint - A String naming the request endpoint.
85
106
  # data - The Hash data for the request.
86
107
  #
87
108
  # Returns the response in JSON String.
88
- def do_request method, endpoint, data = nil
89
- url = get_url endpoint
90
-
109
+ def do_request method, endpoint, data = {}
110
+ url = get_url(endpoint, method)
91
111
  options = {
92
112
  format: :json,
93
113
  verify: @verify_ssl,
@@ -97,27 +117,52 @@ module WooCommerce
97
117
  "Accept" => "application/json"
98
118
  }
99
119
  }
100
-
101
120
  if @is_ssl
102
- options.merge!({
103
- basic_auth: {
104
- username: @consumer_key,
105
- password: @consumer_secret
106
- }
107
- })
108
- else
109
- oauth = WooCommerce::OAuth.new url, method, @version, @consumer_key, @consumer_secret
110
- url = oauth.get_oauth_url
111
- end
112
-
113
- if data
114
- options.merge!({
115
- body: data.to_json
121
+ options.merge!(basic_auth: {
122
+ username: @consumer_key,
123
+ password: @consumer_secret
116
124
  })
117
125
  end
126
+ options.merge!(body: data.to_json) if data
127
+ HTTParty.send(method, url, options)
128
+ end
118
129
 
119
- HTTParty.send method, url, options
130
+ # Internal: Generates an oauth url given current settings
131
+ #
132
+ # url - A String naming the current request url
133
+ # method - The HTTP verb of the request
134
+ #
135
+ # Returns a url to be used for the query.
136
+ def oauth_url url, method
137
+ oauth = WooCommerce::OAuth.new(
138
+ url,
139
+ method,
140
+ @version,
141
+ @consumer_key,
142
+ @consumer_secret,
143
+ @signature_method
144
+ )
145
+ oauth.get_oauth_url
120
146
  end
121
147
 
148
+ # Internal: Flattens a hash into an array of query relations
149
+ #
150
+ # hash - A hash to flatten
151
+ #
152
+ # Returns an array full of key value paired strings
153
+ def flatten_hash hash
154
+ hash.flat_map do |key, value|
155
+ case value
156
+ when Hash
157
+ value.map do |inner_key, inner_value|
158
+ "#{key}[#{inner_key}]=#{inner_value}"
159
+ end
160
+ when Array
161
+ value.map { |inner_value| "#{key}[]=#{inner_value}" }
162
+ else
163
+ "#{key}=#{value}"
164
+ end
165
+ end
166
+ end
122
167
  end
123
168
  end
@@ -6,13 +6,15 @@ require "openssl"
6
6
 
7
7
  module WooCommerce
8
8
  class OAuth
9
+ class InvalidSignatureMethodError < StandardError; end
9
10
 
10
- def initialize url, method, version, consumer_key, consumer_secret
11
+ def initialize url, method, version, consumer_key, consumer_secret, signature_method = "HMAC-SHA256"
11
12
  @url = url
12
13
  @method = method.upcase
13
14
  @version = version
14
15
  @consumer_key = consumer_key
15
16
  @consumer_secret = consumer_secret
17
+ @signature_method = signature_method
16
18
  end
17
19
 
18
20
  # Public: Get OAuth url
@@ -27,13 +29,16 @@ module WooCommerce
27
29
  CGI::parse(parsed_url.query).each do |key, value|
28
30
  params[key] = value[0]
29
31
  end
32
+ params = Hash[params.sort]
30
33
 
31
- url = "#{parsed_url.scheme}://#{parsed_url.host}#{parsed_url.path}"
34
+ url = parsed_url.to_s.gsub(/\?.*/, "")
32
35
  end
33
36
 
37
+ nonce_lifetime = 15 * 60 # Woocommerce keeps nonces for 15 minutes
38
+
34
39
  params["oauth_consumer_key"] = @consumer_key
35
- params["oauth_nonce"] = Digest::SHA1.hexdigest("#{Time.new.to_i + rand(99999)}")
36
- params["oauth_signature_method"] = "HMAC-SHA256"
40
+ params["oauth_nonce"] = Digest::SHA1.hexdigest((Time.new.to_f % nonce_lifetime + (Process.pid * nonce_lifetime)).to_s)
41
+ params["oauth_signature_method"] = @signature_method
37
42
  params["oauth_timestamp"] = Time.new.to_i
38
43
  params["oauth_signature"] = CGI::escape(generate_oauth_signature(params, url))
39
44
 
@@ -68,7 +73,19 @@ module WooCommerce
68
73
  consumer_secret = @consumer_secret
69
74
  end
70
75
 
71
- return Base64.strict_encode64(OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha256'), consumer_secret, string_to_sign))
76
+ return Base64.strict_encode64(OpenSSL::HMAC.digest(digest, consumer_secret, string_to_sign))
77
+ end
78
+
79
+ # Internal: Digest object based on signature method
80
+ #
81
+ # Returns a digest object.
82
+ def digest
83
+ case @signature_method
84
+ when "HMAC-SHA256" then OpenSSL::Digest.new("sha256")
85
+ when "HMAC-SHA1" then OpenSSL::Digest.new("sha1")
86
+ else
87
+ fail InvalidSignatureMethodError
88
+ end
72
89
  end
73
90
 
74
91
  # Internal: Encode param
@@ -76,8 +93,8 @@ module WooCommerce
76
93
  # text - A String to be encoded
77
94
  #
78
95
  # Returns the encoded String.
79
- def encode_param(text)
80
- CGI::escape(text).gsub('%', '%25')
96
+ def encode_param text
97
+ CGI::escape(text).gsub("%", "%25")
81
98
  end
82
99
  end
83
100
  end
@@ -1,3 +1,3 @@
1
1
  module WooCommerce
2
- VERSION = '1.0.3'
2
+ VERSION = '1.1.0'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: woocommerce_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-08-27 00:00:00.000000000 Z
12
+ date: 2015-10-07 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: httparty