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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e8c99b683ba6a20ac1e7a0739e29a654d1976cae
4
- data.tar.gz: ba0aeebf8fdbec667e0bf76500e194eb549ab25f
3
+ metadata.gz: 1d735bbff357cf079a5f5ea6c357e3375644cde5
4
+ data.tar.gz: 55b7d5cbbe130d8412e74db9798e1a7bad3ac827
5
5
  SHA512:
6
- metadata.gz: 3def8a32c76c98d4c43ece8785641cd8499d48bf5ce93525c67c1a6a48c0238ebc07964ae938e9144a671b28b13d3efc44c10c7cfded72dc5aa4dbf0564e7ba6
7
- data.tar.gz: 11e62b62bbe443fb1d8a7f8ffbcbda5218ec64263dec0605444f2490193a1346bccd756003a8c0cee7827edd3d699bba55e2833c4c634e446dcebe34a3865566
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
- 1. Navigate to bitpay.com/api-tokens (Dashboard > My Account > API Tokens)
29
- 1. Copy an existing pairing code or create a new token and copy the pairing code.
30
- 1. Use the bitpay command line tool to pair with bitpay.com `bitpay pair <pairing_code>`
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
 
@@ -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
@@ -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
- case response.code
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 = @https.request request
65
- (JSON.parse response.body)["data"]
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 ||= @tokens[facade] || raise(BitPayError, "No token for specified facade: #{facade}")
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 = @https.request request
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 = @https.request request
130
+ response = process_request(request)
124
131
 
125
- # /tokens returns an array of hashes. Let's turn it into a more useful single hash
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['User-Agent'] = @user_agent
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)
@@ -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 = pem.nil? ? get_local_pem_file : OpenSSL::PKey::EC.new(pem)
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)
@@ -3,5 +3,5 @@
3
3
  # or https://github.com/bitpay/php-bitpay-client/blob/master/LICENSE
4
4
 
5
5
  module BitPay
6
- VERSION = '2.0.0'
6
+ VERSION = '2.0.1'
7
7
  end
@@ -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: {"error"=>"this is a 403 error"}')
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
 
@@ -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 }
@@ -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
@@ -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
- double = double("Object").as_null_object
24
- allow(file).to receive(:path).with(BitPay::BITPAY_CREDENTIALS_DIR).and_return(double)
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
- double = double("Object").as_null_object
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(file).to receive(:path).with(BitPay::BITPAY_CREDENTIALS_DIR).and_return(double)
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
- double = double("Object").as_null_object
44
- allow(file).to receive(:path).with(BitPay::BITPAY_CREDENTIALS_DIR).and_return(double)
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){"TeyN4LPrXiG5t2yuSamKqP3ynVk3F52iHrX"}
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
@@ -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 = "TfFVQhy2hQvchv4VVG4c7j4XPa2viJ9HrR8"
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.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-10-08 00:00:00.000000000 Z
11
+ date: 2014-12-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json