Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ Do yourself a favor: go grab some ice cubes by installing this refreshing librar
- [Transfers](#transfers)
- [Transfer Batches](#transfer-batches)
- [Recipients](#recipients)
- [Crossborder](#crossborder)
- [Simulate](#simulate)
- [Account Verifications](#account-verifications)
- [Entity onboardings API Examples](#entity-onboardings-api-examples)
Expand Down Expand Up @@ -273,6 +274,9 @@ eligibility = client.v2.payment_intents.check_eligibility(
)
checkout_session = client.v2.checkout_sessions.create(currency: 'CLP', flow: 'payment', amount: 5000)
client.v2.checkout_sessions.expire('checkout_session_id')
# Charge the card submitted to a `ui_mode: 'fields'` session. Call it again while
# the session is still `in_progress` (202 Accepted) to get the result.
checkout_session = client.v2.checkout_sessions.confirm('checkout_session_id')
setup_intent = client.v2.setup_intents.get('setup_intent_id')

# Products, subscriptions and invoices
Expand Down Expand Up @@ -571,6 +575,38 @@ recipient = client.v2.recipients.update('recipient_id', alias: 'Lord Snow')
client.v2.recipients.delete('recipient_id')
```

#### Crossborder

Crossborder beneficiaries, quotes and transfers are under the `v2.crossborder` namespace.
Create a quote to lock the exchange rate, and accept it with a transfer to a beneficiary:

```ruby
require 'fintoc'

client = Fintoc::Client.new('api_key')

beneficiary = client.v2.crossborder.beneficiaries.create(
holder_type: 'business',
business_name: 'Acme LLC',
account_identifier: '123456789',
routing_number: '021000021',
bank_name: 'JPMorgan Chase Bank, N.A.',
address: { street_line1: '100 Main St', city: 'New York', state: 'NY', postal_code: '10001' }
)
beneficiaries = client.v2.crossborder.beneficiaries.list(limit: 10)
client.v2.crossborder.beneficiaries.delete(beneficiary.id) # archives the beneficiary

quote = client.v2.crossborder.quotes.create(direction: 'mx_to_usd', source_amount: 200001)
quote = client.v2.crossborder.quotes.get(quote.id)

transfer = client.v2.crossborder.transfers.create(
quote_id: quote.id, beneficiary_id: beneficiary.id, reference: 'Factura 123'
)
transfer.funding_instructions[:clabe]
transfers = client.v2.crossborder.transfers.list(status: %w[pending_funds failed], direction: 'mx_to_usd')
transfer = client.v2.crossborder.transfers.get('crossborder_transfer_id')
```

#### Simulate

```ruby
Expand Down
15 changes: 15 additions & 0 deletions lib/fintoc/errors.rb
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ class InvalidRefundToGetVoucherError < FintocError; end
class InvalidRutError < FintocError; end
class InvalidShareholderStructureError < FintocError; end
class InvalidWebhookEventTypeError < FintocError; end
class QuoteExpiredError < FintocError; end
class SettlementNotConfiguredError < FintocError; end
class MinimumAmountError < FintocError; end
class MutuallyExclusiveParamsError < FintocError; end
class NotSupportedRefundableResourceTypeError < FintocError; end
Expand Down Expand Up @@ -115,6 +117,7 @@ class InvalidJwsTsError < FintocError; end

# 402 Payment Required Errors
class PaymentRequiredError < FintocError; end
class CardDeclinedError < FintocError; end

# 403 Forbidden Errors
class InvalidAccountError < FintocError; end
Expand Down Expand Up @@ -176,9 +179,17 @@ class PaymentMethodNonCancelableError < FintocError; end
class PaymentNonCancelableError < FintocError; end
class PaymentNonExpirableError < FintocError; end
class SubscriptionNotEditableError < FintocError; end
class BeneficiaryAlreadyExistsError < FintocError; end
class CardConfirmationExpiredError < FintocError; end
class ChargeInProgressError < FintocError; end
class CheckoutSessionNotInProgressError < FintocError; end
class NoCardSubmittedError < FintocError; end
class QuoteAlreadyAcceptedError < FintocError; end

# 422 Unprocessable Entity Errors
class AccountBlockedForDirectDebitError < FintocError; end
class AccountCertificateUnavailableError < FintocError; end
class ProviderRejectedError < FintocError; end
class FounderEmailChangeLimitReachedError < FintocError; end
class InvalidHolderNameError < FintocError; end
class InvalidOtpCodeError < FintocError; end
Expand Down Expand Up @@ -245,6 +256,10 @@ class CoreResponseError < FintocError; end
# 501 Not Implemented Errors
class OperationNotImplementedError < FintocError; end

# 503 Service Unavailable Errors
class ProviderOutcomeUnknownError < FintocError; end
class ProviderUnavailableError < FintocError; end

# Webhook Errors
class WebhookSignatureError < FintocError; end

Expand Down
5 changes: 5 additions & 0 deletions lib/fintoc/v2/client/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
require 'fintoc/v2/managers/events_manager'
require 'fintoc/v2/managers/invoices_manager'
require 'fintoc/v2/managers/subscriptions_manager'
require 'fintoc/v2/managers/crossborder_manager'

module Fintoc
module V2
Expand Down Expand Up @@ -87,6 +88,10 @@ def invoices
def subscriptions
@subscriptions ||= Managers::SubscriptionsManager.new(self)
end

def crossborder
@crossborder ||= Managers::CrossborderManager.new(self)
end
end
end
end
6 changes: 6 additions & 0 deletions lib/fintoc/v2/managers/checkout_sessions_manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ def expire(checkout_session_id, idempotency_key: nil)
build_checkout_session(data)
end

def confirm(checkout_session_id, idempotency_key: nil)
data = @client.post(version: :v2, idempotency_key:)
.call("checkout_sessions/#{checkout_session_id}/confirm")
build_checkout_session(data)
end

private

def build_checkout_session(data)
Expand Down
46 changes: 46 additions & 0 deletions lib/fintoc/v2/managers/crossborder_beneficiaries_manager.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
require 'fintoc/v2/resources/crossborder_beneficiary'

module Fintoc
module V2
module Managers
class CrossborderBeneficiariesManager
def initialize(client)
@client = client
end

def create(
holder_type:, account_identifier:, routing_number:, bank_name:, address:,
idempotency_key: nil, **params
)
data = @client.post(version: :v2, idempotency_key:).call(
'crossborder/beneficiaries',
holder_type:, account_identifier:, routing_number:, bank_name:, address:, **params
)
build_beneficiary(data)
end

def list(**params)
@client.get(version: :v2).call('crossborder/beneficiaries', **params).map do |data|
build_beneficiary(data)
end
end

def get(beneficiary_id)
data = @client.get(version: :v2).call("crossborder/beneficiaries/#{beneficiary_id}")
build_beneficiary(data)
end

def delete(beneficiary_id)
data = @client.delete(version: :v2).call("crossborder/beneficiaries/#{beneficiary_id}")
build_beneficiary(data)
end

private

def build_beneficiary(data)
Fintoc::V2::CrossborderBeneficiary.new(**data)
end
end
end
end
end
27 changes: 27 additions & 0 deletions lib/fintoc/v2/managers/crossborder_manager.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
require 'fintoc/v2/managers/crossborder_beneficiaries_manager'
require 'fintoc/v2/managers/crossborder_quotes_manager'
require 'fintoc/v2/managers/crossborder_transfers_manager'

module Fintoc
module V2
module Managers
class CrossborderManager
def initialize(client)
@client = client
end

def beneficiaries
@beneficiaries ||= CrossborderBeneficiariesManager.new(@client)
end

def quotes
@quotes ||= CrossborderQuotesManager.new(@client)
end

def transfers
@transfers ||= CrossborderTransfersManager.new(@client)
end
end
end
end
end
30 changes: 30 additions & 0 deletions lib/fintoc/v2/managers/crossborder_quotes_manager.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
require 'fintoc/v2/resources/crossborder_quote'

module Fintoc
module V2
module Managers
class CrossborderQuotesManager
def initialize(client)
@client = client
end

def create(direction:, source_amount:, idempotency_key: nil)
data = @client.post(version: :v2, idempotency_key:)
.call('crossborder/quotes', direction:, source_amount:)
build_quote(data)
end

def get(quote_id)
data = @client.get(version: :v2).call("crossborder/quotes/#{quote_id}")
build_quote(data)
end

private

def build_quote(data)
Fintoc::V2::CrossborderQuote.new(**data)
end
end
end
end
end
38 changes: 38 additions & 0 deletions lib/fintoc/v2/managers/crossborder_transfers_manager.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
require 'fintoc/v2/resources/crossborder_transfer'

module Fintoc
module V2
module Managers
class CrossborderTransfersManager
def initialize(client)
@client = client
end

def create(quote_id:, idempotency_key: nil, **params)
data = @client.post(version: :v2, idempotency_key:)
.call('crossborder/transfers', quote_id:, **params)
build_transfer(data)
end

# The API expects the status filter as `status[]`; `status:` accepts a string or an array.
def list(status: nil, **params)
params[:'status[]'] = Array(status) unless status.nil?
@client.get(version: :v2).call('crossborder/transfers', **params).map do |data|
build_transfer(data)
end
end

def get(transfer_id)
data = @client.get(version: :v2).call("crossborder/transfers/#{transfer_id}")
build_transfer(data)
end

private

def build_transfer(data)
Fintoc::V2::CrossborderTransfer.new(**data)
end
end
end
end
end
48 changes: 48 additions & 0 deletions lib/fintoc/v2/resources/crossborder_beneficiary.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
module Fintoc
module V2
class CrossborderBeneficiary
attr_reader :id, :object, :mode, :holder_type, :business_name, :first_name, :last_name,
:bank_name, :routing_number, :account_last4, :address, :archived_at,
:created_at

def initialize(
id:,
object:,
mode: nil,
holder_type: nil,
business_name: nil,
first_name: nil,
last_name: nil,
bank_name: nil,
routing_number: nil,
account_last4: nil,
address: nil,
archived_at: nil,
created_at: nil,
**
)
@id = id
@object = object
@mode = mode
@holder_type = holder_type
@business_name = business_name
@first_name = first_name
@last_name = last_name
@bank_name = bank_name
@routing_number = routing_number
@account_last4 = account_last4
@address = address
@archived_at = archived_at
@created_at = created_at
end

def archived?
!@archived_at.nil?
end

def to_s
"Crossborder beneficiary (#{@id}) - #{@bank_name} ****#{@account_last4}"
end
end
end
end
46 changes: 46 additions & 0 deletions lib/fintoc/v2/resources/crossborder_quote.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
module Fintoc
module V2
class CrossborderQuote
attr_reader :id, :object, :mode, :status, :direction, :source_amount, :source_currency,
:target_amount, :target_currency, :exchange_rate, :fees, :transfer_id,
:expires_at, :created_at

def initialize(
id:,
object:,
mode: nil,
status: nil,
direction: nil,
source_amount: nil,
source_currency: nil,
target_amount: nil,
target_currency: nil,
exchange_rate: nil,
fees: nil,
transfer_id: nil,
expires_at: nil,
created_at: nil,
**
)
@id = id
@object = object
@mode = mode
@status = status
@direction = direction
@source_amount = source_amount
@source_currency = source_currency
@target_amount = target_amount
@target_currency = target_currency
@exchange_rate = exchange_rate
@fees = fees
@transfer_id = transfer_id
@expires_at = expires_at
@created_at = created_at
end

def to_s
"Crossborder quote (#{@id}) - #{@direction} #{@status}"
end
end
end
end
Loading
Loading