Class: AddressValidation::Providers::ShipEngine

Inherits:
Object
  • Object
show all
Defined in:
app/services/address_validation/providers/ship_engine.rb

Overview

ShipEngine-backed provider — USPS for US addresses, Canada Post /
Purolator for Canadian ones — reached through the existing
WyShipping.valid_address? integration. Its +suggested_address_hashes+
(keys +:address+/+:city+/+:state+/+:zip+/...) are mapped to
Candidate.

Instance Method Summary collapse

Instance Method Details

#lookup_zip(zip, country_iso3:) ⇒ AddressValidation::Candidate?

Best-effort city/state for a bare postal code. ShipEngine validates full
addresses, so we probe with a synthetic single-line address; returns nil
when it can't resolve. The PostalCode bulk refresh (GeoNames) is the
primary freshness source — this only self-heals misses/stale rows.

Parameters:

  • zip (String)

    postal code to resolve

  • country_iso3 (String)

    ISO 3166-1 alpha-3 country code

Returns:



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'app/services/address_validation/providers/ship_engine.rb', line 35

def lookup_zip(zip, country_iso3:)
  return nil if zip.blank?

  probe = Address.new(street1: 'MAIN ST', city: '', state_code: '', zip: zip,
                      country_iso3: country_iso3, is_residential: true,
                      skip_carrier_validation: true)
  result = verify(probe)
  return result.best if result.verified?
  # Trust an ambiguous result only when every candidate agrees on the
  # state; otherwise we'd cache an arbitrary (possibly wrong) ZIP→state.
  return result.best if result.ambiguous? && result.candidates.filter_map(&:state_code).uniq.one?

  nil
rescue StandardError
  nil
end

#verify(address) ⇒ AddressValidation::Result

Parameters:

  • address (Address)

    (or any object with the Address field API)

Returns:



16
17
18
19
20
21
22
23
24
25
# File 'app/services/address_validation/providers/ship_engine.rb', line 16

def verify(address)
  require 'wy_shipping'
  raw = WyShipping.valid_address?(address)
  candidates = Array(raw[:suggested_address_hashes]).filter_map { |h| to_candidate(h) }
  Result.new(status: status_for(raw, candidates), candidates: candidates,
             provider: :ship_engine, message: raw[:status_message])
rescue StandardError => e
  ErrorReporting.warning(e, context: 'AddressValidation::Providers::ShipEngine#verify')
  Result.new(status: :error, provider: :ship_engine, message: e.message)
end