class BitPay::SDK::Client

Public Class Methods

new(opts={}) click to toggle source

@return [Client] @example

# Create a client with a pem file created by the bitpay client:
client = BitPay::SDK::Client.new
# File lib/bitpay/client.rb, line 22
def initialize(opts={})
  @pem                = opts[:pem] || ENV['BITPAY_PEM'] || KeyUtils.generate_pem 
  @key                = KeyUtils.create_key @pem
  @priv_key           = KeyUtils.get_private_key @key
  @pub_key            = KeyUtils.get_public_key @key
  @client_id          = KeyUtils.generate_sin_from_pem @pem
  @uri                = URI.parse opts[:api_uri] || API_URI
  @user_agent         = opts[:user_agent] || USER_AGENT
  @https              = Net::HTTP.new @uri.host, @uri.port
  @https.use_ssl      = true
  @https.open_timeout = 10
  @https.read_timeout = 10

  @https.ca_file      = CA_FILE
  @tokens             = opts[:tokens] || {}

  # Option to disable certificate validation in extraordinary circumstance.  NOT recommended for production use
  @https.verify_mode = opts[:insecure] == true ? OpenSSL::SSL::VERIFY_NONE : OpenSSL::SSL::VERIFY_PEER
  
  # Option to enable http request debugging
  @https.set_debug_output($stdout) if opts[:debug] == true
end

Public Instance Methods

cancel_refund(invoice_id:, request_id:) click to toggle source

Cancel Refund

Requires merchant facade token

@example:

client.cancel_refund(id: 'JB49z2MsDH7FunczeyDS8j', request_id: '4evCrXq4EDXk4oqDXdWQhX')
# File lib/bitpay/client.rb, line 147
def cancel_refund(invoice_id:, request_id:)
  urlpath = "invoices/#{invoice_id}/refunds/#{request_id}"
  refund = get_refund(invoice_id: invoice_id, request_id: request_id)
  deletion = delete(path: urlpath, token: refund["token"])
  deletion["data"]
end
create_invoice(price:, currency:, facade: 'pos', params:{}) click to toggle source

Create bitcoin invoice

Defaults to pos facade, also works with merchant facade
# File lib/bitpay/client.rb, line 65
def create_invoice(price:, currency:, facade: 'pos', params:{})
  raise BitPay::ArgumentError, "Illegal Argument: Price must be formatted as a float" unless 
    price.is_a?(Numeric) ||
    /^[[:digit:]]+(\.[[:digit:]]{2})?$/.match(price) ||
    currency == 'BTC' && /^[[:digit:]]+(\.[[:digit:]]{1,6})?$/.match(price)
  raise BitPay::ArgumentError, "Illegal Argument: Currency is invalid." unless /^[[:upper:]]{3}$/.match(currency)
  params.merge!({price: price, currency: currency})
  token = get_token(facade)
  invoice = post(path: "invoices", token: token, params: params)
  invoice["data"]
end
get_all_refunds_for_invoice(id:) click to toggle source

Get All Refunds for Invoice

Returns an array of all refund requests for a specific invoice, 

Requires merchant facade token

@example:

client.get_all_refunds_for_invoice(id: 'JB49z2MsDH7FunczeyDS8j')
# File lib/bitpay/client.rb, line 121
def get_all_refunds_for_invoice(id:)
  urlpath = "invoices/#{id}/refunds"
  invoice = get_invoice(id: id)
  refunds = get(path: urlpath, token: invoice["token"])
  refunds["data"]
end
get_invoice(id:) click to toggle source

Gets the privileged merchant-version of the invoice

Requires merchant facade token
# File lib/bitpay/client.rb, line 80
def get_invoice(id:)
  token = get_token('merchant')
  invoice = get(path: "invoices/#{id}", token: token)
  invoice["data"]
end
get_public_invoice(id:) click to toggle source

Gets the public version of the invoice

# File lib/bitpay/client.rb, line 88
def get_public_invoice(id:)
  invoice = get(path: "invoices/#{id}", public: true)
  invoice["data"]
end
get_refund(invoice_id:, request_id:) click to toggle source

Get Refund

Requires merchant facade token

@example:

client.get_refund(id: 'JB49z2MsDH7FunczeyDS8j', request_id: '4evCrXq4EDXk4oqDXdWQhX')
# File lib/bitpay/client.rb, line 134
def get_refund(invoice_id:, request_id:)
  urlpath = "invoices/#{invoice_id}/refunds/#{request_id}"
  invoice = get_invoice(id: invoice_id)
  refund = get(path: urlpath, token: invoice["token"])
  refund["data"]
end
pair_client(params={}) click to toggle source
Pair client with BitPay service

> Pass empty hash {} to retreive client-initiated pairing code

> Pass {pairingCode: 'WfD01d2'} to claim a server-initiated pairing code

# File lib/bitpay/client.rb, line 49
def pair_client(params={})
  tokens = post(path: 'tokens', params: params)
  return tokens["data"]
end
pair_pos_client(claimCode) click to toggle source

Compatibility method for pos pairing

# File lib/bitpay/client.rb, line 56
def pair_pos_client(claimCode)
  raise BitPay::ArgumentError, "pairing code is not legal" unless verify_claim_code(claimCode)
  pair_client({pairingCode: claimCode})
end
refund_invoice(id:, params:{}) click to toggle source

Refund paid BitPay invoice

If invoice["data"]["flags"]["refundable"] == true the a refund address was 
provided with the payment and the refund_address parameter is an optional override

Amount and Currency are required fields for fully paid invoices but optional
for under or overpaid invoices which will otherwise be completely refunded

Requires merchant facade token

@example

client.refund_invoice(id: 'JB49z2MsDH7FunczeyDS8j', params: {amount: 10, currency: 'USD', bitcoinAddress: '1Jtcygf8W3cEmtGgepggtjCxtmFFjrZwRV'})
# File lib/bitpay/client.rb, line 107
def refund_invoice(id:, params:{})
  invoice = get_invoice(id: id)
  refund = post(path: "invoices/#{id}/refunds", token: invoice["token"], params: params)
  refund["data"]
end
verify_tokens(tokens: @tokens) click to toggle source

Checks that the passed tokens are valid by comparing them to those that are authorized by the server

Uses local @tokens variable if no tokens are passed in order to validate the connector is properly paired

# File lib/bitpay/client.rb, line 160
def verify_tokens(tokens: @tokens)
  server_tokens = refresh_tokens
  tokens.each{|key, value| return false if server_tokens[key] != value}
  return true
end

Private Instance Methods

verify_claim_code(claim_code) click to toggle source
# File lib/bitpay/client.rb, line 168
def verify_claim_code(claim_code)
  regex = /^[[:alnum:]]{7}$/
    matches = regex.match(claim_code)
  !(matches.nil?)
end