affirm 0.0.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 689c049744aaff6ed260bd43c0bcdf0219e6689a
4
- data.tar.gz: 90142f082b195d4b12b593ba8dbe8f0a9d0a01b1
3
+ metadata.gz: 39c1e3c767578030a0b0d4040f1369a0984537dc
4
+ data.tar.gz: 41fe7e6a858817d7bb521c68dcc3238457e347e3
5
5
  SHA512:
6
- metadata.gz: 6b0c3a679864712c47a0053eff6135b0fc2ba4c6a24cb49f9d66b019c95b1ca3b724f2eff90d0a4a8e07f46a5654c8667b44a9e87edbb3d817995b25eca1369b
7
- data.tar.gz: 0836887d3303dbb09d741b13e8894b5f6ec7c987c8218cc1a744e053b4b99a86fb440a14ecb93ba9aabb80051fab200833c211ff7d0e3071d54c35e6c84110a4
6
+ metadata.gz: d00eda5029a694f08f75cbd2512dbf6acd9ae10cd2a4de39e41b10c004d454623142aa791bb74ce4481ce39689a3d4790cbf4d5213739794c041a69e77060f23
7
+ data.tar.gz: 12f0057579aba7917cb39f3f5e5d12d38662b6c8639090652e2215c40be8c8278ed1dba5157adf93b118a9f5dd232f428f802eacdb8e466681eedd8c14469e38
data/README.md CHANGED
@@ -7,15 +7,16 @@ Requires Ruby 2.1 or greater.
7
7
 
8
8
  ## Install
9
9
  Add to your gemfile:
10
+
10
11
  ```ruby
11
- gem 'affirm-ruby'
12
+ gem 'affirm'
12
13
  ```
13
- and `bundle install`.
14
14
 
15
- *Note*: This gem is not yet registered with Rubygems. In the meantime, you can use the 'git' option in your Gemfile.
15
+ and `bundle install`.
16
16
 
17
17
  ## Initialize
18
18
  Initialize the client with your credentials (if you're using rails, this goes in `config/initializers`).
19
+
19
20
  ```ruby
20
21
  Affirm::API.public_key = "xxx"
21
22
  Affirm::API.secret_key = "xxx"
@@ -23,86 +24,87 @@ Affirm::API.api_url = "https://sandbox.affirm.com/api/v2/"
23
24
  ```
24
25
 
25
26
  ## Charges
26
- The charges resource can be accessed through the api class:
27
- ```ruby
28
- Affirm::API.charges
29
- ```
30
27
 
31
- ### Authorizing a charge
28
+ All API requests raise an `Affirm::Error` or subclass thereof on failure.
29
+
30
+ ### Creating/authorizing a charge
31
+
32
32
  ```ruby
33
- Affirm::API.charges.authorize(checkout_token: "token")
34
- Affirm::API.charges.authorize!(checkout_token: "token") # raises Affirm::Error on failure
33
+ charge = Affirm::Charge.create("checkout_token")
35
34
  ```
36
35
 
37
- ### Reading a charge
36
+ ### Retrieving a charge
37
+
38
38
  ```ruby
39
- Affirm::API.charges.get(charge_id: "abcd")
39
+ charge = Affirm::Charge.retrieve("ABCD-ABCD")
40
+
41
+ charge.id
42
+ charge.amount
43
+ charge.created
44
+ charge.currency
45
+ charge.auth_hold
46
+ charge.payable
47
+ charge.void?
48
+ charge.order_id
49
+ charge.events # array of Affirm::ChargeEvent
50
+ charge.details # hash of order details
40
51
  ```
41
52
 
53
+ Raises an `Affirm::ResourceNotFoundError` if the charge doesn't exist.
54
+
55
+ See https://docs.affirm.com/v2/api/charges/#charge-object for more info on the charge object
56
+
42
57
  ### Capturing a charge
43
58
  Optionally takes an `order_id`, `shipping_carrier`, and `shipping_confirmation`.
59
+
44
60
  ```ruby
45
- Affirm::API.charges.capture(charge_id: "abcd")
46
- Affirm::API.charges.capture(charge_id: "abcd", order_id: "1234", shipping_carrier: "USPS", shipping_confirmation: "ABCD1234")
47
- Affirm::API.charges.capture!(charge_id: "abcd") # raises Affirm::Error on failure
61
+ charge.capture
62
+ charge.capture(order_id: "1234", shipping_carrier: "USPS", shipping_confirmation: "ABCD1234")
48
63
  ```
49
64
 
65
+ Returns an `Affirm::ChargeEvent` object of type `capture`.
66
+
50
67
  ### Voiding a charge
68
+
51
69
  ```ruby
52
- Affirm::API.charges.void(charge_id: "abcd")
53
- Affirm::API.charges.void!(charge_id: "abcd") # raises Affirm::Error on failure
70
+ charge.void
54
71
  ```
55
72
 
73
+ Returns an `Affirm::ChargeEvent` object of type `void`.
74
+
56
75
  ### Refunding a charge
57
76
  Optionally takes an `amount` to refund (in cents).
77
+
58
78
  ```ruby
59
- Affirm::API.charges.refund(charge_id: "abcd")
60
- Affirm::API.charges.refund(charge_id: "abcd", amount: 5000)
61
- Affirm::API.charges.refund!(charge_id: "abcd") # raises Affirm::Error on failure
79
+ charge.refund
80
+ charge.refund(amount: 1000)
62
81
  ```
63
82
 
83
+ Returns an `Affirm::ChargeEvent` object of type `refund`.
84
+
64
85
  ### Updating tracking fields
65
86
  Optionally takes an `order_id`, `shipping_carrier`, and `shipping_confirmation`.
66
- ```ruby
67
- Affirm::API.charges.update(charge_id: "abcd", order_id: "1234", shipping_carrier: "USPS", shipping_confirmation: "ABCD1234")
68
- Affirm::API.charges.update!(charge_id: "abcd", order_id: "1234") # raises Affirm::Error on failure
69
- ```
70
87
 
71
- ## Responses
72
- On successful api calls, the response json is
73
88
  ```ruby
74
- response = Affirm::API.charges.get(charge_id: "abcd")
75
-
76
- response.success? # => true
77
- response.error? # => false
78
-
79
- response.status_code # => 200
80
-
81
- response.body # => hash of values
82
- response.body["id"] # eg "abcd"
83
- response.body["details"]["shipping_amount"] # eg 400
89
+ charge.update(order_id: "1234", shipping_carrier: "USPS", shipping_confirmation: "ABCD1234")
84
90
  ```
85
91
 
86
- ### Error responses
87
- Unsuccessful responses have a few methods built in:
88
- ```ruby
89
- response.code # eg "auth-declined"
90
- response.type # eg "invalid_request"
91
- response.message # eg "Invalid phone number format"
92
- response.field # eg "shipping_address.phone"
93
- ```
94
- See https://docs.affirm.com/v2/api/errors/#error-object.
92
+ Returns an `Affirm::ChargeEvent` object of type `update`.
95
93
 
96
- ### Exceptions
97
- Exceptions are raised for 5xx, 404 and 401 responses, yielding an `Affirm::ServerError`,
94
+ ## Exceptions
95
+ Special exceptions are raised for 5xx, 404 and 401 responses, yielding an `Affirm::ServerError`,
98
96
  `Affirm::ResourceNotFoundError` and `Affirm::AuthenticationError`, respectively. These are subclassed from
99
97
  `Affirm::Error`.
98
+
99
+ All exceptions have the following methods on them:
100
+
100
101
  ```ruby
101
102
  begin
102
- Affirm::API.charges.authorize(checkout_token: "token")
103
- rescue Affirm::ServerError => e
104
- Logger.info e.code
105
- Logger.info e.message
103
+ Affirm::Charge.create("checkout_token")
104
+ rescue Affirm::Error => e
105
+ Logger.info e.http_code # eg 422
106
+ Logger.info e.code # eg "auth-declined"
107
+ Logger.info e.message # eg "Invalid phone number format"
106
108
  end
107
109
  ```
108
110
 
data/affirm.gemspec CHANGED
@@ -2,7 +2,7 @@ Gem::Specification.new do |s|
2
2
  s.name = "affirm"
3
3
  s.summary = "Affirm Ruby Client Library"
4
4
  s.description = "Ruby client library for integrating with Affirm financing payments"
5
- s.version = "0.0.1"
5
+ s.version = "1.0.0"
6
6
  s.license = "Apache License Version 2.0"
7
7
  s.author = "Reverb.com"
8
8
  s.email = "dev@reverb.com"
data/lib/affirm/api.rb CHANGED
@@ -4,10 +4,6 @@ module Affirm
4
4
  attr_accessor :public_key, :secret_key, :api_url
5
5
  @@client = nil
6
6
 
7
- def charges
8
- @@charges ||= Affirm::Charges.new(client)
9
- end
10
-
11
7
  def client
12
8
  @@client ||= Affirm::Client.new(
13
9
  public_key: public_key,
@@ -0,0 +1,115 @@
1
+ module Affirm
2
+ class Charge
3
+ attr_reader :id, :amount, :created, :currency, :auth_hold, :payable, :order_id, :events, :details
4
+
5
+ ##
6
+ # RETRIEVE
7
+ #
8
+ # id - (required) string. The charge id, in format 'XXXX-XXXX'
9
+ def self.retrieve(id, client: Affirm::API.client)
10
+ new(attrs: {"id" => id}, client: client).refresh
11
+ end
12
+
13
+ ##
14
+ # CREATE / AUTHORIZE
15
+ #
16
+ # checkout_token - (required) string. The charge token passed through the confirmation response.
17
+ def self.create(checkout_token, client: Affirm::API.client)
18
+ response = client.make_request!("/charges", :post, checkout_token: checkout_token)
19
+
20
+ new(attrs: response.body, client: client)
21
+ end
22
+
23
+ ##
24
+ # CAPTURE
25
+ #
26
+ # order_id - (optional) string. Your internal order id. This is stored for your own future reference.
27
+ # shipping_carrier - (optional) string. The shipping carrier used to ship the items in the charge.
28
+ # shipping_confirmation - (optional) string. The shipping confirmation for the shipment.
29
+ def capture(order_id: nil, shipping_carrier: nil, shipping_confirmation: nil)
30
+ api_request("/charges/#{id}/capture", :post, {
31
+ order_id: order_id,
32
+ shipping_carrier: shipping_carrier,
33
+ shipping_confirmation: shipping_confirmation
34
+ })
35
+ end
36
+
37
+ ##
38
+ # VOID
39
+ #
40
+ def void
41
+ api_request("/charges/#{id}/void", :post)
42
+ end
43
+
44
+ ##
45
+ # REFUND
46
+ #
47
+ # amount - (optional) integer or null. The amount to refund in cents. The default amount is the remaining balance on the charge.
48
+ def refund(amount: nil)
49
+ api_request("/charges/#{id}/refund", :post, {
50
+ amount: amount
51
+ })
52
+ end
53
+
54
+ ##
55
+ # UPDATE
56
+ #
57
+ # order_id - (optional) string. Your internal order id. This is stored for your own future reference.
58
+ # shipping_carrier - (optional) string. The shipping carrier used to ship the items in the charge.
59
+ # shipping_confirmation - (optional) string. The shipping confirmation for the shipment.
60
+ def update(order_id: nil, shipping_carrier: nil, shipping_confirmation: nil)
61
+ api_request("/charges/#{id}/update", :post, {
62
+ order_id: order_id,
63
+ shipping_carrier: shipping_carrier,
64
+ shipping_confirmation: shipping_confirmation
65
+ })
66
+ end
67
+
68
+ def initialize(attrs: {}, client: Affirm::API.client)
69
+ @client = client
70
+ set_attrs(attrs)
71
+ end
72
+
73
+ def refresh
74
+ response = @client.make_request("/charges/#{id}", :get)
75
+
76
+ set_attrs(response.body)
77
+
78
+ self
79
+ end
80
+
81
+ def void?
82
+ @void
83
+ end
84
+
85
+ private
86
+
87
+ def set_attrs(attrs)
88
+ @id = attrs["id"]
89
+ @amount = attrs["amount"]
90
+ @created = attrs["created"]
91
+ @currency = attrs["currency"]
92
+ @auth_hold = attrs["auth_hold"]
93
+ @payable = attrs["payable"]
94
+ @void = attrs["void"]
95
+ @order_id = attrs["order_id"]
96
+ @details = attrs["details"]
97
+ @events = parse_events(attrs["events"])
98
+ end
99
+
100
+ def parse_events(events_attrs)
101
+ if events_attrs
102
+ events_attrs.map { |event| ChargeEvent.new(event) }
103
+ else
104
+ []
105
+ end
106
+ end
107
+
108
+ def api_request(url, method, params={})
109
+ response = @client.make_request!(url, method, params)
110
+ event = ChargeEvent.new(response.body)
111
+ @events << event
112
+ event
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,20 @@
1
+ module Affirm
2
+ class ChargeEvent
3
+ attr_reader :id, :transaction_id, :type, :created,
4
+ :amount, :fee, :order_id, :shipping_carrier, :shipping_confirmation,
5
+ :fee_refunded
6
+
7
+ def initialize(attrs)
8
+ @id = attrs["id"]
9
+ @transaction_id = attrs["transaction_id"]
10
+ @type = attrs["type"]
11
+ @created = attrs["created"]
12
+ @amount = attrs["amount"]
13
+ @fee = attrs["fee"]
14
+ @order_id = attrs["order_id"]
15
+ @shipping_carrier = attrs["shipping_carrier"]
16
+ @shipping_confirmation = attrs["shipping_confirmation"]
17
+ @fee_refunded = attrs["fee_refunded"]
18
+ end
19
+ end
20
+ end
data/lib/affirm/client.rb CHANGED
@@ -28,6 +28,15 @@ module Affirm
28
28
  handle_errors(affirm_response)
29
29
  end
30
30
 
31
+ # like make_request, but raise error on failure
32
+ def make_request!(path, method, data={})
33
+ response = make_request(path, method, data)
34
+
35
+ raise Affirm::Error.from_response(response) if response.error?
36
+
37
+ response
38
+ end
39
+
31
40
  private
32
41
 
33
42
  def parse_response(response)
@@ -6,7 +6,7 @@ module Affirm
6
6
  new(
7
7
  status_code: response.status_code,
8
8
  code: response.code,
9
- message: response.message
9
+ message: response.message || response.raw_body
10
10
  )
11
11
  end
12
12
 
@@ -17,7 +17,11 @@ module Affirm
17
17
  end
18
18
 
19
19
  def to_s
20
- "#{status_code} #{code}: #{message}"
20
+ if code || message
21
+ "#{status_code} - (#{code}) #{message}"
22
+ else
23
+ status_code.to_s
24
+ end
21
25
  end
22
26
  end
23
27
  end
@@ -1,11 +1,11 @@
1
1
  module Affirm
2
2
  class Response
3
- attr_reader :status_code
3
+ attr_reader :status_code, :raw_body
4
4
 
5
5
  def initialize(success:, status_code:, body:)
6
6
  @success = success
7
7
  @status_code = status_code.to_i
8
- @body = body
8
+ @raw_body = body
9
9
  end
10
10
 
11
11
  def success?
@@ -17,7 +17,9 @@ module Affirm
17
17
  end
18
18
 
19
19
  def body
20
- JSON.parse(@body)
20
+ JSON.parse(@raw_body)
21
+ rescue JSON::ParserError
22
+ {}
21
23
  end
22
24
 
23
25
  def type
data/lib/affirm.rb CHANGED
@@ -3,7 +3,8 @@ require 'json'
3
3
  require 'affirm/api'
4
4
  require 'affirm/client'
5
5
  require 'affirm/response'
6
- require 'affirm/charges'
6
+ require 'affirm/charge_event'
7
+ require 'affirm/charge'
7
8
 
8
9
  require 'affirm/errors/error'
9
10
  require 'affirm/errors/authentication_error'
@@ -0,0 +1,242 @@
1
+ require 'spec_helper'
2
+
3
+ describe Affirm::Charge do
4
+ let(:id) { "ABCD" }
5
+ let!(:request) do
6
+ stub_request(request_method, request_url).to_return(status: response_code, body: response_body)
7
+ end
8
+
9
+ let(:response_code) { 200 }
10
+
11
+ let(:charge) { Affirm::Charge.new(attrs: {"id" => id}) }
12
+
13
+ describe "self.retrieve" do
14
+ let(:request_method) { :get }
15
+ let(:request_url) { "#{TEST_URL}/charges/#{id}" }
16
+ let(:response_body) { load_fixture("charges/retrieve.json") }
17
+
18
+ it "returns a charge" do
19
+ charge = Affirm::Charge.retrieve(id)
20
+
21
+ charge.should be_a Affirm::Charge
22
+ end
23
+
24
+ it "sets attributes" do
25
+ charge = Affirm::Charge.retrieve(id)
26
+
27
+ charge.id.should == id
28
+ charge.created.should == "2014-03-18T19:19:04Z"
29
+ charge.currency.should == "USD"
30
+ charge.amount.should == 6100
31
+ charge.auth_hold.should == 6100
32
+ charge.payable.should == 0
33
+ charge.void?.should == false
34
+ end
35
+
36
+ it "parses events" do
37
+ charge = Affirm::Charge.retrieve(id)
38
+ events = charge.events
39
+
40
+ events.length.should == 1
41
+ events.first.type.should == "auth"
42
+ end
43
+
44
+ context "not found" do
45
+ let(:response_code) { 404 }
46
+
47
+ it "raises an error" do
48
+ expect { Affirm::Charge.retrieve(id) }.to raise_error(Affirm::ResourceNotFoundError)
49
+ end
50
+ end
51
+ end
52
+
53
+ describe "self.create" do
54
+ let(:request_method) { :post }
55
+ let(:request_url) { "#{TEST_URL}/charges" }
56
+ let(:response_body) { load_fixture("charges/create.json") }
57
+
58
+ it "returns a charge" do
59
+ charge = Affirm::Charge.create("token")
60
+
61
+ charge.should be_a Affirm::Charge
62
+ charge.id.should == id
63
+ end
64
+
65
+ it "sends the correct body" do
66
+ charge = Affirm::Charge.create("token")
67
+
68
+ expect(WebMock).to have_requested(request_method, request_url).with(body: {
69
+ checkout_token: "token"
70
+ }.to_json)
71
+ end
72
+
73
+ context "failed response" do
74
+ let(:response_code) { 422 }
75
+ let(:response_body) { load_fixture("charges/invalid_request.json") }
76
+
77
+ it "raises an error" do
78
+ expect { Affirm::Charge.create("token") }.to raise_error(Affirm::Error)
79
+ end
80
+ end
81
+ end
82
+
83
+ describe "capture" do
84
+ let(:request_method) { :post }
85
+ let(:request_url) { "#{TEST_URL}/charges/#{id}/capture" }
86
+ let(:response_body) { load_fixture("charges/capture.json") }
87
+
88
+ it "POSTs to the capture url" do
89
+ charge.capture
90
+
91
+ expect(WebMock).to have_requested(request_method, request_url)
92
+ end
93
+
94
+ it "optionally allows tracking params" do
95
+ params = { order_id: "order_id", shipping_carrier: "carrier", shipping_confirmation: "confirmation" }
96
+ charge.capture(params)
97
+
98
+ expect(WebMock).to have_requested(request_method, request_url).with(body: params.to_json)
99
+ end
100
+
101
+ it "adds the event to the charge" do
102
+ expect { charge.capture }.to change { charge.events.length }.by(1)
103
+
104
+ charge.events.last.type.should == "capture"
105
+ end
106
+
107
+ it "returns an event" do
108
+ charge.capture.should be_a Affirm::ChargeEvent
109
+ end
110
+
111
+ context "failed response" do
112
+ let(:response_code) { 422 }
113
+ let(:response_body) { load_fixture("charges/invalid_request.json") }
114
+
115
+ it "raises an error" do
116
+ expect { charge.capture }.to raise_error(Affirm::Error)
117
+ end
118
+ end
119
+ end
120
+
121
+ describe "void" do
122
+ let(:request_method) { :post }
123
+ let(:request_url) { "#{TEST_URL}/charges/#{id}/void" }
124
+ let(:response_body) { load_fixture("charges/void.json") }
125
+
126
+ it "POSTs to the void url" do
127
+ charge.void
128
+
129
+ expect(WebMock).to have_requested(request_method, request_url)
130
+ end
131
+
132
+ it "adds the event to the charge" do
133
+ expect { charge.void }.to change { charge.events.length }.by(1)
134
+
135
+ charge.events.last.type.should == "void"
136
+ end
137
+
138
+ it "returns an event" do
139
+ charge.void.should be_a Affirm::ChargeEvent
140
+ end
141
+
142
+ context "failed response" do
143
+ let(:response_code) { 422 }
144
+ let(:response_body) { load_fixture("charges/invalid_request.json") }
145
+
146
+ it "raises an error" do
147
+ expect { charge.void }.to raise_error(Affirm::Error)
148
+ end
149
+ end
150
+ end
151
+
152
+ describe "refund" do
153
+ let(:request_method) { :post }
154
+ let(:request_url) { "#{TEST_URL}/charges/#{id}/refund" }
155
+ let(:response_body) { load_fixture("charges/refund.json") }
156
+
157
+ it "POSTs to the refund url" do
158
+ charge.refund
159
+
160
+ expect(WebMock).to have_requested(request_method, request_url)
161
+ end
162
+
163
+ it "adds the event to the charge" do
164
+ expect { charge.refund }.to change { charge.events.length }.by(1)
165
+
166
+ charge.events.last.type.should == "refund"
167
+ end
168
+
169
+ it "returns an event" do
170
+ charge.refund.should be_a Affirm::ChargeEvent
171
+ end
172
+
173
+ context "with amount" do
174
+ it "sends the amount" do
175
+ charge.refund(amount: 100)
176
+
177
+ expect(WebMock).to have_requested(request_method, request_url).with(body: {
178
+ amount: 100
179
+ }.to_json)
180
+ end
181
+ end
182
+
183
+ context "failed response" do
184
+ let(:response_code) { 422 }
185
+ let(:response_body) { load_fixture("charges/invalid_request.json") }
186
+
187
+ it "raises an error" do
188
+ expect { charge.refund }.to raise_error(Affirm::Error)
189
+ end
190
+ end
191
+ end
192
+
193
+ describe "update" do
194
+ let(:request_method) { :post }
195
+ let(:request_url) { "#{TEST_URL}/charges/#{id}/update" }
196
+ let(:response_body) { load_fixture("charges/update.json") }
197
+
198
+ it "POSTs to the update url" do
199
+ charge.update
200
+
201
+ expect(WebMock).to have_requested(request_method, request_url)
202
+ end
203
+
204
+ it "optionally allows params" do
205
+ params = { order_id: "order_id", shipping_carrier: "carrier", shipping_confirmation: "confirmation" }
206
+ charge.update(params)
207
+
208
+ expect(WebMock).to have_requested(request_method, request_url).with(body: params.to_json)
209
+ end
210
+
211
+ it "adds the event to the charge" do
212
+ expect { charge.update }.to change { charge.events.length }.by(1)
213
+
214
+ charge.events.last.type.should == "update"
215
+ end
216
+
217
+ it "returns an event" do
218
+ charge.update.should be_a Affirm::ChargeEvent
219
+ end
220
+
221
+ context "failed response" do
222
+ let(:response_code) { 422 }
223
+ let(:response_body) { load_fixture("charges/invalid_request.json") }
224
+
225
+ it "raises an error" do
226
+ expect { charge.update }.to raise_error(Affirm::Error)
227
+ end
228
+ end
229
+ end
230
+
231
+ context "with specified client" do
232
+ let(:client) { Affirm::Client.new(public_key: "other_public", secret_key: "other_secret") }
233
+
234
+ let(:request_method) { :get }
235
+ let(:response_body) { load_fixture("charges/retrieve.json") }
236
+ let(:request_url) { /.*other_public:other_secret.*/ }
237
+
238
+ it "uses the client's creds" do
239
+ Affirm::Charge.retrieve(id, client: client)
240
+ end
241
+ end
242
+ end
data/spec/client_spec.rb CHANGED
@@ -54,10 +54,6 @@ describe Affirm::Client do
54
54
  end
55
55
  end
56
56
  end
57
-
58
- context "authentication error" do
59
-
60
- end
61
57
  end
62
58
 
63
59
  describe "get" do
@@ -137,5 +133,16 @@ describe Affirm::Client do
137
133
  expect { client.get("testpath") }.to raise_error(Affirm::ResourceNotFoundError)
138
134
  end
139
135
  end
136
+
137
+ context "non-json response" do
138
+ before do
139
+ stub_request(:get, affirm_url).
140
+ to_return(status: 500, body: "the server is down")
141
+ end
142
+
143
+ it "doesn't blow up" do
144
+ expect { client.get("testpath") }.to raise_error(Affirm::ServerError)
145
+ end
146
+ end
140
147
  end
141
148
  end
@@ -1,5 +1,5 @@
1
1
  {
2
- "id":"TEST-ALO4-UVGR",
2
+ "id":"ABCD",
3
3
  "created":"2014-03-18T19:19:04Z",
4
4
  "currency":"USD",
5
5
  "amount":6100,
@@ -1,5 +1,5 @@
1
1
  {
2
- "id":"TEST-ALO4-UVGR",
2
+ "id":"ABCD",
3
3
  "created":"2014-03-18T19:19:04Z",
4
4
  "currency":"USD",
5
5
  "amount":6100,
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "created": "2014-10-08T23:48:04Z",
3
3
  "id": "DCPO5PP6QA9V7T60",
4
+ "type": "update",
4
5
  "order_id": "CUSTOM_ORDER_ID",
5
6
  "shipping_carrier": "USPS",
6
7
  "shipping_confirmation": "1Z23223"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: affirm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Reverb.com
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-04-20 00:00:00.000000000 Z
11
+ date: 2015-04-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: typhoeus
@@ -90,20 +90,21 @@ files:
90
90
  - affirm.gemspec
91
91
  - lib/affirm.rb
92
92
  - lib/affirm/api.rb
93
- - lib/affirm/charges.rb
93
+ - lib/affirm/charge.rb
94
+ - lib/affirm/charge_event.rb
94
95
  - lib/affirm/client.rb
95
96
  - lib/affirm/errors/authentication_error.rb
96
97
  - lib/affirm/errors/error.rb
97
98
  - lib/affirm/errors/resource_not_found_error.rb
98
99
  - lib/affirm/errors/server_error.rb
99
100
  - lib/affirm/response.rb
100
- - spec/charges_spec.rb
101
+ - spec/charge_spec.rb
101
102
  - spec/client_spec.rb
102
- - spec/fixtures/charges/authorize.json
103
103
  - spec/fixtures/charges/capture.json
104
- - spec/fixtures/charges/get.json
104
+ - spec/fixtures/charges/create.json
105
105
  - spec/fixtures/charges/invalid_request.json
106
106
  - spec/fixtures/charges/refund.json
107
+ - spec/fixtures/charges/retrieve.json
107
108
  - spec/fixtures/charges/update.json
108
109
  - spec/fixtures/charges/void.json
109
110
  - spec/spec_helper.rb
@@ -1,103 +0,0 @@
1
- module Affirm
2
- class Charges
3
- def initialize(client)
4
- @client = client
5
- @namespace = "charges"
6
- end
7
-
8
- ######
9
- # GET
10
- #
11
- def get(charge_id:)
12
- make_request(charge_id, :get)
13
- end
14
-
15
- ######
16
- # AUTHORIZE
17
- #
18
- # checkout_token - (required) string. The charge token passed through the confirmation response.
19
- def authorize(checkout_token:)
20
- make_request("/", :post, checkout_token: checkout_token)
21
- end
22
-
23
- def authorize!(checkout_token:)
24
- response = authorize(checkout_token: checkout_token)
25
- assert_success(response)
26
- end
27
-
28
- ######
29
- # CAPTURE
30
- #
31
- # order_id - (optional) string. Your internal order id. This is stored for your own future reference.
32
- # shipping_carrier - (optional) string. The shipping carrier used to ship the items in the charge.
33
- # shipping_confirmation - (optional) string. The shipping confirmation for the shipment.
34
- def capture(charge_id:, order_id: nil, shipping_carrier: nil, shipping_confirmation: nil)
35
- make_request("#{charge_id}/capture", :post, {
36
- order_id: order_id,
37
- shipping_carrier: shipping_carrier,
38
- shipping_confirmation: shipping_confirmation
39
- })
40
- end
41
-
42
- def capture!(charge_id:, order_id: nil, shipping_carrier: nil, shipping_confirmation: nil)
43
- response = capture(charge_id: charge_id, order_id: order_id, shipping_carrier: shipping_carrier, shipping_confirmation: shipping_confirmation)
44
- assert_success(response)
45
- end
46
-
47
- ######
48
- # VOID
49
- #
50
- def void(charge_id:)
51
- make_request("#{charge_id}/void", :post)
52
- end
53
-
54
- def void!(charge_id:)
55
- response = void(charge_id: charge_id)
56
- assert_success(response)
57
- end
58
-
59
- ######
60
- # REFUND
61
- #
62
- # amount - (optional) integer or null. The amount to refund in cents. The default amount is the remaining balance on the charge.
63
- def refund(charge_id:, amount: nil)
64
- make_request("#{charge_id}/refund", :post, amount: amount)
65
- end
66
-
67
- def refund!(charge_id:, amount: nil)
68
- response = refund(charge_id: charge_id, amount: amount)
69
- assert_success(response)
70
- end
71
-
72
- ######
73
- # UPDATE
74
- #
75
- # order_id - (optional) string. Your internal order id. This is stored for your own future reference.
76
- # shipping_carrier - (optional) string. The shipping carrier used to ship the items in the charge.
77
- # shipping_confirmation - (optional) string. The shipping confirmation for the shipment.
78
- def update(charge_id:, order_id: nil, shipping_carrier: nil, shipping_confirmation: nil)
79
- make_request("#{charge_id}/update", :post, {
80
- order_id: order_id,
81
- shipping_carrier: shipping_carrier,
82
- shipping_confirmation: shipping_confirmation
83
- })
84
- end
85
-
86
- def update!(charge_id:, order_id: nil, shipping_carrier: nil, shipping_confirmation: nil)
87
- response = update(charge_id: charge_id, order_id: order_id, shipping_carrier: shipping_carrier, shipping_confirmation: shipping_confirmation)
88
- assert_success(response)
89
- end
90
-
91
- private
92
-
93
- def make_request(path, method, data={})
94
- @client.make_request(File.join(@namespace, path), method, data)
95
- end
96
-
97
- def assert_success(response)
98
- raise Affirm::Error.from_response(response) if response.error?
99
-
100
- response
101
- end
102
- end
103
- end
data/spec/charges_spec.rb DELETED
@@ -1,170 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Affirm::Charges do
4
- let!(:request) do
5
- stub_request(request_method, request_url).to_return(status: response_code, body: response_body)
6
- end
7
-
8
- let(:response_code) { 200 }
9
-
10
- describe "self.get" do
11
- let(:request_method) { :get }
12
- let(:request_url) { "#{TEST_URL}/charges/ABCD" }
13
- let(:response_body) { load_fixture("charges/get.json") }
14
-
15
- it "is successful" do
16
- response = Affirm::API.charges.get(charge_id: "ABCD")
17
- response.should be_success
18
- response.body["amount"].should == 6100
19
- end
20
- end
21
-
22
- describe "self.authorize" do
23
- let(:request_method) { :post }
24
- let(:request_url) { "#{TEST_URL}/charges/" }
25
- let(:response_body) { load_fixture("charges/authorize.json") }
26
-
27
- it "is successful" do
28
- response = Affirm::API.charges.authorize(checkout_token: "token")
29
- response.should be_success
30
- end
31
-
32
- it "sends the correct body" do
33
- Affirm::API.charges.authorize(checkout_token: "token")
34
-
35
- expect(WebMock).to have_requested(request_method, request_url).with(body: {
36
- checkout_token: "token"
37
- }.to_json)
38
- end
39
-
40
- context "bang method" do
41
- let(:response_code) { 422 }
42
- let(:response_body) { load_fixture("charges/invalid_request.json") }
43
-
44
- it "raises an error on failure" do
45
- expect { Affirm::API.charges.authorize!(checkout_token: "token") }.to raise_error(Affirm::Error)
46
- end
47
- end
48
- end
49
-
50
- describe "self.capture" do
51
- let(:request_method) { :post }
52
- let(:request_url) { "#{TEST_URL}/charges/ABCD/capture" }
53
- let(:response_body) { load_fixture("charges/capture.json") }
54
-
55
- it "is successful" do
56
- response = Affirm::API.charges.capture(charge_id: "ABCD")
57
- response.should be_success
58
- end
59
-
60
- it "optionally allows tracking params" do
61
- params = { order_id: "order_id", shipping_carrier: "carrier", shipping_confirmation: "confirmation" }
62
- Affirm::API.charges.capture({charge_id: "ABCD"}.merge(params))
63
-
64
- expect(WebMock).to have_requested(request_method, request_url).with(body: params.to_json)
65
- end
66
-
67
- context "bang method" do
68
- let(:response_code) { 422 }
69
- let(:response_body) { load_fixture("charges/invalid_request.json") }
70
-
71
- it "raises an error on failure" do
72
- expect { Affirm::API.charges.capture!(charge_id: "ABCD") }.to raise_error(Affirm::Error)
73
- end
74
- end
75
- end
76
-
77
- describe "self.void" do
78
- let(:request_method) { :post }
79
- let(:request_url) { "#{TEST_URL}/charges/ABCD/void" }
80
- let(:response_body) { load_fixture("charges/void.json") }
81
-
82
- it "is successful" do
83
- response = Affirm::API.charges.void(charge_id: "ABCD")
84
- response.should be_success
85
- end
86
-
87
- context "bang method" do
88
- let(:response_code) { 422 }
89
- let(:response_body) { load_fixture("charges/invalid_request.json") }
90
-
91
- it "raises an error on failure" do
92
- expect { Affirm::API.charges.void!(charge_id: "ABCD") }.to raise_error(Affirm::Error)
93
- end
94
- end
95
- end
96
-
97
- describe "self.refund" do
98
- let(:request_method) { :post }
99
- let(:request_url) { "#{TEST_URL}/charges/ABCD/refund" }
100
- let(:response_body) { load_fixture("charges/refund.json") }
101
-
102
- it "is successful" do
103
- response = Affirm::API.charges.refund(charge_id: "ABCD")
104
- response.should be_success
105
- end
106
-
107
- context "with amount" do
108
- it "sends the correct body" do
109
- Affirm::API.charges.refund(charge_id: "ABCD", amount: 100)
110
-
111
- expect(WebMock).to have_requested(request_method, request_url).with(body: {
112
- amount: 100
113
- }.to_json)
114
- end
115
- end
116
-
117
- context "bang method" do
118
- let(:response_code) { 422 }
119
- let(:response_body) { load_fixture("charges/invalid_request.json") }
120
-
121
- it "raises an error on failure" do
122
- expect { Affirm::API.charges.refund!(charge_id: "ABCD") }.to raise_error(Affirm::Error)
123
- end
124
- end
125
- end
126
-
127
- describe "self.update" do
128
- let(:request_method) { :post }
129
- let(:request_url) { "#{TEST_URL}/charges/ABCD/update" }
130
- let(:response_body) { load_fixture("charges/update.json") }
131
-
132
- it "is successful" do
133
- response = Affirm::API.charges.update(charge_id: "ABCD", order_id: "order_id", shipping_carrier: "carrier", shipping_confirmation: "confirmation")
134
- response.should be_success
135
- end
136
-
137
- it "sends the correct body" do
138
- params = { order_id: "order_id", shipping_carrier: "carrier", shipping_confirmation: "confirmation" }
139
- Affirm::API.charges.update({charge_id: "ABCD"}.merge(params))
140
-
141
- expect(WebMock).to have_requested(request_method, request_url).with(body: params.to_json)
142
- end
143
-
144
- it "doesn't require the params" do
145
- response = Affirm::API.charges.update(charge_id: "ABCD")
146
- response.should be_success
147
- end
148
-
149
- context "bang method" do
150
- let(:response_code) { 422 }
151
- let(:response_body) { load_fixture("charges/invalid_request.json") }
152
-
153
- it "raises an error on failure" do
154
- expect { Affirm::API.charges.update!(charge_id: "ABCD") }.to raise_error(Affirm::Error)
155
- end
156
- end
157
- end
158
-
159
- context "with specified client" do
160
- let(:client) { Affirm::Client.new(public_key: "other_public", secret_key: "other_secret") }
161
-
162
- let(:request_method) { :get }
163
- let(:response_body) { load_fixture("charges/get.json") }
164
- let(:request_url) { /.*other_public:other_secret.*/ }
165
-
166
- it "uses the client's creds" do
167
- described_class.new(client).get(charge_id: "ABCD")
168
- end
169
- end
170
- end