Class: OpenReceive::Configuration

Inherits:
Object
  • Object
show all
Defined in:
lib/openreceive/configuration.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeConfiguration

Returns a new instance of Configuration.



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
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
# File 'lib/openreceive/configuration.rb', line 41

def initialize
  @parent_controller = "ActionController::Base"
  @nwc = nil
  @nwc_client = nil
  @authorize = nil
  @amount_for = nil
  @on_paid = nil
  @resolve_checkout = nil
  @on_checkout_created = nil
  @rate_limit = nil
  # Built-in per-IP invoice rate limiting (mirrors the JS `rateLimiting`
  # option): OFF by default — shared-IP deployments (POS terminals,
  # kiosks) must never be throttled by accident. `true` caps invoice
  # creation at 60 per client IP per rolling hour, counted from the
  # engine-owned openreceive_payments rows; or a Hash with
  # limit_per_hour / limit_per_day. Mutually exclusive with rate_limit.
  @rate_limiting = false
  # Client IP attribution: a proc receiving the framework request.
  # Defaults to ActionDispatch::Request#ip (which honors the app's
  # trusted-proxy configuration).
  @client_ip = nil
  # nil (the default) mirrors the JS createOpenReceive defaults: the
  # price provider becomes the built-in cached live price feed (with
  # OPENRECEIVE_PRICE_FEED_*_URL overrides), and swap providers are
  # auto-built from LSC_URI_PRIMARY / LSC_URI_BACKUP. Set an explicit
  # value (e.g. swap_providers = []) to override.
  @price_provider = nil
  @swap_providers = nil
  @price_currencies = ["USD"]
  @allow_spend_capable_wallet = false
  # Opportunistic settlement discovery, ON by default (mirrors the JS
  # handler's opportunisticReconcile): every engine request first runs one
  # durably gated reconcile pass when attempts are pending, so abandoned
  # checkouts settle on any later OpenReceive call with no scheduled job.
  # The openreceive_meta gate row is shared by every Puma worker/process on
  # the host database (min 2s between real wallet scans, stretched by
  # invoice age). Set false to disable (e.g. when the optional
  # `bin/rails openreceive:notifications` worker owns scanning), or a Hash
  # with min_interval_seconds to tune.
  @opportunistic_reconcile = true
  # The production boot preflight (Engine's after_initialize): build the
  # service, and with it the wallet check, so a missing NWC_URI or a
  # spend-capable wallet stops a deploy instead of the first customer. ON by
  # default. Asset builds are detected and skipped automatically (see
  # OpenReceive.eager_preflight?); set false for any other boot that must
  # come up without wallet secrets.
  @eager_preflight = true
end

Instance Attribute Details

#allow_spend_capable_walletObject

Quickstart contract: authorize + amount_for + on_paid. The engine derives checkout resolution, attempt commit, and settlement write-once from the engine-owned OpenReceivePayment model.

Advanced escape hatch: hosts with a custom payment repository configure resolve_checkout and on_checkout_created together; on_paid then receives the raw settlement event and owns replay safety itself.



34
35
36
# File 'lib/openreceive/configuration.rb', line 34

def allow_spend_capable_wallet
  @allow_spend_capable_wallet
end

#amount_forObject

Quickstart contract: authorize + amount_for + on_paid. The engine derives checkout resolution, attempt commit, and settlement write-once from the engine-owned OpenReceivePayment model.

Advanced escape hatch: hosts with a custom payment repository configure resolve_checkout and on_checkout_created together; on_paid then receives the raw settlement event and owns replay safety itself.



34
35
36
# File 'lib/openreceive/configuration.rb', line 34

def amount_for
  @amount_for
end

#authorizeObject

Quickstart contract: authorize + amount_for + on_paid. The engine derives checkout resolution, attempt commit, and settlement write-once from the engine-owned OpenReceivePayment model.

Advanced escape hatch: hosts with a custom payment repository configure resolve_checkout and on_checkout_created together; on_paid then receives the raw settlement event and owns replay safety itself.



34
35
36
# File 'lib/openreceive/configuration.rb', line 34

def authorize
  @authorize
end

#client_ipObject

Quickstart contract: authorize + amount_for + on_paid. The engine derives checkout resolution, attempt commit, and settlement write-once from the engine-owned OpenReceivePayment model.

Advanced escape hatch: hosts with a custom payment repository configure resolve_checkout and on_checkout_created together; on_paid then receives the raw settlement event and owns replay safety itself.



34
35
36
# File 'lib/openreceive/configuration.rb', line 34

def client_ip
  @client_ip
end

#eager_preflightObject

Quickstart contract: authorize + amount_for + on_paid. The engine derives checkout resolution, attempt commit, and settlement write-once from the engine-owned OpenReceivePayment model.

Advanced escape hatch: hosts with a custom payment repository configure resolve_checkout and on_checkout_created together; on_paid then receives the raw settlement event and owns replay safety itself.



34
35
36
# File 'lib/openreceive/configuration.rb', line 34

def eager_preflight
  @eager_preflight
end

#nwcObject

Quickstart contract: authorize + amount_for + on_paid. The engine derives checkout resolution, attempt commit, and settlement write-once from the engine-owned OpenReceivePayment model.

Advanced escape hatch: hosts with a custom payment repository configure resolve_checkout and on_checkout_created together; on_paid then receives the raw settlement event and owns replay safety itself.



34
35
36
# File 'lib/openreceive/configuration.rb', line 34

def nwc
  @nwc
end

#nwc_clientObject

Quickstart contract: authorize + amount_for + on_paid. The engine derives checkout resolution, attempt commit, and settlement write-once from the engine-owned OpenReceivePayment model.

Advanced escape hatch: hosts with a custom payment repository configure resolve_checkout and on_checkout_created together; on_paid then receives the raw settlement event and owns replay safety itself.



34
35
36
# File 'lib/openreceive/configuration.rb', line 34

def nwc_client
  @nwc_client
end

#on_checkout_createdObject

Quickstart contract: authorize + amount_for + on_paid. The engine derives checkout resolution, attempt commit, and settlement write-once from the engine-owned OpenReceivePayment model.

Advanced escape hatch: hosts with a custom payment repository configure resolve_checkout and on_checkout_created together; on_paid then receives the raw settlement event and owns replay safety itself.



34
35
36
# File 'lib/openreceive/configuration.rb', line 34

def on_checkout_created
  @on_checkout_created
end

#on_paidObject

Quickstart contract: authorize + amount_for + on_paid. The engine derives checkout resolution, attempt commit, and settlement write-once from the engine-owned OpenReceivePayment model.

Advanced escape hatch: hosts with a custom payment repository configure resolve_checkout and on_checkout_created together; on_paid then receives the raw settlement event and owns replay safety itself.



34
35
36
# File 'lib/openreceive/configuration.rb', line 34

def on_paid
  @on_paid
end

#opportunistic_reconcileObject

Quickstart contract: authorize + amount_for + on_paid. The engine derives checkout resolution, attempt commit, and settlement write-once from the engine-owned OpenReceivePayment model.

Advanced escape hatch: hosts with a custom payment repository configure resolve_checkout and on_checkout_created together; on_paid then receives the raw settlement event and owns replay safety itself.



34
35
36
# File 'lib/openreceive/configuration.rb', line 34

def opportunistic_reconcile
  @opportunistic_reconcile
end

#parent_controllerObject

Quickstart contract: authorize + amount_for + on_paid. The engine derives checkout resolution, attempt commit, and settlement write-once from the engine-owned OpenReceivePayment model.

Advanced escape hatch: hosts with a custom payment repository configure resolve_checkout and on_checkout_created together; on_paid then receives the raw settlement event and owns replay safety itself.



34
35
36
# File 'lib/openreceive/configuration.rb', line 34

def parent_controller
  @parent_controller
end

#price_currenciesObject

Quickstart contract: authorize + amount_for + on_paid. The engine derives checkout resolution, attempt commit, and settlement write-once from the engine-owned OpenReceivePayment model.

Advanced escape hatch: hosts with a custom payment repository configure resolve_checkout and on_checkout_created together; on_paid then receives the raw settlement event and owns replay safety itself.



34
35
36
# File 'lib/openreceive/configuration.rb', line 34

def price_currencies
  @price_currencies
end

#price_providerObject

Quickstart contract: authorize + amount_for + on_paid. The engine derives checkout resolution, attempt commit, and settlement write-once from the engine-owned OpenReceivePayment model.

Advanced escape hatch: hosts with a custom payment repository configure resolve_checkout and on_checkout_created together; on_paid then receives the raw settlement event and owns replay safety itself.



34
35
36
# File 'lib/openreceive/configuration.rb', line 34

def price_provider
  @price_provider
end

#rate_limitObject

Quickstart contract: authorize + amount_for + on_paid. The engine derives checkout resolution, attempt commit, and settlement write-once from the engine-owned OpenReceivePayment model.

Advanced escape hatch: hosts with a custom payment repository configure resolve_checkout and on_checkout_created together; on_paid then receives the raw settlement event and owns replay safety itself.



34
35
36
# File 'lib/openreceive/configuration.rb', line 34

def rate_limit
  @rate_limit
end

#rate_limitingObject

Quickstart contract: authorize + amount_for + on_paid. The engine derives checkout resolution, attempt commit, and settlement write-once from the engine-owned OpenReceivePayment model.

Advanced escape hatch: hosts with a custom payment repository configure resolve_checkout and on_checkout_created together; on_paid then receives the raw settlement event and owns replay safety itself.



34
35
36
# File 'lib/openreceive/configuration.rb', line 34

def rate_limiting
  @rate_limiting
end

#resolve_checkoutObject

Quickstart contract: authorize + amount_for + on_paid. The engine derives checkout resolution, attempt commit, and settlement write-once from the engine-owned OpenReceivePayment model.

Advanced escape hatch: hosts with a custom payment repository configure resolve_checkout and on_checkout_created together; on_paid then receives the raw settlement event and owns replay safety itself.



34
35
36
# File 'lib/openreceive/configuration.rb', line 34

def resolve_checkout
  @resolve_checkout
end

#swap_providersObject

Quickstart contract: authorize + amount_for + on_paid. The engine derives checkout resolution, attempt commit, and settlement write-once from the engine-owned OpenReceivePayment model.

Advanced escape hatch: hosts with a custom payment repository configure resolve_checkout and on_checkout_created together; on_paid then receives the raw settlement event and owns replay safety itself.



34
35
36
# File 'lib/openreceive/configuration.rb', line 34

def swap_providers
  @swap_providers
end

Instance Method Details

#advanced_hooks?Boolean

Returns:

  • (Boolean)


130
131
132
# File 'lib/openreceive/configuration.rb', line 130

def advanced_hooks?
  !@resolve_checkout.nil? && !@on_checkout_created.nil?
end

#request_handlerObject



106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/openreceive/configuration.rb', line 106

def request_handler
  validate!
  @request_handler ||= OpenReceive::Server::RequestHandler.new(
    service: service,
    authorize: @authorize,
    resolve_checkout: @resolve_checkout || engine_resolve_checkout,
    on_checkout_created: @on_checkout_created || engine_on_checkout_created,
    on_paid: settlement_hook,
    rate_limit: resolved_rate_limit,
    client_ip: resolved_client_ip
  )
end

#reset_runtime!Object



134
135
136
137
138
139
# File 'lib/openreceive/configuration.rb', line 134

def reset_runtime!
  %i[@service @request_handler @settlement_hook @resolved_nwc_client].each do |name|
    remove_instance_variable(name) if instance_variable_defined?(name)
  end
  self
end

#serviceObject



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/openreceive/configuration.rb', line 90

def service
  validate!
  # The Rails logger, so the service's operator diagnostics actually land:
  # the detailed invoice-expiry rejection ("requested Xs, got Ys…") and the
  # spend-capable override warning are logged, never sent, so without this
  # a Rails operator saw only the short 502 wire message.
  @service ||= OpenReceive::Server::Service.new(
    nwc_client: resolved_nwc_client,
    price_provider: @price_provider,
    swap_providers: @swap_providers,
    price_currencies: @price_currencies,
    allow_spend_capable_wallet: @allow_spend_capable_wallet,
    logger: rails_logger
  )
end

#settlement_hookObject

The settlement-event hook shared by payments/check and OpenReceive.reconcile!. In quickstart mode it delivers through OpenReceivePayment.mark_paid_once!, so config.on_paid fires only for the order's FIRST settled attempt, inside the settlement transaction; a later duplicate settlement is recorded (status_reason "duplicate_settlement") but never fulfilled again.



124
125
126
127
128
# File 'lib/openreceive/configuration.rb', line 124

def settlement_hook
  return @on_paid if advanced_hooks?

  @settlement_hook ||= engine_settlement_hook
end

#validate!Object

Raises:



141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/openreceive/configuration.rb', line 141

def validate!
  raise ConfigurationError, "OpenReceive.config.authorize is required." if @authorize.nil?
  if @rate_limiting && @rate_limit
    raise ConfigurationError,
          "Set either OpenReceive.config.rate_limiting or a custom rate_limit hook, not both."
  end
  if @rate_limiting && advanced_hooks?
    raise ConfigurationError,
          "config.rate_limiting counts engine-owned OpenReceivePayment rows; with a custom " \
          "repository (resolve_checkout/on_checkout_created), pass a custom rate_limit hook " \
          "backed by your own store instead."
  end
  if @opportunistic_reconcile && advanced_hooks?
    # Same fail-at-construction idiom as the JS handler: the default
    # settlement path needs the engine-owned durable gate and payment rows;
    # a custom repository must opt out explicitly, never degrade silently.
    raise ConfigurationError,
          "config.opportunistic_reconcile (on by default) scans engine-owned " \
          "OpenReceivePayment rows through the shared openreceive_meta gate; with a custom " \
          "repository (resolve_checkout/on_checkout_created), set " \
          "config.opportunistic_reconcile = false and run your own settlement worker."
  end
  if @on_paid.nil?
    raise ConfigurationError, "OpenReceive.config.on_paid is required to durably record settlement."
  end
  if @resolve_checkout.nil? != @on_checkout_created.nil?
    raise ConfigurationError,
          "OpenReceive.config.resolve_checkout and on_checkout_created must be configured together (advanced mode)."
  end
  if !advanced_hooks? && @amount_for.nil?
    raise ConfigurationError,
          "Set OpenReceive.config.amount_for (quickstart), " \
          "or resolve_checkout and on_checkout_created (advanced)."
  end
  resolved_nwc_client
  true
end