Class: RideBuilder::Affiliate::Client

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

Overview

Server-side client for RideBuilder's FirstParty affiliate program: report checkout/return postbacks and prove integration liveness. Handles auth, per-attempt timeout, retry with exponential backoff + jitter, and idempotency. Port of the Node RideBuilderClient — same wire contract, verified by sdk/conformance.

Instance Method Summary collapse

Constructor Details

#initialize(api_key:, base_url: nil, max_retries: 3, timeout_ms: 10_000, environment: "production", transport: nil) ⇒ Client

Returns a new instance of Client.

Raises:



9
10
11
12
13
14
15
16
17
# File 'lib/ridebuilder/affiliate/client.rb', line 9

def initialize(api_key:, base_url: nil, max_retries: 3, timeout_ms: 10_000, environment: "production", transport: nil)
  raise Error.new("api_key must be a non-empty string", retryable: false) if api_key.nil? || api_key.strip.empty?

  @api_key = api_key
  @base_url = (base_url || DEFAULT_BASE_URL).sub(%r{/+\z}, "")
  @max_retries = max_retries
  @environment = environment == "sandbox" ? "sandbox" : "production"
  @transport = transport || NetHttpTransport.new(timeout_ms)
end

Instance Method Details

#health_checkObject

Authenticated liveness ping (legacy alias). Raises a terminal Error on a bad key.



49
50
51
# File 'lib/ridebuilder/affiliate/client.rb', line 49

def health_check
  HealthResult.new(true, send_request("POST", "/postback/health").status)
end

#heartbeatObject

Periodic liveness. Call on a schedule so RideBuilder can tell "alive" from "went dark".



69
70
71
72
73
74
# File 'lib/ridebuilder/affiliate/client.rb', line 69

def heartbeat
  res = send_request("POST", "/integration/heartbeat", {
    "type" => SDK_TYPE, "environment" => @environment, "version" => VERSION
  })
  HealthResult.new(true, res.status)
end

#register(capabilities: nil) ⇒ Object

Announce this integration on install/startup — the handshake. Idempotent; returns the integration id.



54
55
56
57
58
59
60
61
# File 'lib/ridebuilder/affiliate/client.rb', line 54

def register(capabilities: nil)
  res = send_request("POST", "/integration/register", {
    "type" => SDK_TYPE, "environment" => @environment, "version" => VERSION,
    "capabilities" => capabilities || DEFAULT_CAPABILITIES
  })
  body = res.json.is_a?(Hash) ? res.json : {}
  RegisterResult.new(body["integrationId"] || "", body["status"] || "connected")
end

#report_checkout(order_id:, subtotal:, currency:, click_id:) ⇒ Object

order_id is the server-side idempotency key, so a retried checkout never double-counts.



20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/ridebuilder/affiliate/client.rb', line 20

def report_checkout(order_id:, subtotal:, currency:, click_id:)
  assert_non_empty(order_id, "order_id")
  amount = normalize_amount(subtotal, "subtotal")
  assert_currency(currency)
  unless ClickId.valid?(click_id)
    raise Error.new("click_id must be a valid RideBuilder click_id (UUID v4)", retryable: false)
  end

  res = send_request("POST", "/postback/checkout", {
    "order_id" => order_id, "order_subtotal" => amount, "currency" => currency,
    "ref" => ClickId::REF, "click_id" => click_id
  })
  PostbackResult.new(true, res.status)
end

#report_return(return_id:, order_id:, refund_amount:, currency:) ⇒ Object

return_id is the server-side idempotency key, so a retried refund never double-counts.



36
37
38
39
40
41
42
43
44
45
46
# File 'lib/ridebuilder/affiliate/client.rb', line 36

def report_return(return_id:, order_id:, refund_amount:, currency:)
  assert_non_empty(return_id, "return_id")
  assert_non_empty(order_id, "order_id")
  amount = normalize_amount(refund_amount, "refund_amount")
  assert_currency(currency)

  res = send_request("POST", "/postback/return", {
    "return_id" => return_id, "order_id" => order_id, "refund_amount" => amount, "currency" => currency
  })
  PostbackResult.new(true, res.status)
end

#verifyObject

Self-test: verifies the API key is valid + active. Raises a terminal Error on a bad/rotated key.



64
65
66
# File 'lib/ridebuilder/affiliate/client.rb', line 64

def verify
  HealthResult.new(true, send_request("GET", "/integration/verify").status)
end