bitpay-client 2.0.0 → 2.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|