bitpay-sdk 2.3.3 → 2.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -1
- data/GUIDE.md +9 -2
- data/config/capybara.rb +1 -1
- data/config/constants.rb +4 -0
- data/features/pairing.feature +3 -3
- data/features/refunds.feature +20 -0
- data/features/retrieving_invoices.feature +6 -2
- data/features/step_definitions/invoice_steps.rb +10 -5
- data/features/step_definitions/keygen_steps.rb +8 -6
- data/features/step_definitions/refund_steps.rb +37 -0
- data/features/step_definitions/step_helpers.rb +17 -2
- data/lib/bitpay/client.rb +68 -6
- data/lib/bitpay/rest_connector.rb +12 -3
- data/lib/bitpay/version.rb +1 -1
- data/spec/client_spec.rb +51 -0
- data/spec/fixtures/invoices_{id}_refunds_{refund_id}-GET.json +8 -6
- data/spec/set_constants.sh +4 -2
- metadata +4 -3
- data/CHANGELOG.md +0 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 934b96a7f24134990a0cfed00c6e3b50502c3823
|
4
|
+
data.tar.gz: 68a05391e925b79b565f7cc2400ce7a101bc5ebf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b9c62e5a6a700b1c73c928f27c5cff0436ddb33bffd2292e18248046b89ce9c54b65918b151a3f9a32559e42c239da02c20fc326d350f1369cedad6748cc9089
|
7
|
+
data.tar.gz: 56ab8bfb2b86bd9e15a5f7165a0e58b98eb92ac987868e9789d6167a19f15645f99157680fe17c313dcf692f21dcd94779507881710198f3738e05a298222698
|
data/.gitignore
CHANGED
data/GUIDE.md
CHANGED
@@ -154,6 +154,13 @@ client.get_all_refunds_for_invoice(id: 'PvVhgBfA7wKPWhuVC24rJo')
|
|
154
154
|
# To get a specific refund for a specific invoice
|
155
155
|
client.get_refund(id: 'JB49z2MsDH7FunczeyDS8j', request_id: '4evCrXq4EDXk4oqDXdWQhX')
|
156
156
|
```
|
157
|
+
### Cancel Refund Requests
|
158
|
+
|
159
|
+
Requires a `merchant` token.
|
160
|
+
|
161
|
+
```ruby
|
162
|
+
client.cancel_refund(id: 'JB49z2MsDH7FunczeyDS8j', request_id: '4evCrXq4EDXk4oqDXdWQhX')
|
163
|
+
```
|
157
164
|
|
158
165
|
### Make a HTTP request directly against the REST API
|
159
166
|
|
@@ -187,10 +194,10 @@ API Documentation is available on the [BitPay site](https://bitpay.com/api).
|
|
187
194
|
|
188
195
|
In order to run the tests, you must have phantomjs installed and on your PATH.
|
189
196
|
|
190
|
-
The tests require that environment variables be set for the bitpay server, user name, and
|
197
|
+
The tests require that environment variables be set for the bitpay server, user name, password, an invoice id for refunds and a valid testnet bitcoin address for refunds. First run:
|
191
198
|
|
192
199
|
```bash
|
193
|
-
$ source ./spec/set_constants.sh https://test.bitpay.com <yourusername> <yourpassword>
|
200
|
+
$ source ./spec/set_constants.sh https://test.bitpay.com <yourusername> <yourpassword> <a-confirmed-invoice-id> <a-valid-testnet-address>
|
194
201
|
$ bundle install
|
195
202
|
$ bundle exec rake
|
196
203
|
```
|
data/config/capybara.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Capybara.javascript_driver = :poltergeist
|
2
2
|
Capybara.default_driver = :poltergeist
|
3
|
-
Capybara.default_wait_time =
|
3
|
+
Capybara.default_wait_time = 10
|
4
4
|
Capybara.register_driver :poltergeist do |app|
|
5
5
|
Capybara::Poltergeist::Driver.new(app, timeout: 60, js_errors: false, phantomjs_options: ['--ignore-ssl-errors=yes', '--ssl-protocol=TLSv1', '--web-security=false'])
|
6
6
|
end
|
data/config/constants.rb
CHANGED
@@ -10,6 +10,10 @@ TEST_USER = ENV['RCTESTUSER']
|
|
10
10
|
TEST_PASS = ENV['RCTESTPASSWORD']
|
11
11
|
DASHBOARD_URL = "#{ROOT_ADDRESS}/dashboard/merchant/home"
|
12
12
|
|
13
|
+
# Specify a bitpay txid which has 6+ confirmations. Default belongs to 'bitpayrubyclient@gmail.com' test account
|
14
|
+
REFUND_TRANSACTION = ENV['REFUND_TRANSACTION']
|
15
|
+
REFUND_ADDRESS = ENV['REFUND_ADDRESS']
|
16
|
+
|
13
17
|
unless
|
14
18
|
ROOT_ADDRESS &&
|
15
19
|
TEST_USER &&
|
data/features/pairing.feature
CHANGED
@@ -6,10 +6,10 @@ Feature: pairing with bitpay
|
|
6
6
|
Scenario: the client has a correct pairing code
|
7
7
|
Given the user pairs with BitPay with a valid pairing code
|
8
8
|
Then the user is paired with BitPay
|
9
|
-
|
9
|
+
|
10
10
|
Scenario: the client initiates pairing
|
11
|
-
Given the user
|
12
|
-
Then
|
11
|
+
Given the user performs a client-side pairing
|
12
|
+
Then the user has a merchant token
|
13
13
|
|
14
14
|
Scenario Outline: the client has a bad pairing code
|
15
15
|
Given the user fails to pair with a semantically <valid> code <code>
|
@@ -0,0 +1,20 @@
|
|
1
|
+
@refunds
|
2
|
+
Feature: issuing a refund
|
3
|
+
The merchant wants to issue a refund
|
4
|
+
So that they can serve their customers
|
5
|
+
|
6
|
+
Scenario: creating a refund
|
7
|
+
Given the user creates a refund
|
8
|
+
Then they will receive a refund id
|
9
|
+
|
10
|
+
Scenario: retrieving a refund
|
11
|
+
Given the user requests a specific refund
|
12
|
+
Then they will receive the refund
|
13
|
+
|
14
|
+
Scenario: retrieving all refunds
|
15
|
+
Given the user requests all refunds for an invoice
|
16
|
+
Then they will receive an array of refunds
|
17
|
+
|
18
|
+
Scenario: canceling a refund
|
19
|
+
Given a properly formatted cancellation request
|
20
|
+
Then the refund will be cancelled
|
@@ -2,6 +2,10 @@ Feature: retrieving an invoice
|
|
2
2
|
The user may want to retrieve invoices
|
3
3
|
So that they can view them
|
4
4
|
|
5
|
-
Scenario:
|
5
|
+
Scenario: Correct public request
|
6
6
|
Given that a user knows an invoice id
|
7
|
-
Then they can retrieve that invoice
|
7
|
+
Then they can retrieve the public version of that invoice
|
8
|
+
|
9
|
+
Scenario: Correct merchant request
|
10
|
+
Given that a user knows an invoice id
|
11
|
+
Then they can retrieve the merchant-scoped version of that invoice
|
@@ -1,6 +1,6 @@
|
|
1
1
|
When(/^the user (?:tries to |)creates? an invoice (?:for|without) "(.*?)" (?:or |and |)"(.*?)"$/) do |price, currency|
|
2
2
|
begin
|
3
|
-
@response = @client.create_invoice(price: price, currency: currency)
|
3
|
+
@response = @client.create_invoice(price: price, currency: currency, facade: 'merchant')
|
4
4
|
rescue => error
|
5
5
|
@error = error
|
6
6
|
end
|
@@ -15,12 +15,17 @@ Given(/^there is an invalid token$/) do
|
|
15
15
|
end
|
16
16
|
|
17
17
|
Given(/^that a user knows an invoice id$/) do
|
18
|
-
client = new_client_from_stored_values
|
19
|
-
@id = (client.create_invoice(price: 3, currency: "USD" ))['id']
|
18
|
+
@client = new_client_from_stored_values
|
19
|
+
@id = (@client.create_invoice(price: 3, currency: "USD", facade: 'merchant' ))['id']
|
20
20
|
end
|
21
21
|
|
22
|
-
Then(/^they can retrieve that invoice$/) do
|
23
|
-
invoice =
|
22
|
+
Then(/^they can retrieve the public version of that invoice$/) do
|
23
|
+
invoice = @client.get_public_invoice(id: @id)
|
24
|
+
raise "That's the wrong invoice" unless invoice['id'] == @id
|
25
|
+
end
|
26
|
+
|
27
|
+
Then(/^they can retrieve the merchant\-scoped version of that invoice$/) do
|
28
|
+
invoice = @client.get_invoice(id: @id)
|
24
29
|
raise "That's the wrong invoice" unless invoice['id'] == @id
|
25
30
|
end
|
26
31
|
|
@@ -31,7 +31,6 @@ Given(/^the user is paired with BitPay$/) do
|
|
31
31
|
raise "Client is not paired" unless @client.verify_tokens
|
32
32
|
end
|
33
33
|
|
34
|
-
|
35
34
|
Given(/^the user has a bad pairing_code "(.*?)"$/) do |arg1|
|
36
35
|
# This is a no-op, pairing codes are transient and never actually saved
|
37
36
|
end
|
@@ -53,13 +52,16 @@ Then(/^they will receive an? (.*?) matching "(.*?)"$/) do |error_class, error_me
|
|
53
52
|
raise "Error: #{@error.class}, message: #{@error.message}" unless Object.const_get(error_class) == @error.class && @error.message.include?(error_message)
|
54
53
|
end
|
55
54
|
|
56
|
-
Given(/^the user
|
55
|
+
Given(/^the user performs a client\-side pairing$/) do
|
57
56
|
sleep 1
|
58
57
|
pem = BitPay::KeyUtils.generate_pem
|
59
|
-
client = BitPay::SDK::Client.new(api_uri: ROOT_ADDRESS, pem: pem, insecure: true)
|
60
|
-
|
58
|
+
@client = BitPay::SDK::Client.new(api_uri: ROOT_ADDRESS, pem: pem, insecure: true)
|
59
|
+
response = @client.pair_client({facade: 'merchant'})
|
60
|
+
@token = response.first["token"]
|
61
|
+
approve_token_on_server(response.first["pairingCode"])
|
61
62
|
end
|
62
63
|
|
63
|
-
Then(/^
|
64
|
-
|
64
|
+
Then(/^the user has a merchant token$/) do
|
65
|
+
tokens = {'merchant' => @token}
|
66
|
+
raise "Merchant token not authorized" unless @client.verify_tokens(tokens: tokens)
|
65
67
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
Given(/^the user creates a refund$/) do
|
2
|
+
client = new_client_from_stored_values
|
3
|
+
@response = client.refund_invoice(id: REFUND_TRANSACTION, params: {amount: 1, currency: 'USD', bitcoinAddress: REFUND_ADDRESS})
|
4
|
+
end
|
5
|
+
|
6
|
+
Then(/^they will receive a refund id$/) do
|
7
|
+
@refund_id = @response["id"]
|
8
|
+
expect(@refund_id).not_to be_empty
|
9
|
+
end
|
10
|
+
|
11
|
+
Given(/^the user requests a specific refund$/) do
|
12
|
+
client = new_client_from_stored_values
|
13
|
+
@response = client.get_refund(invoice_id: REFUND_TRANSACTION, request_id: @refund_id)
|
14
|
+
end
|
15
|
+
|
16
|
+
Then(/^they will receive the refund$/) do
|
17
|
+
expect(@response.first["status"]).not_to be_empty
|
18
|
+
end
|
19
|
+
|
20
|
+
Given(/^the user requests all refunds for an invoice$/) do
|
21
|
+
client = new_client_from_stored_values
|
22
|
+
@response = client.get_all_refunds_for_invoice(id: REFUND_TRANSACTION)
|
23
|
+
end
|
24
|
+
|
25
|
+
Then(/^they will receive an array of refunds$/) do
|
26
|
+
expect(@response).to be_instance_of Array
|
27
|
+
end
|
28
|
+
|
29
|
+
Given(/^a properly formatted cancellation request$/) do
|
30
|
+
client = new_client_from_stored_values
|
31
|
+
@refund_id = client.get_all_refunds_for_invoice(id: REFUND_TRANSACTION).first["id"]
|
32
|
+
@response = client.cancel_refund(invoice_id: REFUND_TRANSACTION, request_id: @refund_id)
|
33
|
+
end
|
34
|
+
|
35
|
+
Then(/^the refund will be cancelled$/) do
|
36
|
+
expect(@response).to eq("Success")
|
37
|
+
end
|
@@ -29,6 +29,17 @@ def get_claim_code_from_server
|
|
29
29
|
Capybara::find(".token-claimcode", match: :first).text
|
30
30
|
end
|
31
31
|
|
32
|
+
def approve_token_on_server(pairing_code)
|
33
|
+
Capybara::visit ROOT_ADDRESS
|
34
|
+
log_in unless logged_in
|
35
|
+
Capybara::visit DASHBOARD_URL
|
36
|
+
raise "Bad Login" unless Capybara.current_session.current_url == DASHBOARD_URL
|
37
|
+
Capybara::visit "#{ROOT_ADDRESS}/api-tokens"
|
38
|
+
Capybara::fill_in 'pairingCode', :with => pairing_code
|
39
|
+
Capybara::click_button "Find"
|
40
|
+
Capybara::click_button "Approve"
|
41
|
+
end
|
42
|
+
|
32
43
|
def log_in
|
33
44
|
Capybara::visit "#{ROOT_ADDRESS}/dashboard/login/"
|
34
45
|
Capybara::fill_in 'email', :with => TEST_USER
|
@@ -53,11 +64,15 @@ def new_client_from_stored_values
|
|
53
64
|
unless client.verify_tokens then
|
54
65
|
raise "Locally stored tokens are invalid, please remove #{BitPay::TOKEN_FILE_PATH}" end
|
55
66
|
else
|
56
|
-
claim_code = get_claim_code_from_server
|
57
67
|
pem = BitPay::KeyUtils.generate_pem
|
58
68
|
client = BitPay::SDK::Client.new(api_uri: ROOT_ADDRESS, pem: pem, insecure: true)
|
59
69
|
sleep 1 # rate limit compliance
|
60
|
-
|
70
|
+
response = client.pair_client({facade: 'merchant'})
|
71
|
+
pairing_code = response.first["pairingCode"]
|
72
|
+
token = response #.first["token"]
|
73
|
+
approve_token_on_server(pairing_code)
|
74
|
+
|
75
|
+
|
61
76
|
FileUtils.mkdir_p(BitPay::BITPAY_CREDENTIALS_DIR)
|
62
77
|
File.write(BitPay::PRIVATE_KEY_PATH, pem)
|
63
78
|
File.write(BitPay::TOKEN_FILE_PATH, JSON.generate(token))
|
data/lib/bitpay/client.rb
CHANGED
@@ -47,8 +47,7 @@ module BitPay
|
|
47
47
|
# => Pass {pairingCode: 'WfD01d2'} to claim a server-initiated pairing code
|
48
48
|
#
|
49
49
|
def pair_client(params={})
|
50
|
-
|
51
|
-
return tokens["data"]
|
50
|
+
post(path: 'tokens', params: params)
|
52
51
|
end
|
53
52
|
|
54
53
|
## Compatibility method for pos pairing
|
@@ -70,17 +69,80 @@ module BitPay
|
|
70
69
|
raise BitPay::ArgumentError, "Illegal Argument: Currency is invalid." unless /^[[:upper:]]{3}$/.match(currency)
|
71
70
|
params.merge!({price: price, currency: currency})
|
72
71
|
token = get_token(facade)
|
73
|
-
|
74
|
-
|
72
|
+
post(path: "invoices", token: token, params: params)
|
73
|
+
end
|
74
|
+
|
75
|
+
## Gets the privileged merchant-version of the invoice
|
76
|
+
# Requires merchant facade token
|
77
|
+
#
|
78
|
+
def get_invoice(id:)
|
79
|
+
token = get_token('merchant')
|
80
|
+
get(path: "invoices/#{id}", token: token)
|
75
81
|
end
|
76
82
|
|
77
83
|
## Gets the public version of the invoice
|
78
84
|
#
|
79
85
|
def get_public_invoice(id:)
|
80
|
-
|
81
|
-
invoice["data"]
|
86
|
+
get(path: "invoices/#{id}", public: true)
|
82
87
|
end
|
83
88
|
|
89
|
+
|
90
|
+
## Refund paid BitPay invoice
|
91
|
+
#
|
92
|
+
# If invoice["data"]["flags"]["refundable"] == true the a refund address was
|
93
|
+
# provided with the payment and the refund_address parameter is an optional override
|
94
|
+
#
|
95
|
+
# Amount and Currency are required fields for fully paid invoices but optional
|
96
|
+
# for under or overpaid invoices which will otherwise be completely refunded
|
97
|
+
#
|
98
|
+
# Requires merchant facade token
|
99
|
+
#
|
100
|
+
# @example
|
101
|
+
# client.refund_invoice(id: 'JB49z2MsDH7FunczeyDS8j', params: {amount: 10, currency: 'USD', bitcoinAddress: '1Jtcygf8W3cEmtGgepggtjCxtmFFjrZwRV'})
|
102
|
+
#
|
103
|
+
def refund_invoice(id:, params:{})
|
104
|
+
invoice = get_invoice(id: id)
|
105
|
+
post(path: "invoices/#{id}/refunds", token: invoice["token"], params: params)
|
106
|
+
end
|
107
|
+
|
108
|
+
## Get All Refunds for Invoice
|
109
|
+
# Returns an array of all refund requests for a specific invoice,
|
110
|
+
#
|
111
|
+
# Requires merchant facade token
|
112
|
+
#
|
113
|
+
# @example:
|
114
|
+
# client.get_all_refunds_for_invoice(id: 'JB49z2MsDH7FunczeyDS8j')
|
115
|
+
#
|
116
|
+
def get_all_refunds_for_invoice(id:)
|
117
|
+
urlpath = "invoices/#{id}/refunds"
|
118
|
+
invoice = get_invoice(id: id)
|
119
|
+
get(path: urlpath, token: invoice["token"])
|
120
|
+
end
|
121
|
+
|
122
|
+
## Get Refund
|
123
|
+
# Requires merchant facade token
|
124
|
+
#
|
125
|
+
# @example:
|
126
|
+
# client.get_refund(id: 'JB49z2MsDH7FunczeyDS8j', request_id: '4evCrXq4EDXk4oqDXdWQhX')
|
127
|
+
#
|
128
|
+
def get_refund(invoice_id:, request_id:)
|
129
|
+
urlpath = "invoices/#{invoice_id}/refunds/#{request_id}"
|
130
|
+
invoice = get_invoice(id: invoice_id)
|
131
|
+
get(path: urlpath, token: invoice["token"])
|
132
|
+
end
|
133
|
+
|
134
|
+
## Cancel Refund
|
135
|
+
# Requires merchant facade token
|
136
|
+
#
|
137
|
+
# @example:
|
138
|
+
# client.cancel_refund(id: 'JB49z2MsDH7FunczeyDS8j', request_id: '4evCrXq4EDXk4oqDXdWQhX')
|
139
|
+
#
|
140
|
+
def cancel_refund(invoice_id:, request_id:)
|
141
|
+
urlpath = "invoices/#{invoice_id}/refunds/#{request_id}"
|
142
|
+
refund = get_refund(invoice_id: invoice_id, request_id: request_id)
|
143
|
+
delete(path: urlpath, token: refund["token"])
|
144
|
+
end
|
145
|
+
|
84
146
|
## Checks that the passed tokens are valid by
|
85
147
|
# comparing them to those that are authorized by the server
|
86
148
|
#
|
@@ -8,7 +8,7 @@ module BitPay
|
|
8
8
|
token ||= get_token(facade)
|
9
9
|
case verb.upcase
|
10
10
|
when "GET"
|
11
|
-
return get(path: path, token:token)
|
11
|
+
return get(path: path, token: token)
|
12
12
|
when "POST"
|
13
13
|
return post(path: path, token: token, params: params)
|
14
14
|
else
|
@@ -41,6 +41,15 @@ module BitPay
|
|
41
41
|
process_request(request)
|
42
42
|
end
|
43
43
|
|
44
|
+
def delete(path:, token: nil)
|
45
|
+
urlpath = '/' + path
|
46
|
+
urlpath = urlpath + '?token=' + token if token
|
47
|
+
request = Net::HTTP::Delete.new urlpath
|
48
|
+
request['X-Signature'] = KeyUtils.sign(@uri.to_s + urlpath, @priv_key)
|
49
|
+
request['X-Identity'] = @pub_key
|
50
|
+
process_request(request)
|
51
|
+
end
|
52
|
+
|
44
53
|
private
|
45
54
|
|
46
55
|
## Processes HTTP Request and returns parsed response
|
@@ -58,7 +67,7 @@ module BitPay
|
|
58
67
|
end
|
59
68
|
|
60
69
|
if response.kind_of? Net::HTTPSuccess
|
61
|
-
return JSON.parse(response.body)
|
70
|
+
return JSON.parse(response.body)["data"]
|
62
71
|
elsif JSON.parse(response.body)["error"]
|
63
72
|
raise(BitPayError, "#{response.code}: #{JSON.parse(response.body)['error']}")
|
64
73
|
else
|
@@ -71,7 +80,7 @@ module BitPay
|
|
71
80
|
# updates @tokens
|
72
81
|
#
|
73
82
|
def refresh_tokens
|
74
|
-
response = get(path: 'tokens')
|
83
|
+
response = get(path: 'tokens')
|
75
84
|
token_array = response || {}
|
76
85
|
tokens = {}
|
77
86
|
token_array.each do |t|
|
data/lib/bitpay/version.rb
CHANGED
data/spec/client_spec.rb
CHANGED
@@ -19,6 +19,12 @@ describe BitPay::SDK::Client do
|
|
19
19
|
.to_return(:status => 200, :body => tokens.to_json, :headers => {})
|
20
20
|
stub_request(:get, "#{BitPay::TEST_API_URI}/invoices/TEST_INVOICE_ID?token=MERCHANT_TOKEN").
|
21
21
|
to_return(:body => get_fixture('invoices_{id}-GET.json'))
|
22
|
+
stub_request(:get, "#{BitPay::TEST_API_URI}/invoices/TEST_INVOICE_ID/refunds?token=MERCHANT_INVOICE_TOKEN").
|
23
|
+
to_return(:body => get_fixture('invoices_{id}_refunds-GET.json'))
|
24
|
+
stub_request(:get, "#{BitPay::TEST_API_URI}/invoices/TEST_INVOICE_ID/refunds/TEST_REQUEST_ID?token=MERCHANT_INVOICE_TOKEN").
|
25
|
+
to_return(:body => get_fixture('invoices_{id}_refunds-GET.json'))
|
26
|
+
stub_request(:post, "#{BitPay::TEST_API_URI}/invoices/TEST_INVOICE_ID/refunds").
|
27
|
+
to_return(:body => get_fixture('invoices_{id}_refunds-POST.json'))
|
22
28
|
end
|
23
29
|
|
24
30
|
describe "#initialize" do
|
@@ -109,6 +115,51 @@ describe BitPay::SDK::Client do
|
|
109
115
|
end
|
110
116
|
end
|
111
117
|
|
118
|
+
describe '#refund_invoice' do
|
119
|
+
subject { bitpay_client }
|
120
|
+
before { stub_const('ENV', {'BITPAY_PEM' => PEM}) }
|
121
|
+
it { is_expected.to respond_to(:refund_invoice) }
|
122
|
+
|
123
|
+
it 'should get the token for the invoice' do
|
124
|
+
bitpay_client.refund_invoice(id: 'TEST_INVOICE_ID')
|
125
|
+
expect(WebMock).to have_requested :get, "#{BitPay::TEST_API_URI}/invoices/TEST_INVOICE_ID?token=MERCHANT_TOKEN"
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'should generate a POST to the invoices/refund endpoint' do
|
129
|
+
bitpay_client.refund_invoice(id: 'TEST_INVOICE_ID')
|
130
|
+
expect(WebMock).to have_requested :post, "#{BitPay::TEST_API_URI}/invoices/TEST_INVOICE_ID/refunds"
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
describe '#get_all_refunds_for_invoice' do
|
135
|
+
subject { bitpay_client }
|
136
|
+
before {stub_const('ENV', {'BITPAY_PEM' => PEM})}
|
137
|
+
it { is_expected.to respond_to(:get_all_refunds_for_invoice) }
|
138
|
+
|
139
|
+
it 'should get the token for the invoice' do
|
140
|
+
bitpay_client.get_all_refunds_for_invoice(id: 'TEST_INVOICE_ID')
|
141
|
+
expect(WebMock).to have_requested :get, "#{BitPay::TEST_API_URI}/invoices/TEST_INVOICE_ID?token=MERCHANT_TOKEN"
|
142
|
+
end
|
143
|
+
it 'should GET all refunds' do
|
144
|
+
bitpay_client.get_all_refunds_for_invoice(id: 'TEST_INVOICE_ID')
|
145
|
+
expect(WebMock).to have_requested :get, "#{BitPay::TEST_API_URI}/invoices/TEST_INVOICE_ID/refunds?token=MERCHANT_INVOICE_TOKEN"
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
describe '#get_refund' do
|
150
|
+
subject { bitpay_client }
|
151
|
+
before {stub_const('ENV', {'BITPAY_PEM' => PEM})}
|
152
|
+
it { is_expected.to respond_to(:get_refund) }
|
153
|
+
it 'should get the token for the invoice' do
|
154
|
+
bitpay_client.get_refund(invoice_id: 'TEST_INVOICE_ID', request_id: 'TEST_REQUEST_ID')
|
155
|
+
expect(WebMock).to have_requested :get, "#{BitPay::TEST_API_URI}/invoices/TEST_INVOICE_ID?token=MERCHANT_TOKEN"
|
156
|
+
end
|
157
|
+
it 'should GET a single refund' do
|
158
|
+
bitpay_client.get_refund(invoice_id: 'TEST_INVOICE_ID', request_id: 'TEST_REQUEST_ID')
|
159
|
+
expect(WebMock).to have_requested :get, "#{BitPay::TEST_API_URI}/invoices/TEST_INVOICE_ID/refunds/TEST_REQUEST_ID?token=MERCHANT_INVOICE_TOKEN"
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
112
163
|
describe "#verify_tokens" do
|
113
164
|
subject { bitpay_client }
|
114
165
|
before {stub_const('ENV', {'BITPAY_PEM' => PEM})}
|
@@ -1,9 +1,11 @@
|
|
1
1
|
{
|
2
2
|
"facade": "merchant/supportRequest",
|
3
|
-
"data":
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
3
|
+
"data": [
|
4
|
+
{
|
5
|
+
"id": "TEST_REQUEST_ID",
|
6
|
+
"requestDate": "2015-01-27T00:36:12.360Z",
|
7
|
+
"status": "pending",
|
8
|
+
"token": "REFUND_REQUEST_TOKEN"
|
9
|
+
}
|
10
|
+
]
|
9
11
|
}
|
data/spec/set_constants.sh
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bitpay-sdk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bitpay, Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-03-
|
11
|
+
date: 2015-03-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json
|
@@ -215,7 +215,6 @@ extra_rdoc_files: []
|
|
215
215
|
files:
|
216
216
|
- ".gitignore"
|
217
217
|
- ".travis.yml"
|
218
|
-
- CHANGELOG.md
|
219
218
|
- GUIDE.md
|
220
219
|
- Gemfile
|
221
220
|
- LICENSE.md
|
@@ -226,9 +225,11 @@ files:
|
|
226
225
|
- config/constants.rb
|
227
226
|
- features/creating_invoices.feature
|
228
227
|
- features/pairing.feature
|
228
|
+
- features/refunds.feature
|
229
229
|
- features/retrieving_invoices.feature
|
230
230
|
- features/step_definitions/invoice_steps.rb
|
231
231
|
- features/step_definitions/keygen_steps.rb
|
232
|
+
- features/step_definitions/refund_steps.rb
|
232
233
|
- features/step_definitions/step_helpers.rb
|
233
234
|
- lib/bitpay/cacert.pem
|
234
235
|
- lib/bitpay/client.rb
|
data/CHANGELOG.md
DELETED
@@ -1,11 +0,0 @@
|
|
1
|
-
# Change Log
|
2
|
-
All notable changes to this project will be documented in this file.
|
3
|
-
This project adheres to [Semantic Versioning](http://semver.org/).
|
4
|
-
|
5
|
-
## [2.3.3] - 2015-03-12
|
6
|
-
### Changed
|
7
|
-
- Pull refund functionality from 2.3 spec
|
8
|
-
- Bump gem version
|
9
|
-
|
10
|
-
### Fixed
|
11
|
-
- Fix Bug: GitHub issue #40 - error on return from endpoints that do not have a "data" field
|