diff --git a/README.md b/README.md index 4f63f9e..df25687 100644 --- a/README.md +++ b/README.md @@ -435,6 +435,10 @@ accounts = client.v2.accounts.list # Update an account updated_account = client.v2.accounts.update('account_id', description: 'Updated Description') + +# Get the account certificate (signed download URL) +certificate = client.v2.accounts.certificate('account_id') +certificate.download_url ``` #### Account Numbers @@ -461,6 +465,9 @@ updated_account_number = client.v2.account_numbers.update( 'account_number_id', description: 'Updated account number' ) + +# Get the certificate for an account number +certificate = client.v2.account_numbers.certificate('account_number_id') ``` #### Transfers diff --git a/lib/fintoc/v2/managers/account_numbers_manager.rb b/lib/fintoc/v2/managers/account_numbers_manager.rb index 6b65a25..04773c1 100644 --- a/lib/fintoc/v2/managers/account_numbers_manager.rb +++ b/lib/fintoc/v2/managers/account_numbers_manager.rb @@ -1,4 +1,5 @@ require 'fintoc/v2/resources/account_number' +require 'fintoc/v2/resources/account_certificate' module Fintoc module V2 @@ -33,6 +34,11 @@ def delete(account_number_id) _delete_account_number(account_number_id) end + def certificate(account_number_id) + data = @client.get(version: :v2).call("account_numbers/#{account_number_id}/certificate") + Fintoc::V2::AccountCertificate.new(**data) + end + private def _create_account_number( diff --git a/lib/fintoc/v2/managers/accounts_manager.rb b/lib/fintoc/v2/managers/accounts_manager.rb index 4b704ca..1adfad5 100644 --- a/lib/fintoc/v2/managers/accounts_manager.rb +++ b/lib/fintoc/v2/managers/accounts_manager.rb @@ -1,4 +1,5 @@ require 'fintoc/v2/resources/account' +require 'fintoc/v2/resources/account_certificate' module Fintoc module V2 @@ -27,6 +28,11 @@ def update(account_id, idempotency_key: nil, **params) build_account(data) end + def certificate(account_id) + data = @client.get(version: :v2).call("accounts/#{account_id}/certificate") + Fintoc::V2::AccountCertificate.new(**data) + end + private def _create_account(entity_id:, description:, idempotency_key: nil, **params) diff --git a/lib/fintoc/v2/resources/account.rb b/lib/fintoc/v2/resources/account.rb index 18ec4be..ab280a6 100644 --- a/lib/fintoc/v2/resources/account.rb +++ b/lib/fintoc/v2/resources/account.rb @@ -54,6 +54,10 @@ def update(description: nil, idempotency_key: nil) refresh_from_account(updated_account) end + def certificate + @client.accounts.certificate(@id) + end + def active? @status == 'active' end diff --git a/lib/fintoc/v2/resources/account_certificate.rb b/lib/fintoc/v2/resources/account_certificate.rb new file mode 100644 index 0000000..28fd923 --- /dev/null +++ b/lib/fintoc/v2/resources/account_certificate.rb @@ -0,0 +1,26 @@ +module Fintoc + module V2 + class AccountCertificate + attr_reader :object, :account_id, :account_number_id, :download_url, :expires_at + + def initialize( + object:, + account_id:, + account_number_id:, + download_url:, + expires_at: nil, + ** + ) + @object = object + @account_id = account_id + @account_number_id = account_number_id + @download_url = download_url + @expires_at = expires_at + end + + def to_s + "📄 Account certificate (#{@account_number_id})" + end + end + end +end diff --git a/lib/fintoc/v2/resources/account_number.rb b/lib/fintoc/v2/resources/account_number.rb index d0a179d..5a597e4 100644 --- a/lib/fintoc/v2/resources/account_number.rb +++ b/lib/fintoc/v2/resources/account_number.rb @@ -57,6 +57,10 @@ def update(description: nil, status: nil, metadata: nil, idempotency_key: nil) refresh_from_account_number(updated_account_number) end + def certificate + @client.account_numbers.certificate(@id) + end + def enabled? @status == 'enabled' end diff --git a/spec/fixtures/v2/account_certificate.json b/spec/fixtures/v2/account_certificate.json new file mode 100644 index 0000000..86a4f86 --- /dev/null +++ b/spec/fixtures/v2/account_certificate.json @@ -0,0 +1,7 @@ +{ + "object": "account_certificate", + "account_id": "acc_31yYL7h9LVPg121AgFtCyJPDsgM", + "account_number_id": "acno_31yYL5uOb39vzvRIszPhoXYMjt4", + "download_url": "https://storage.example.com/account_certificates/certificate.pdf?signature=2d9a", + "expires_at": "2026-11-09T18:05:00Z" +} diff --git a/spec/lib/fintoc/v2/account_certificate_spec.rb b/spec/lib/fintoc/v2/account_certificate_spec.rb new file mode 100644 index 0000000..6cf5978 --- /dev/null +++ b/spec/lib/fintoc/v2/account_certificate_spec.rb @@ -0,0 +1,71 @@ +require 'json' +require 'webmock/rspec' +require 'fintoc/v2/client/client' + +RSpec.describe Fintoc::V2::AccountCertificate do + let(:client) { Fintoc::V2::Client.new('sk_test_certificates') } + let(:payload) do + JSON.parse(File.read('spec/fixtures/v2/account_certificate.json'), symbolize_names: true) + end + let(:account_id) { payload[:account_id] } + let(:account_number_id) { payload[:account_number_id] } + let(:headers) { { 'Content-Type' => 'application/json' } } + + before do + stub_request(:get, "https://api.fintoc.com/v2/accounts/#{account_id}/certificate") + .to_return(body: payload.to_json, headers: headers) + stub_request(:get, "https://api.fintoc.com/v2/account_numbers/#{account_number_id}/certificate") + .to_return(body: payload.to_json, headers: headers) + end + + describe 'accounts manager #certificate' do + it 'returns the account certificate' do + expect(client.accounts.certificate(account_id)) + .to be_a(described_class).and have_attributes(payload) + end + end + + describe 'account numbers manager #certificate' do + it 'returns the account certificate' do + expect(client.account_numbers.certificate(account_number_id)) + .to be_a(described_class).and have_attributes(payload) + end + end + + describe 'Account#certificate' do + let(:account) do + Fintoc::V2::Account.new( + id: account_id, object: 'account', mode: 'test', description: 'Main', + available_balance: 0, currency: 'MXN', is_root: true, + root_account_number_id: account_number_id, root_account_number: '738969123456789120', + status: 'active', entity: {}, client: + ) + end + + it 'fetches the certificate of the account' do + expect(account.certificate).to be_a(described_class).and have_attributes(payload) + end + end + + describe 'AccountNumber#certificate' do + let(:account_number) do + Fintoc::V2::AccountNumber.new( + id: account_number_id, object: 'account_number', description: 'Main', + number: '738969123456789120', created_at: '2026-11-09T18:00:00Z', + updated_at: '2026-11-09T18:00:00Z', mode: 'test', status: 'enabled', is_root: true, + account_id:, metadata: {}, client: + ) + end + + it 'fetches the certificate of the account number' do + expect(account_number.certificate).to be_a(described_class).and have_attributes(payload) + end + end + + describe '#to_s' do + it 'does not expose the signed download URL' do + expect(described_class.new(**payload).to_s) + .to eq("📄 Account certificate (#{account_number_id})") + end + end +end