button 0.0.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7000fd76d3af3d8e674e4ef5764d9db85b0858be
4
+ data.tar.gz: 816710af43f2165f4a54cbfd785f43c797128cde
5
+ SHA512:
6
+ metadata.gz: 5caa52ecc60d1ae70654006a7a20354c239fa3740dcbf7889c8fbaee83294847f07382ba60067a738dbf6573fa37de0939d18af9acf3dc885e73caf44ac7eb59
7
+ data.tar.gz: accbb50b91a0c6a1bd518eadb67fc9209958f7e26fe480dcf914e447fc569b8c487bc0ccc65ab310a6c3c66845188154b314e5648eece7bfbc5bb517ec6bcd58
data/CHANGELOG.md ADDED
@@ -0,0 +1,2 @@
1
+ 0.0.1 August X, 2016
2
+ - Initial Release
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Button
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,125 @@
1
+ # button-client-ruby [![Build Status](https://travis-ci.com/button/button-client-ruby.svg?token=HswVzGqEpwteP838Y3ss&branch=master)](https://travis-ci.com/button/button-client-ruby)
2
+
3
+ This module is a thin client for interacting with Button's API.
4
+
5
+ Please see the full [API Docs](https://www.usebutton.com/developers/api-reference) for more information.
6
+
7
+ #### Supported runtimes
8
+
9
+ * Ruby (MRI) `>=1.9.3`
10
+
11
+ #### Dependencies
12
+
13
+ * None
14
+
15
+ ## Usage
16
+
17
+ ```bash
18
+ gem install button
19
+ ```
20
+
21
+ To create a client capable of making network requests, instantiate a `Button::Client` with your [API key](https://app.usebutton.com/settings/organization).
22
+
23
+ ```ruby
24
+ require 'button'
25
+
26
+ client = Button::Client.new('sk-XXX')
27
+ ```
28
+
29
+ The client will always attempt to raise a `Button::ButtonClientError` in an error condition.
30
+
31
+ All API requests will return a `Button::Response` instance, which supports accessing data properties from the API response as methods. To access the raw response hash, use `#to_hash`. For instance:
32
+
33
+ ```ruby
34
+ require 'button'
35
+
36
+ client = Button::Client.new('sk-XXX')
37
+
38
+ begin
39
+ response = client.orders.get('btnorder-XXX')
40
+ rescue Button::ButtonClientError => error
41
+ puts error
42
+ end
43
+
44
+ puts response
45
+ # => Button::Response(button_order_id: btnorder-XXX, total: 60, ... )
46
+
47
+ puts response.button_order_id
48
+ # => btnorder-XXX
49
+
50
+ puts response.to_hash()
51
+ # => {:button_order_id=>'btnorder-29de0b1436075ea6', :total=>60, ... }
52
+ ```
53
+
54
+ n.b. the keys of the response hash will always be symbols.
55
+
56
+ ## Resources
57
+
58
+ We currently expose only one resource to manage, `Orders`.
59
+
60
+ ### Orders
61
+
62
+ **n.b: all currency values should be reported in the smallest possible unit of that denomination, i.e. $1.00 should be reported as `100` (i.e. 100 pennies)**
63
+
64
+ ##### Create
65
+
66
+ ```ruby
67
+ require 'button'
68
+
69
+ client = Button::Client.new('sk-XXX')
70
+
71
+ response = client.orders.create({
72
+ total: 50,
73
+ currency: 'USD',
74
+ order_id: '1994',
75
+ finalization_date: '2017-08-02T19:26:08Z'
76
+ })
77
+
78
+ puts response
79
+ # => Button::Response(button_order_id: btnorder-XXX, total: 50, ... )
80
+ ```
81
+
82
+ ##### Get
83
+
84
+ ```ruby
85
+ require 'button'
86
+
87
+ client = Button::Client.new('sk-XXX')
88
+
89
+ response = client.orders.get('btnorder-XXX')
90
+
91
+ puts response
92
+ # => Button::Response(button_order_id: btnorder-XXX, total: 50, ... )
93
+ ```
94
+ ##### Update
95
+
96
+ ```ruby
97
+ require 'button'
98
+
99
+ client = Button::Client.new('sk-XXX')
100
+
101
+ response = client.orders.update('btnorder-XXX', total: 60)
102
+
103
+ puts response
104
+ # => Button::Response(button_order_id: btnorder-XXX, total: 60, ... )
105
+ ```
106
+
107
+ ##### Delete
108
+
109
+ ```ruby
110
+ require 'button'
111
+
112
+ client = Button::Client.new('sk-XXX')
113
+
114
+ response = client.orders.delete('btnorder-XXX')
115
+
116
+ puts response
117
+ # => Button::Response()
118
+ ```
119
+
120
+ ## Contributing
121
+
122
+ * Building the gem: `gem build button.gemspec`
123
+ * Installing locally: `gem install ./button-X.Y.Z.gem`
124
+ * Installing development dependencies: `bundle install`
125
+ * Running tests: `bundle exec rake`
@@ -0,0 +1,26 @@
1
+ require 'button/resources/orders'
2
+ require 'button/errors'
3
+
4
+ module Button
5
+ # Client is the top-level interface for the Button API. It exposes one
6
+ # resource currently: `.orders`. It requires a valid API key to make
7
+ # requests on behalf of your organization, which can be found at
8
+ # https://app.usebutton.com/settings/organization.
9
+ #
10
+ # ## Usage
11
+ #
12
+ # client = Button::Client.new("sk-XXX")
13
+ # puts client.orders.get("btnorder-XXX")
14
+ #
15
+ class Client
16
+ def initialize(api_key)
17
+ if api_key.nil? || api_key.empty?
18
+ raise ButtonClientError, 'Must provide a Button API key. Find yours at https://app.usebutton.com/settings/organization'
19
+ end
20
+
21
+ @orders = Orders.new(api_key)
22
+ end
23
+
24
+ attr_reader :orders
25
+ end
26
+ end
@@ -0,0 +1,4 @@
1
+ module Button
2
+ class ButtonClientError < StandardError
3
+ end
4
+ end
@@ -0,0 +1,49 @@
1
+ require 'button/resources/resource'
2
+
3
+ module Button
4
+ # https://www.usebutton.com/developers/api-reference/
5
+ #
6
+ class Orders < Resource
7
+ def path(order_id = nil)
8
+ return "/v1/order/#{order_id}" if order_id
9
+ '/v1/order'
10
+ end
11
+
12
+ # Gets an order
13
+ #
14
+ # @param [String] order_id the order id
15
+ # @return [Button::Response] the API response
16
+ #
17
+ def get(order_id)
18
+ api_get(path(order_id))
19
+ end
20
+
21
+ # Creates an order
22
+ #
23
+ # @param [Hash] order the order to create
24
+ # @return [Button::Response] the API response
25
+ #
26
+ def create(order)
27
+ api_post(path, order)
28
+ end
29
+
30
+ # Updates an order
31
+ #
32
+ # @param [String] order_id the order id
33
+ # @param [Hash] order the order to create
34
+ # @return [Button::Response] the API response
35
+ #
36
+ def update(order_id, order)
37
+ api_post(path(order_id), order)
38
+ end
39
+
40
+ # Deletes an order
41
+ #
42
+ # @param [String] order_id the order id
43
+ # @return [Button::Response] the API response
44
+ #
45
+ def delete(order_id)
46
+ api_delete(path(order_id))
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,101 @@
1
+ require 'net/http'
2
+ require 'json'
3
+
4
+ require 'button/errors'
5
+ require 'button/response'
6
+ require 'button/version'
7
+
8
+ module Button
9
+ # Resource is a handy base class for making API requests. It includes
10
+ # serveral handy methods for making such requests:
11
+ #
12
+ # api_get(path)
13
+ # api_post(path, body)
14
+ # api_delete(path)
15
+ #
16
+ # ## Usage
17
+ #
18
+ # class Blorp < Button::Resource
19
+ #
20
+ # def get(blorp_id)
21
+ # api_get("/api/v1/blorps/#{blorp_id}")
22
+ # end
23
+ #
24
+ # end
25
+ #
26
+ class Resource
27
+ HOST = 'api.usebutton.com'.freeze
28
+ PORT = 443
29
+ USER_AGENT = "Button/#{Button::VERSION} ruby/#{RUBY_VERSION}".freeze
30
+
31
+ def initialize(api_key)
32
+ @api_key = api_key
33
+ @http = Net::HTTP.new(HOST, PORT)
34
+ @http.use_ssl = true
35
+ end
36
+
37
+ # Performs an HTTP GET at the provided path.
38
+ #
39
+ # @param [String] path the HTTP path
40
+ # @return [Button::Response] the API response
41
+ #
42
+ def api_get(path)
43
+ api_request(Net::HTTP::Get.new(path))
44
+ end
45
+
46
+ # Performs an HTTP POST at the provided path.
47
+ #
48
+ # @param [String] path the HTTP path
49
+ # @param [Hash] body the HTTP request body
50
+ # @return [Button::Response] the API response
51
+ #
52
+ def api_post(path, body)
53
+ api_request(Net::HTTP::Post.new(path), body)
54
+ end
55
+
56
+ # Performs an HTTP DELETE at the provided path.
57
+ #
58
+ # @param [String] path the HTTP path
59
+ # @return [Button::Response] the API response
60
+ #
61
+ def api_delete(path)
62
+ api_request(Net::HTTP::Delete.new(path))
63
+ end
64
+
65
+ def api_request(request, body = nil)
66
+ request.basic_auth(@api_key, '')
67
+ request.add_field('User-Agent', USER_AGENT)
68
+
69
+ if !body.nil? && body.respond_to?(:to_json)
70
+ request.add_field('Content-Type', 'application/json')
71
+ request.body = body.to_json
72
+ end
73
+
74
+ body = @http.request(request).body
75
+ process_response(body)
76
+ end
77
+
78
+ def process_response(response)
79
+ if response.nil? || response.empty?
80
+ raise ButtonClientError, 'Client received an empty response from the server'
81
+ end
82
+
83
+ begin
84
+ parsed = JSON.parse(response, symbolize_names: true)
85
+ rescue
86
+ raise ButtonClientError, "Error parsing response as JSON: #{response}"
87
+ end
88
+
89
+ raise ButtonClientError, "Invalid response: #{parsed}" unless parsed[:meta].is_a?(Hash)
90
+
91
+ status = parsed[:meta][:status]
92
+
93
+ return Response.new(parsed[:object]) if status == 'ok'
94
+ raise ButtonClientError, "Unknown status: #{status}" unless status == 'error'
95
+ raise ButtonClientError, parsed[:error][:message] if parsed[:error].is_a?(Hash)
96
+ raise ButtonClientError, "Invalid response: #{parsed}"
97
+ end
98
+
99
+ private :api_request, :process_response
100
+ end
101
+ end
@@ -0,0 +1,37 @@
1
+ module Button
2
+ # Response is a simple proxy class for easy value unpacking from an API
3
+ # response. It is constructed with a hash and proxies method calls on the
4
+ # instance down to keys in the underling hash.
5
+ #
6
+ # ## Usage
7
+ #
8
+ # response = Button::Response.new({ :a => 1, :b => "two" })
9
+ # puts response.a
10
+ # puts response.to_hash
11
+ #
12
+ class Response
13
+ def initialize(attrs)
14
+ @attrs = attrs || {}
15
+ end
16
+
17
+ def to_s
18
+ values = @attrs.reduce([]) do |acc, (name, value)|
19
+ acc + ["#{name}: #{value || 'nil'}"]
20
+ end.join(', ')
21
+
22
+ "Button::Response(#{values})"
23
+ end
24
+
25
+ def to_hash
26
+ @attrs
27
+ end
28
+
29
+ def method_missing(attr)
30
+ @attrs[attr] || super
31
+ end
32
+
33
+ def respond_to_missing?(method_name, include_private = false)
34
+ @attrs.key?(method_name) || super
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,3 @@
1
+ module Button
2
+ VERSION = '0.0.1'.freeze
3
+ end
data/lib/button.rb ADDED
@@ -0,0 +1,2 @@
1
+ require 'button/client'
2
+ require 'button/version'
metadata ADDED
@@ -0,0 +1,55 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: button
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Button
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-08-11 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Button is a contextual acquisition channel and closed-loop attribution
14
+ and affiliation system for mobile commerce.
15
+ email:
16
+ - support@usebutton.com
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - CHANGELOG.md
22
+ - LICENSE
23
+ - README.md
24
+ - lib/button.rb
25
+ - lib/button/client.rb
26
+ - lib/button/errors.rb
27
+ - lib/button/resources/orders.rb
28
+ - lib/button/resources/resource.rb
29
+ - lib/button/response.rb
30
+ - lib/button/version.rb
31
+ homepage: https://usebutton.com
32
+ licenses:
33
+ - MIT
34
+ metadata: {}
35
+ post_install_message:
36
+ rdoc_options: []
37
+ require_paths:
38
+ - lib
39
+ required_ruby_version: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: 1.9.3
44
+ required_rubygems_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ requirements: []
50
+ rubyforge_project:
51
+ rubygems_version: 2.5.1
52
+ signing_key:
53
+ specification_version: 4
54
+ summary: ruby client for the Button Order API
55
+ test_files: []