bitpay-client 2.0.0 → 2.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 +4 -4
- data/README.md +5 -5
- data/config/capybara.rb +1 -1
- data/lib/bitpay/client.rb +30 -27
- data/lib/bitpay/key_utils.rb +1 -1
- data/lib/bitpay/version.rb +1 -1
- data/spec/client_spec.rb +7 -2
- data/spec/features/pair_spec.rb +3 -1
- data/spec/features/pos_spec.rb +2 -1
- data/spec/key_utils_spec.rb +13 -7
- data/spec/spec_helper.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1d735bbff357cf079a5f5ea6c357e3375644cde5
|
4
|
+
data.tar.gz: 55b7d5cbbe130d8412e74db9798e1a7bad3ac827
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 43df16582f56058a03896e433f62a8c4338dd40c7598192d0811f437e628ebe601e53d28aa54913fae88a5f89f48b3306255df4153825d136f65504d468de85e
|
7
|
+
data.tar.gz: 4b679cc6bdae90dbb028081457b8990cf2c33ccc75024e43378ad7a687c36bd94fcee09d3ff2f0ea300e3e679db459483edba53c1c3463ea51f48fe2ad2b98c8
|
data/README.md
CHANGED
@@ -23,11 +23,11 @@ The client will generate a key when initialized if one does not already exist.
|
|
23
23
|
|
24
24
|
### Pairing with Bitpay.com
|
25
25
|
|
26
|
-
To pair with bitpay.com you need to have an approved merchant account.
|
27
|
-
1. Login to your account
|
28
|
-
|
29
|
-
|
30
|
-
|
26
|
+
To pair with bitpay.com you need to have an approved merchant account.
|
27
|
+
1. Login to your account
|
28
|
+
2. Navigate to bitpay.com/api-tokens (Dashboard > My Account > API Tokens)
|
29
|
+
3. Copy an existing pairing code or create a new token and copy the pairing code.
|
30
|
+
4. Use the bitpay command line tool to pair with bitpay.com `bitpay pair <pairing_code>`
|
31
31
|
|
32
32
|
### To create an invoice with a paired client:
|
33
33
|
|
data/config/capybara.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
Capybara.javascript_driver = :poltergeist
|
2
2
|
Capybara.default_driver = :poltergeist
|
3
3
|
Capybara.register_driver :poltergeist do |app|
|
4
|
-
Capybara::Poltergeist::Driver.new(app, js_errors: false, phantomjs_options: ['--ignore-ssl-errors=yes'])
|
4
|
+
Capybara::Poltergeist::Driver.new(app, js_errors: false, phantomjs_options: ['--ignore-ssl-errors=yes', '--ssl-protocol=TLSv1'] )
|
5
5
|
end
|
data/lib/bitpay/client.rb
CHANGED
@@ -29,6 +29,7 @@ module BitPay
|
|
29
29
|
@https = Net::HTTP.new @uri.host, @uri.port
|
30
30
|
@https.use_ssl = true
|
31
31
|
@https.ca_file = CA_FILE
|
32
|
+
@tokens = {}
|
32
33
|
|
33
34
|
# Option to disable certificate validation in extraordinary circumstance. NOT recommended for production use
|
34
35
|
@https.verify_mode = opts[:insecure] == true ? OpenSSL::SSL::VERIFY_NONE : OpenSSL::SSL::VERIFY_PEER
|
@@ -36,20 +37,11 @@ module BitPay
|
|
36
37
|
# Option to enable http request debugging
|
37
38
|
@https.set_debug_output($stdout) if opts[:debug] == true
|
38
39
|
|
39
|
-
# Load all the available tokens into @tokens
|
40
|
-
load_tokens
|
41
40
|
end
|
42
41
|
|
43
42
|
def pair_pos_client(claimCode)
|
44
43
|
response = set_pos_token(claimCode)
|
45
|
-
|
46
|
-
when "200"
|
47
|
-
get_token 'pos'
|
48
|
-
when "500"
|
49
|
-
raise BitPayError, JSON.parse(response.body)["error"]
|
50
|
-
else
|
51
|
-
raise BitPayError, "#{response.code}: #{JSON.parse(response.body)}"
|
52
|
-
end
|
44
|
+
get_token 'pos'
|
53
45
|
response
|
54
46
|
end
|
55
47
|
|
@@ -61,13 +53,13 @@ module BitPay
|
|
61
53
|
|
62
54
|
def get_public_invoice(id:)
|
63
55
|
request = Net::HTTP::Get.new("/invoices/#{id}")
|
64
|
-
response =
|
65
|
-
|
56
|
+
response = process_request(request)
|
57
|
+
response["data"]
|
66
58
|
end
|
67
59
|
|
68
60
|
## Generates REST request to api endpoint
|
69
61
|
def send_request(verb, path, facade: 'merchant', params: {}, token: nil)
|
70
|
-
token ||=
|
62
|
+
token ||= get_token(facade)
|
71
63
|
|
72
64
|
# Verb-specific logic
|
73
65
|
case verb.upcase
|
@@ -95,18 +87,35 @@ module BitPay
|
|
95
87
|
end
|
96
88
|
|
97
89
|
# Build request headers and submit
|
98
|
-
request['User-Agent'] = @user_agent
|
99
|
-
request['Content-Type'] = 'application/json'
|
100
|
-
request['X-BitPay-Plugin-Info'] = 'Rubylib' + VERSION
|
101
90
|
request['X-Identity'] = @pub_key
|
102
91
|
|
103
|
-
response =
|
104
|
-
JSON.parse response.body
|
92
|
+
response = process_request(request)
|
105
93
|
end
|
106
94
|
|
107
95
|
##### PRIVATE METHODS #####
|
108
96
|
private
|
109
97
|
|
98
|
+
## Processes HTTP Request and returns parsed response
|
99
|
+
# Otherwise throws error
|
100
|
+
#
|
101
|
+
def process_request(request)
|
102
|
+
|
103
|
+
request['User-Agent'] = @user_agent
|
104
|
+
request['Content-Type'] = 'application/json'
|
105
|
+
request['X-BitPay-Plugin-Info'] = 'Rubylib' + VERSION
|
106
|
+
|
107
|
+
response = @https.request request
|
108
|
+
|
109
|
+
if response.kind_of? Net::HTTPSuccess
|
110
|
+
return JSON.parse(response.body)
|
111
|
+
elsif JSON.parse(response.body)["error"]
|
112
|
+
raise(BitPayError, "#{response.code}: #{JSON.parse(response.body)['error']}")
|
113
|
+
else
|
114
|
+
raise BitPayError, "#{response.code}: #{JSON.parse(response.body)}"
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
110
119
|
## Requests token by appending nonce and signing URL
|
111
120
|
# Returns a hash of available tokens
|
112
121
|
#
|
@@ -115,15 +124,12 @@ module BitPay
|
|
115
124
|
urlpath = '/tokens?nonce=' + KeyUtils.nonce
|
116
125
|
|
117
126
|
request = Net::HTTP::Get.new(urlpath)
|
118
|
-
request['content-type'] = "application/json"
|
119
|
-
request['user-agent'] = @user_agent
|
120
127
|
request['x-identity'] = @pub_key
|
121
128
|
request['x-signature'] = KeyUtils.sign(@uri.to_s + urlpath, @priv_key)
|
122
129
|
|
123
|
-
response =
|
130
|
+
response = process_request(request)
|
124
131
|
|
125
|
-
|
126
|
-
token_array = JSON.parse(response.body)["data"] || {}
|
132
|
+
token_array = response["data"] || {}
|
127
133
|
|
128
134
|
tokens = {}
|
129
135
|
token_array.each do |t|
|
@@ -143,10 +149,7 @@ module BitPay
|
|
143
149
|
params[:guid] = SecureRandom.uuid
|
144
150
|
params[:id] = @client_id
|
145
151
|
request.body = params.to_json
|
146
|
-
request
|
147
|
-
request['Content-Type'] = 'application/json'
|
148
|
-
request['X-BitPay-Plugin-Info'] = 'Rubylib' + VERSION
|
149
|
-
@https.request request
|
152
|
+
process_request(request)
|
150
153
|
end
|
151
154
|
|
152
155
|
def get_token(facade)
|
data/lib/bitpay/key_utils.rb
CHANGED
@@ -85,7 +85,7 @@ module BitPay
|
|
85
85
|
# hence the requirement to use [].pack("H*") to convert to binary for each step
|
86
86
|
|
87
87
|
#Generate Private Key
|
88
|
-
key =
|
88
|
+
key = OpenSSL::PKey::EC.new(pem ||= get_local_pem_file)
|
89
89
|
key.public_key.group.point_conversion_form = :compressed
|
90
90
|
public_key = key.public_key.to_bn.to_s(2)
|
91
91
|
step_one = Digest::SHA256.hexdigest(public_key)
|
data/lib/bitpay/version.rb
CHANGED
data/spec/client_spec.rb
CHANGED
@@ -53,13 +53,13 @@ describe BitPay::Client do
|
|
53
53
|
it 'throws a BitPayError with the error message if the token setting fails' do
|
54
54
|
stub_const('ENV', {'BITPAY_PEM' => PEM})
|
55
55
|
stub_request(:any, /#{BitPay::TEST_API_URI}.*/).to_return(status: 500, body: "{\n \"error\": \"Unable to create token\"\n}")
|
56
|
-
expect { bitpay_client.pair_pos_client(:claim_code) }.to raise_error(BitPay::BitPayError, 'Unable to create token')
|
56
|
+
expect { bitpay_client.pair_pos_client(:claim_code) }.to raise_error(BitPay::BitPayError, '500: Unable to create token')
|
57
57
|
end
|
58
58
|
|
59
59
|
it 'gracefully handles 4xx errors' do
|
60
60
|
stub_const('ENV', {'BITPAY_PEM' => PEM})
|
61
61
|
stub_request(:any, /#{BitPay::TEST_API_URI}.*/).to_return(status: 403, body: "{\n \"error\": \"this is a 403 error\"\n}")
|
62
|
-
expect { bitpay_client.pair_pos_client(:claim_code) }.to raise_error(BitPay::BitPayError, '403:
|
62
|
+
expect { bitpay_client.pair_pos_client(:claim_code) }.to raise_error(BitPay::BitPayError, '403: this is a 403 error')
|
63
63
|
end
|
64
64
|
end
|
65
65
|
|
@@ -73,6 +73,11 @@ describe BitPay::Client do
|
|
73
73
|
bitpay_client.create_invoice(id: "addd", price: 20, currency: "USD")
|
74
74
|
assert_requested :post, "#{BitPay::TEST_API_URI}/invoices"
|
75
75
|
end
|
76
|
+
|
77
|
+
it 'should pass through the API error message from load_tokens' do
|
78
|
+
stub_request(:get, /#{BitPay::TEST_API_URI}\/tokens.*/).to_return(status: 500, body: '{"error": "load_tokens_error"}')
|
79
|
+
expect { bitpay_client.create_invoice(id: "addd", price: 20, currency: "USD") }.to raise_error(BitPay::BitPayError, '500: load_tokens_error')
|
80
|
+
end
|
76
81
|
end
|
77
82
|
end
|
78
83
|
|
data/spec/features/pair_spec.rb
CHANGED
@@ -9,7 +9,9 @@ describe "pairing a token", javascript: true, type: :feature do
|
|
9
9
|
click_button('loginButton')
|
10
10
|
click_link "My Account"
|
11
11
|
click_link "API Tokens", match: :first
|
12
|
-
find(".token-access-new-button").find(".btn").click
|
12
|
+
find(".token-access-new-button").find(".btn").find(".icon-plus").click
|
13
|
+
sleep 0.25
|
14
|
+
click_button("Add Token")
|
13
15
|
find(".token-claimcode", match: :first).text
|
14
16
|
end
|
15
17
|
let(:pem) { BitPay::KeyUtils.generate_pem }
|
data/spec/features/pos_spec.rb
CHANGED
@@ -12,10 +12,11 @@ describe "create an invoice", javascript: true, type: :feature do
|
|
12
12
|
click_link "My Account"
|
13
13
|
click_link "API Tokens", match: :first
|
14
14
|
find(".token-access-new-button").find(".btn").click
|
15
|
+
sleep 0.25
|
16
|
+
click_button("Add Token")
|
15
17
|
find(".token-claimcode", match: :first).text
|
16
18
|
}
|
17
19
|
set_client = -> {
|
18
|
-
private_key = BitPay::KeyUtils.get_private_key_from_pem PEM
|
19
20
|
client = BitPay::Client.new(api_uri: ROOT_ADDRESS, pem: PEM, insecure: true)
|
20
21
|
client.pair_pos_client(get_claim_code.call)
|
21
22
|
client
|
data/spec/key_utils_spec.rb
CHANGED
@@ -20,8 +20,8 @@ describe BitPay::KeyUtils do
|
|
20
20
|
describe '.generate_pem' do
|
21
21
|
it 'should write a new key to ~/.bitpay/bitpay.pem' do
|
22
22
|
file = class_double("File").as_stubbed_const
|
23
|
-
|
24
|
-
allow(
|
23
|
+
fileutils = class_double("FileUtils").as_stubbed_const
|
24
|
+
allow(fileutils).to receive(:mkdir_p).with(BitPay::BITPAY_CREDENTIALS_DIR).and_return(nil)
|
25
25
|
expect(file).to receive(:open).with(BitPay::PRIVATE_KEY_PATH, 'w')
|
26
26
|
key_utils.generate_pem
|
27
27
|
end
|
@@ -31,17 +31,17 @@ describe BitPay::KeyUtils do
|
|
31
31
|
describe '.retrieve_or_generate_pem' do
|
32
32
|
it 'should write a new key to ~/.bitpay/bitpay.pem if there is no existing file' do
|
33
33
|
file = class_double("File").as_stubbed_const
|
34
|
-
|
34
|
+
fileutils = class_double("FileUtils").as_stubbed_const
|
35
35
|
allow(file).to receive(:read).with(BitPay::PRIVATE_KEY_PATH).and_throw(StandardError)
|
36
|
-
allow(
|
36
|
+
allow(fileutils).to receive(:mkdir_p).with(BitPay::BITPAY_CREDENTIALS_DIR).and_return(nil)
|
37
37
|
expect(file).to receive(:open).with(BitPay::PRIVATE_KEY_PATH, 'w')
|
38
38
|
key_utils.retrieve_or_generate_pem
|
39
39
|
end
|
40
40
|
|
41
41
|
it 'should retrieve the pem if there is an existing file' do
|
42
42
|
file = class_double("File").as_stubbed_const
|
43
|
-
|
44
|
-
allow(
|
43
|
+
fileutils = class_double("FileUtils").as_stubbed_const
|
44
|
+
allow(fileutils).to receive(:mkdir_p).with(BitPay::BITPAY_CREDENTIALS_DIR).and_return(nil)
|
45
45
|
expect(file).to receive(:open).with(BitPay::PRIVATE_KEY_PATH, 'w')
|
46
46
|
key_utils.generate_pem
|
47
47
|
end
|
@@ -60,11 +60,17 @@ describe BitPay::KeyUtils do
|
|
60
60
|
|
61
61
|
describe '.generate_sin_from_pem' do
|
62
62
|
let(:pem){PEM}
|
63
|
-
let(:sin){
|
63
|
+
let(:sin){CLIENT_ID}
|
64
64
|
|
65
65
|
it 'will return the right sin for the right pem' do
|
66
66
|
expect(key_utils.generate_sin_from_pem(pem)).to eq sin
|
67
67
|
end
|
68
|
+
|
69
|
+
it 'will retrieve the locally stored PEM if one is not provided' do
|
70
|
+
allow(File).to receive(:read).with(BitPay::PRIVATE_KEY_PATH) {PEM}
|
71
|
+
expect(key_utils.generate_sin_from_pem(nil)).to eq sin
|
72
|
+
end
|
73
|
+
|
68
74
|
end
|
69
75
|
|
70
76
|
context "errors when priv_key is not provided" do
|
data/spec/spec_helper.rb
CHANGED
@@ -15,7 +15,7 @@ require_relative '../config/capybara.rb'
|
|
15
15
|
PEM = "-----BEGIN EC PRIVATE KEY-----\nMHQCAQEEICg7E4NN53YkaWuAwpoqjfAofjzKI7Jq1f532dX+0O6QoAcGBSuBBAAK\noUQDQgAEjZcNa6Kdz6GQwXcUD9iJ+t1tJZCx7hpqBuJV2/IrQBfue8jh8H7Q/4vX\nfAArmNMaGotTpjdnymWlMfszzXJhlw==\n-----END EC PRIVATE KEY-----\n"
|
16
16
|
|
17
17
|
PUB_KEY = '038d970d6ba29dcfa190c177140fd889fadd6d2590b1ee1a6a06e255dbf22b4017'
|
18
|
-
CLIENT_ID = "
|
18
|
+
CLIENT_ID = "TeyN4LPrXiG5t2yuSamKqP3ynVk3F52iHrX"
|
19
19
|
|
20
20
|
|
21
21
|
RSpec.configure do |config|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bitpay-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bitpay, Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-12-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json
|