Class: Wire::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/wire/client.rb

Overview

Client is the Wire API client. Construct it with an API key (sk_live_…).

client = Wire::Client.new("sk_live_...")
pi = client.payment_intents.create(amount: 50_000, currency: "MNT")

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(api_key, base_url: DEFAULT_BASE_URL, timeout: 30, max_retries: 2, backoff: 0.5, http_adapter: nil) ⇒ Client

Returns a new instance of Client.

Parameters:

  • api_key (String)

    secret API key (sk_live_…).

  • base_url (String) (defaults to: DEFAULT_BASE_URL)

    API base URL.

  • timeout (Numeric) (defaults to: 30)

    per-request timeout in seconds.

  • max_retries (Integer) (defaults to: 2)

    retry attempts for 429/5xx/network errors.

  • backoff (Numeric) (defaults to: 0.5)

    base backoff in seconds (exponential w/ jitter).

  • http_adapter (defaults to: nil)

    an optional object responding to #call(method, uri, headers, body, timeout) -> Wire::Response. Used to inject a stub transport in tests; defaults to Net::HTTP.

Raises:

  • (ArgumentError)


32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/wire/client.rb', line 32

def initialize(api_key, base_url: DEFAULT_BASE_URL, timeout: 30,
               max_retries: 2, backoff: 0.5, http_adapter: nil)
  raise ArgumentError, "api_key is required" if api_key.nil? || api_key.empty?

  @api_key = api_key
  @base_url = base_url.sub(%r{/+\z}, "")
  @timeout = timeout
  @max_retries = max_retries
  @backoff = backoff
  @http_adapter = http_adapter || NetHTTPAdapter.new

  @payment_intents = Resources::PaymentIntents.new(self)
  @charges = Resources::Charges.new(self)
  @events = Resources::Events.new(self)
  @webhook_endpoints = Resources::WebhookEndpoints.new(self)
end

Instance Attribute Details

#chargesObject (readonly)

Returns the value of attribute charges.



22
23
24
# File 'lib/wire/client.rb', line 22

def charges
  @charges
end

#eventsObject (readonly)

Returns the value of attribute events.



22
23
24
# File 'lib/wire/client.rb', line 22

def events
  @events
end

#payment_intentsObject (readonly)

Returns the value of attribute payment_intents.



22
23
24
# File 'lib/wire/client.rb', line 22

def payment_intents
  @payment_intents
end

#webhook_endpointsObject (readonly)

Returns the value of attribute webhook_endpoints.



22
23
24
# File 'lib/wire/client.rb', line 22

def webhook_endpoints
  @webhook_endpoints
end

Class Method Details

.new_idempotency_keyObject



98
99
100
# File 'lib/wire/client.rb', line 98

def self.new_idempotency_key
  "idk_#{SecureRandom.hex(16)}"
end

Instance Method Details

#request(method, path, body: nil, query: nil, idempotency_key: nil) ⇒ Object

request performs an HTTP request with auth, idempotency, retries, and error decoding, returning the parsed JSON body as a Hash.

Parameters:

  • method (String)

    HTTP method (“GET”, “POST”, “DELETE”).

  • path (String)

    request path (e.g. “/v1/payment_intents”).

  • body (Hash, nil) (defaults to: nil)

    request body, JSON-encoded when present.

  • query (Hash, nil) (defaults to: nil)

    query parameters.

  • idempotency_key (String, nil) (defaults to: nil)

    reused across retries; a random key is generated for POST when absent.



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/wire/client.rb', line 58

def request(method, path, body: nil, query: nil, idempotency_key: nil)
  uri = build_uri(path, query)

  headers = {
    "Authorization" => "Bearer #{@api_key}",
    "Accept" => "application/json"
  }
  body_str = nil
  unless body.nil?
    body_str = JSON.generate(body)
    headers["Content-Type"] = "application/json"
  end
  if method == "POST"
    headers["Idempotency-Key"] = idempotency_key || self.class.new_idempotency_key
  end

  attempt = 0
  loop do
    begin
      resp = @http_adapter.call(method, uri, headers, body_str, @timeout)
    rescue TimeoutError, ConnectionError => e
      if attempt < @max_retries
        sleep_for(backoff_delay(attempt))
        attempt += 1
        next
      end
      raise e
    end

    if (resp.status == 429 || resp.status >= 500) && attempt < @max_retries
      delay = retry_after(resp.headers) || backoff_delay(attempt)
      sleep_for(delay)
      attempt += 1
      next
    end

    return handle_response(resp)
  end
end