├── .gitignore ├── .rspec ├── lib └── gocardless_pro │ ├── error │ ├── permission_error.rb │ ├── rate_limit_error.rb │ ├── authentication_error.rb │ ├── gocardless_error.rb │ ├── validation_error.rb │ ├── invalid_api_usage_error.rb │ ├── api_error.rb │ └── invalid_state_error.rb │ ├── version.rb │ ├── api_response.rb │ ├── response.rb │ ├── resources │ ├── payer_theme.rb │ ├── logo.rb │ ├── mandate_pdf.rb │ ├── bank_details_lookup.rb │ ├── export.rb │ ├── currency_exchange_rate.rb │ ├── scenario_simulator.rb │ ├── bank_account_detail.rb │ ├── tax_rate.rb │ ├── billing_request_with_action.rb │ ├── institution.rb │ ├── transferred_mandate.rb │ ├── webhook.rb │ ├── balance.rb │ ├── negative_balance_limit.rb │ ├── refund.rb │ ├── scheme_identifier.rb │ ├── customer.rb │ ├── verification_detail.rb │ ├── bank_authorisation.rb │ ├── payout.rb │ ├── payout_item.rb │ ├── instalment_schedule.rb │ ├── payment.rb │ ├── customer_notification.rb │ ├── creditor_bank_account.rb │ ├── mandate.rb │ ├── billing_request_flow.rb │ ├── outbound_payment.rb │ ├── customer_bank_account.rb │ ├── block.rb │ ├── billing_request_template.rb │ ├── mandate_import_entry.rb │ ├── mandate_import.rb │ ├── creditor.rb │ └── event.rb │ ├── list_response.rb │ ├── paginator.rb │ ├── error.rb │ ├── services │ ├── payer_themes_service.rb │ ├── bank_account_details_service.rb │ ├── base_service.rb │ ├── transferred_mandates_service.rb │ ├── billing_request_with_actions_service.rb │ ├── logos_service.rb │ ├── balances_service.rb │ ├── currency_exchange_rates_service.rb │ ├── negative_balance_limits_service.rb │ ├── customer_notifications_service.rb │ ├── payout_items_service.rb │ ├── billing_request_flows_service.rb │ ├── exports_service.rb │ ├── events_service.rb │ ├── verification_details_service.rb │ ├── tax_rates_service.rb │ ├── bank_authorisations_service.rb │ ├── institutions_service.rb │ ├── bank_details_lookups_service.rb │ ├── mandate_pdfs_service.rb │ ├── mandate_import_entries_service.rb │ ├── payouts_service.rb │ └── webhooks_service.rb │ ├── middlewares │ └── raise_gocardless_errors.rb │ ├── api_service.rb │ └── request.rb ├── .travis.yml ├── demo.rb ├── .rubocop.yml ├── Gemfile ├── spec ├── client_spec.rb ├── response_spec.rb ├── api_response_spec.rb ├── error_spec.rb ├── resources │ ├── scenario_simulator_spec.rb │ ├── transferred_mandate_spec.rb │ ├── customer_notification_spec.rb │ ├── bank_account_detail_spec.rb │ ├── payout_item_spec.rb │ ├── logo_spec.rb │ ├── payer_theme_spec.rb │ ├── currency_exchange_rate_spec.rb │ ├── mandate_pdf_spec.rb │ ├── balance_spec.rb │ ├── negative_balance_limit_spec.rb │ ├── billing_request_with_action_spec.rb │ └── bank_details_lookup_spec.rb └── services │ ├── scenario_simulators_service_spec.rb │ ├── transferred_mandates_service_spec.rb │ └── customer_notifications_service_spec.rb ├── LICENSE.txt ├── gocardless_pro.gemspec └── .github └── workflows └── ci.yml /.gitignore: -------------------------------------------------------------------------------- 1 | Gemfile.lock 2 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --color 2 | --require spec_helper 3 | -------------------------------------------------------------------------------- /lib/gocardless_pro/error/permission_error.rb: -------------------------------------------------------------------------------- 1 | module GoCardlessPro 2 | class PermissionError < InvalidApiUsageError 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /lib/gocardless_pro/error/rate_limit_error.rb: -------------------------------------------------------------------------------- 1 | module GoCardlessPro 2 | class RateLimitError < InvalidApiUsageError 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /lib/gocardless_pro/error/authentication_error.rb: -------------------------------------------------------------------------------- 1 | module GoCardlessPro 2 | class AuthenticationError < InvalidApiUsageError 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | 3 | rvm: 4 | - 2.3.0 5 | - 2.0.0 6 | 7 | sudo: false 8 | 9 | script: 10 | - bundle exec rspec spec 11 | -------------------------------------------------------------------------------- /lib/gocardless_pro/version.rb: -------------------------------------------------------------------------------- 1 | module GoCardlessPro 2 | end 3 | 4 | module GoCardlessPro 5 | # Current version of the GC gem 6 | VERSION = '4.2.0' 7 | end 8 | -------------------------------------------------------------------------------- /lib/gocardless_pro/error/gocardless_error.rb: -------------------------------------------------------------------------------- 1 | module GoCardlessPro 2 | # Thrown when the API returns a GoCardlessError 3 | class GoCardlessError < Error 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /lib/gocardless_pro/error/validation_error.rb: -------------------------------------------------------------------------------- 1 | module GoCardlessPro 2 | # Thrown when the API returns a validation error 3 | class ValidationError < Error 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /lib/gocardless_pro/error/invalid_api_usage_error.rb: -------------------------------------------------------------------------------- 1 | module GoCardlessPro 2 | # Thrown when the API returns an invalid usage error 3 | class InvalidApiUsageError < Error 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /lib/gocardless_pro/error/api_error.rb: -------------------------------------------------------------------------------- 1 | module GoCardlessPro 2 | # Thrown when something goes wrong with the request to the API 3 | # and we don\'t get a proper response from the GC API 4 | class ApiError < Error 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /demo.rb: -------------------------------------------------------------------------------- 1 | require_relative 'lib/gocardless_pro' 2 | 3 | @client = GoCardlessPro::Client.new( 4 | access_token: ENV['GOCARDLESS_TOKEN'], 5 | environment: :sandbox 6 | ) 7 | 8 | puts 'Your first customer:' 9 | puts "-> #{@client.customers.list.records.first.inspect}" 10 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | Layout/DotPosition: 2 | EnforcedStyle: trailing 3 | 4 | Style/TrailingCommaInArrayLiteral: 5 | EnforcedStyleForMultiline: comma 6 | 7 | Style/TrailingCommaInHashLiteral: 8 | EnforcedStyleForMultiline: comma 9 | 10 | Style/AccessorGrouping: 11 | EnforcedStyle: separated 12 | -------------------------------------------------------------------------------- /lib/gocardless_pro/api_response.rb: -------------------------------------------------------------------------------- 1 | module GoCardlessPro 2 | # wraps a faraday response object with some accessors 3 | class ApiResponse 4 | extend Forwardable 5 | 6 | def initialize(response) 7 | @response = response 8 | end 9 | 10 | def_delegator :@response, :headers 11 | def_delegator :@response, :body 12 | def_delegator :@response, :status_code 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | gemspec 3 | 4 | # We support both pre-1.x and post-1.x Faraday versions, but to ensure compatibility we 5 | # pin this gem against each in separate runs of CI, using the FARADAY_VERSION env var. For 6 | # more details on the values, see .github/workflows/tests.yml in the gocardless-pro-ruby 7 | # repository. 8 | if ENV.key?("FARADAY_VERSION") 9 | gem 'faraday', "~> #{ENV["FARADAY_VERSION"]}" 10 | end 11 | -------------------------------------------------------------------------------- /spec/client_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe GoCardlessPro::Client do 4 | subject { -> { described_class.new(options) } } 5 | 6 | let(:options) do 7 | { 8 | environment: environment, 9 | token: token 10 | } 11 | end 12 | 13 | context 'when initialised without an Access Token' do 14 | let(:environment) { :live } 15 | let(:token) { nil } 16 | 17 | it { is_expected.to raise_error('No Access Token given to GoCardless Client') } 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /lib/gocardless_pro/response.rb: -------------------------------------------------------------------------------- 1 | module GoCardlessPro 2 | # A class to wrap an API response 3 | class Response 4 | extend Forwardable 5 | 6 | def_delegator :@response, :headers 7 | def_delegator :@response, :status, :status_code 8 | 9 | # Initialize a response instance 10 | # @param response an API response 11 | def initialize(response) 12 | @response = response 13 | end 14 | 15 | # Return the body of parsed JSON body of the API response 16 | def body 17 | JSON.parse(@response.body) unless @response.body.empty? 18 | end 19 | 20 | # Returns the meta hash of the response 21 | def meta 22 | json_body.fetch('meta', {}) 23 | end 24 | 25 | # Returns the limit parameter from the response 26 | def limit 27 | meta.fetch('limit', nil) 28 | end 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /lib/gocardless_pro/error/invalid_state_error.rb: -------------------------------------------------------------------------------- 1 | module GoCardlessPro 2 | # Thrown when the API returns an invalid state error 3 | class InvalidStateError < Error 4 | IDEMPOTENT_CREATION_CONFLICT = 'idempotent_creation_conflict'.freeze 5 | CONFLICTING_RESOURCE_ID = 'conflicting_resource_id'.freeze 6 | 7 | def idempotent_creation_conflict? 8 | !idempotent_creation_conflict_error.nil? 9 | end 10 | 11 | def conflicting_resource_id 12 | return unless idempotent_creation_conflict? 13 | 14 | idempotent_creation_conflict_error['links'][CONFLICTING_RESOURCE_ID] 15 | end 16 | 17 | private 18 | 19 | def idempotent_creation_conflict_error 20 | errors.find { |error| error['reason'] == IDEMPOTENT_CREATION_CONFLICT } 21 | end 22 | end 23 | 24 | IdempotencyConflict = Class.new(Error) 25 | end 26 | -------------------------------------------------------------------------------- /spec/response_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe GoCardlessPro::Response do 4 | subject(:response) { described_class.new(raw_response) } 5 | 6 | let(:default_headers) do 7 | { 'Content-Type' => 'application/json' } 8 | end 9 | 10 | describe '#body' do 11 | subject(:body) { response.body } 12 | 13 | let(:raw_response) do 14 | double('response', 15 | headers: default_headers, 16 | status: 200, 17 | body: { customers: [] }.to_json) 18 | end 19 | 20 | it 'returns the body parsed into a hash' do 21 | expect(body).to eq('customers' => []) 22 | end 23 | 24 | context 'when the response is empty' do 25 | let(:raw_response) do 26 | double('response', headers: default_headers, status: 204, body: '') 27 | end 28 | 29 | it 'returns nil' do 30 | expect(body).to be_nil 31 | end 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /spec/api_response_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'json' 3 | 4 | describe GoCardlessPro::ApiResponse do 5 | describe 'wrapping a Faraday response' do 6 | let(:content_type) { 'application/json' } 7 | 8 | let(:stubbed) do 9 | Faraday::Adapter::Test::Stubs.new do |stub| 10 | stub.get('/testing') do |_env| 11 | [200, { 'Content-Type' => content_type }, { test: true }.to_json] 12 | end 13 | end 14 | end 15 | let(:test) { Faraday.new { |builder| builder.adapter :test, stubbed } } 16 | subject(:api_response) do 17 | described_class.new( 18 | GoCardlessPro::Response.new(test.get('/testing')) 19 | ) 20 | end 21 | 22 | specify { expect(api_response.status_code).to eql(200) } 23 | specify do 24 | expect(api_response.headers).to eql('Content-Type' => content_type) 25 | end 26 | specify { expect(api_response.body).to eql('test' => true) } 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /lib/gocardless_pro/resources/payer_theme.rb: -------------------------------------------------------------------------------- 1 | # 2 | # This client is automatically generated from a template and JSON schema definition. 3 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 4 | # 5 | 6 | require 'uri' 7 | 8 | module GoCardlessPro 9 | # A module containing classes for each of the resources in the GC Api 10 | module Resources 11 | # Represents an instance of a payer_theme resource returned from the API 12 | 13 | # Custom colour themes for payment pages and customer notifications. 14 | class PayerTheme 15 | attr_reader :id 16 | 17 | # Initialize a payer_theme resource instance 18 | # @param object [Hash] an object returned from the API 19 | def initialize(object, response = nil) 20 | @object = object 21 | 22 | @id = object['id'] 23 | @response = response 24 | end 25 | 26 | def api_response 27 | ApiResponse.new(@response) 28 | end 29 | 30 | # Provides the payer_theme resource as a hash of all its readable attributes 31 | def to_h 32 | @object 33 | end 34 | end 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 GoCardless 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /lib/gocardless_pro/list_response.rb: -------------------------------------------------------------------------------- 1 | module GoCardlessPro 2 | # Wraps a response from an API LIST endpoint 3 | class ListResponse 4 | attr_reader :records 5 | 6 | # Initialize a list response 7 | # @param options [Hash] 8 | # @option option :raw_response the raw API response 9 | # @option option :resource_class the class for the resource returned by the API 10 | # @option option :unenveloped_body the parsed response from the API 11 | def initialize(options = {}) 12 | @response = options.fetch(:response) 13 | @resource_class = options.fetch(:resource_class) 14 | @unenveloped_body = options.fetch(:unenveloped_body) 15 | 16 | @records = @unenveloped_body.map { |item| @resource_class.new(item) } 17 | end 18 | 19 | def api_response 20 | @api_response ||= ApiResponse.new(@response) 21 | end 22 | 23 | # return the before cursor for paginating 24 | def before 25 | @response.body['meta']['cursors']['before'] 26 | end 27 | 28 | # return the after cursor for paginating 29 | def after 30 | @response.body['meta']['cursors']['after'] 31 | end 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /lib/gocardless_pro/resources/logo.rb: -------------------------------------------------------------------------------- 1 | # 2 | # This client is automatically generated from a template and JSON schema definition. 3 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 4 | # 5 | 6 | require 'uri' 7 | 8 | module GoCardlessPro 9 | # A module containing classes for each of the resources in the GC Api 10 | module Resources 11 | # Represents an instance of a logo resource returned from the API 12 | 13 | # Logos are image uploads that, when associated with a creditor, are shown 14 | # on the [billing request flow](#billing-requests-billing-request-flows) 15 | # payment pages. 16 | class Logo 17 | attr_reader :id 18 | 19 | # Initialize a logo resource instance 20 | # @param object [Hash] an object returned from the API 21 | def initialize(object, response = nil) 22 | @object = object 23 | 24 | @id = object['id'] 25 | @response = response 26 | end 27 | 28 | def api_response 29 | ApiResponse.new(@response) 30 | end 31 | 32 | # Provides the logo resource as a hash of all its readable attributes 33 | def to_h 34 | @object 35 | end 36 | end 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /gocardless_pro.gemspec: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | lib = File.expand_path('../lib', __FILE__) 3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 4 | require 'gocardless_pro/version' 5 | 6 | Gem::Specification.new do |spec| 7 | spec.name = 'gocardless_pro' 8 | spec.version = GoCardlessPro::VERSION 9 | spec.authors = %w(GoCardless) 10 | spec.email = %w(engineering@gocardless.com) 11 | spec.summary = %q{A gem for calling the GoCardless Pro API} 12 | spec.homepage = 'https://github.com/gocardless/gocardless-pro-ruby' 13 | spec.license = 'MIT' 14 | 15 | spec.files = Dir['README.md', 'LICENSE.txt', 'lib/**/*'] 16 | spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } 17 | spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) 18 | spec.require_paths = ['lib'] 19 | 20 | spec.required_ruby_version = '>= 2.6' 21 | spec.add_dependency 'faraday', ['>= 2', '< 3'] 22 | spec.add_dependency 'base64' 23 | 24 | spec.add_development_dependency 'rspec', '~> 3.7.0' 25 | spec.add_development_dependency 'webmock', '~> 3.8.3' 26 | spec.add_development_dependency 'rubocop', '~> 1.44.1' 27 | spec.add_development_dependency 'yard', '~> 0.9.11' 28 | end 29 | -------------------------------------------------------------------------------- /lib/gocardless_pro/paginator.rb: -------------------------------------------------------------------------------- 1 | module GoCardlessPro 2 | # A class that can take an API LIST query and auto paginate through results 3 | class Paginator 4 | # initialize a paginator 5 | # @param options [Hash] 6 | # @option options :service the service class to use to make requests to 7 | # @option options :options additional options to send with the requests 8 | def initialize(options = {}) 9 | @service = options.fetch(:service) 10 | @options = options.fetch(:options) 11 | end 12 | 13 | # Get a lazy enumerable for listing data from the API 14 | def enumerator 15 | response = get_initial_response 16 | Enumerator.new do |yielder| 17 | loop do 18 | response.records.each { |item| yielder << item } 19 | 20 | after_cursor = response.after 21 | break if after_cursor.nil? 22 | 23 | @options[:params] ||= {} 24 | @options[:params] = @options[:params].merge(after: after_cursor) 25 | response = @service.list(@options.merge(after: after_cursor)) 26 | end 27 | end.lazy 28 | end 29 | 30 | private 31 | 32 | def get_initial_response 33 | @initial_response ||= @service.list(@options) 34 | end 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /lib/gocardless_pro/resources/mandate_pdf.rb: -------------------------------------------------------------------------------- 1 | # 2 | # This client is automatically generated from a template and JSON schema definition. 3 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 4 | # 5 | 6 | require 'uri' 7 | 8 | module GoCardlessPro 9 | # A module containing classes for each of the resources in the GC Api 10 | module Resources 11 | # Represents an instance of a mandate_pdf resource returned from the API 12 | 13 | # Mandate PDFs allow you to easily display [scheme-rules 14 | # compliant](#appendix-compliance-requirements) Direct Debit mandates to 15 | # your customers. 16 | class MandatePdf 17 | attr_reader :expires_at, :url 18 | 19 | # Initialize a mandate_pdf resource instance 20 | # @param object [Hash] an object returned from the API 21 | def initialize(object, response = nil) 22 | @object = object 23 | 24 | @expires_at = object['expires_at'] 25 | @url = object['url'] 26 | @response = response 27 | end 28 | 29 | def api_response 30 | ApiResponse.new(@response) 31 | end 32 | 33 | # Provides the mandate_pdf resource as a hash of all its readable attributes 34 | def to_h 35 | @object 36 | end 37 | end 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /lib/gocardless_pro/resources/bank_details_lookup.rb: -------------------------------------------------------------------------------- 1 | # 2 | # This client is automatically generated from a template and JSON schema definition. 3 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 4 | # 5 | 6 | require 'uri' 7 | 8 | module GoCardlessPro 9 | # A module containing classes for each of the resources in the GC Api 10 | module Resources 11 | # Represents an instance of a bank_details_lookup resource returned from the API 12 | 13 | # Look up the name and reachability of a bank account. 14 | class BankDetailsLookup 15 | attr_reader :available_debit_schemes, :bank_name, :bic 16 | 17 | # Initialize a bank_details_lookup resource instance 18 | # @param object [Hash] an object returned from the API 19 | def initialize(object, response = nil) 20 | @object = object 21 | 22 | @available_debit_schemes = object['available_debit_schemes'] 23 | @bank_name = object['bank_name'] 24 | @bic = object['bic'] 25 | @response = response 26 | end 27 | 28 | def api_response 29 | ApiResponse.new(@response) 30 | end 31 | 32 | # Provides the bank_details_lookup resource as a hash of all its readable attributes 33 | def to_h 34 | @object 35 | end 36 | end 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /lib/gocardless_pro/resources/export.rb: -------------------------------------------------------------------------------- 1 | # 2 | # This client is automatically generated from a template and JSON schema definition. 3 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 4 | # 5 | 6 | require 'uri' 7 | 8 | module GoCardlessPro 9 | # A module containing classes for each of the resources in the GC Api 10 | module Resources 11 | # Represents an instance of a export resource returned from the API 12 | 13 | # File-based exports of data 14 | class Export 15 | attr_reader :created_at, :currency, :download_url, :export_type, :id 16 | 17 | # Initialize a export resource instance 18 | # @param object [Hash] an object returned from the API 19 | def initialize(object, response = nil) 20 | @object = object 21 | 22 | @created_at = object['created_at'] 23 | @currency = object['currency'] 24 | @download_url = object['download_url'] 25 | @export_type = object['export_type'] 26 | @id = object['id'] 27 | @response = response 28 | end 29 | 30 | def api_response 31 | ApiResponse.new(@response) 32 | end 33 | 34 | # Provides the export resource as a hash of all its readable attributes 35 | def to_h 36 | @object 37 | end 38 | end 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /lib/gocardless_pro/resources/currency_exchange_rate.rb: -------------------------------------------------------------------------------- 1 | # 2 | # This client is automatically generated from a template and JSON schema definition. 3 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 4 | # 5 | 6 | require 'uri' 7 | 8 | module GoCardlessPro 9 | # A module containing classes for each of the resources in the GC Api 10 | module Resources 11 | # Represents an instance of a currency_exchange_rate resource returned from the API 12 | 13 | # Currency exchange rates from our foreign exchange provider. 14 | class CurrencyExchangeRate 15 | attr_reader :rate, :source, :target, :time 16 | 17 | # Initialize a currency_exchange_rate resource instance 18 | # @param object [Hash] an object returned from the API 19 | def initialize(object, response = nil) 20 | @object = object 21 | 22 | @rate = object['rate'] 23 | @source = object['source'] 24 | @target = object['target'] 25 | @time = object['time'] 26 | @response = response 27 | end 28 | 29 | def api_response 30 | ApiResponse.new(@response) 31 | end 32 | 33 | # Provides the currency_exchange_rate resource as a hash of all its readable attributes 34 | def to_h 35 | @object 36 | end 37 | end 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /lib/gocardless_pro/resources/scenario_simulator.rb: -------------------------------------------------------------------------------- 1 | # 2 | # This client is automatically generated from a template and JSON schema definition. 3 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 4 | # 5 | 6 | require 'uri' 7 | 8 | module GoCardlessPro 9 | # A module containing classes for each of the resources in the GC Api 10 | module Resources 11 | # Represents an instance of a scenario_simulator resource returned from the API 12 | 13 | # Scenario Simulators allow you to manually trigger and test certain paths 14 | # that your 15 | # integration will encounter in the real world. These endpoints are only 16 | # active in the 17 | # sandbox environment. 18 | class ScenarioSimulator 19 | attr_reader :id 20 | 21 | # Initialize a scenario_simulator resource instance 22 | # @param object [Hash] an object returned from the API 23 | def initialize(object, response = nil) 24 | @object = object 25 | 26 | @id = object['id'] 27 | @response = response 28 | end 29 | 30 | def api_response 31 | ApiResponse.new(@response) 32 | end 33 | 34 | # Provides the scenario_simulator resource as a hash of all its readable attributes 35 | def to_h 36 | @object 37 | end 38 | end 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /lib/gocardless_pro/error.rb: -------------------------------------------------------------------------------- 1 | module GoCardlessPro 2 | # A class to represent an API Error 3 | class Error < StandardError 4 | attr_reader :error 5 | 6 | # intialize a new error 7 | #  @param error the error from the API 8 | def initialize(error) 9 | raise ArgumentError, 'GoCardless errors expect a hash' unless error.is_a?(Hash) 10 | 11 | @error = error 12 | end 13 | 14 | # access the documentation_url from the response 15 | def documentation_url 16 | @error['documentation_url'] 17 | end 18 | 19 | # access the message from the response 20 | def message 21 | @error['message'] 22 | end 23 | 24 | def to_s 25 | if errors.any? 26 | errors 27 | .map { |err| "#{err['field']} #{err['message']}" } 28 | .join(', ') 29 | else 30 | @error['message'] 31 | end 32 | end 33 | 34 | # access the type from the response 35 | def type 36 | @error['type'] 37 | end 38 | 39 | # access the code from the response 40 | def code 41 | @error['code'] 42 | end 43 | 44 | # access the request_id from the response 45 | def request_id 46 | @error['request_id'] 47 | end 48 | 49 | # access the errors from the response 50 | def errors 51 | @error.fetch('errors', []) 52 | end 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /lib/gocardless_pro/resources/bank_account_detail.rb: -------------------------------------------------------------------------------- 1 | # 2 | # This client is automatically generated from a template and JSON schema definition. 3 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 4 | # 5 | 6 | require 'uri' 7 | 8 | module GoCardlessPro 9 | # A module containing classes for each of the resources in the GC Api 10 | module Resources 11 | # Represents an instance of a bank_account_detail resource returned from the API 12 | 13 | # Retrieve bank account details in JWE encrypted format 14 | class BankAccountDetail 15 | attr_reader :ciphertext, :encrypted_key, :iv, :protected, :tag 16 | 17 | # Initialize a bank_account_detail resource instance 18 | # @param object [Hash] an object returned from the API 19 | def initialize(object, response = nil) 20 | @object = object 21 | 22 | @ciphertext = object['ciphertext'] 23 | @encrypted_key = object['encrypted_key'] 24 | @iv = object['iv'] 25 | @protected = object['protected'] 26 | @tag = object['tag'] 27 | @response = response 28 | end 29 | 30 | def api_response 31 | ApiResponse.new(@response) 32 | end 33 | 34 | # Provides the bank_account_detail resource as a hash of all its readable attributes 35 | def to_h 36 | @object 37 | end 38 | end 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | pull_request: 4 | types: [opened, reopened, synchronize] 5 | push: 6 | branches: 7 | - master 8 | 9 | env: 10 | RUBYGEM_PUBLISH_API_KEY: ${{ secrets.RUBYGEM_PUBLISH_API_KEY }} 11 | 12 | jobs: 13 | test: 14 | runs-on: ubuntu-latest 15 | strategy: 16 | matrix: 17 | faraday-version: 18 | - '2.0' 19 | ruby-version: 20 | - '3.2' 21 | - '3.3' 22 | - '3.4' 23 | env: 24 | FARADAY_VERSION: ${{ matrix.faraday-version }} 25 | steps: 26 | - uses: actions/checkout@v2 27 | - uses: ruby/setup-ruby@v1 28 | with: 29 | ruby-version: ${{ matrix.ruby-version }} 30 | bundler-cache: true 31 | - run: bundle install && bundle exec rspec 32 | 33 | publish: 34 | if: github.ref == 'refs/heads/master' 35 | runs-on: ubuntu-latest 36 | needs: 37 | - test 38 | steps: 39 | - uses: actions/checkout@v2 40 | - uses: ruby/setup-ruby@v1 41 | with: 42 | ruby-version: '3.2' 43 | bundler-cache: true 44 | - run: | 45 | mkdir -p $HOME/.gem 46 | touch $HOME/.gem/credentials 47 | chmod 0600 $HOME/.gem/credentials 48 | printf -- "---\n:rubygems_api_key: $RUBYGEM_PUBLISH_API_KEY\n" > $HOME/.gem/credentials 49 | gem build *.gemspec 50 | gem push *.gem 51 | -------------------------------------------------------------------------------- /lib/gocardless_pro/resources/tax_rate.rb: -------------------------------------------------------------------------------- 1 | # 2 | # This client is automatically generated from a template and JSON schema definition. 3 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 4 | # 5 | 6 | require 'uri' 7 | 8 | module GoCardlessPro 9 | # A module containing classes for each of the resources in the GC Api 10 | module Resources 11 | # Represents an instance of a tax_rate resource returned from the API 12 | 13 | # Tax rates from tax authority. 14 | # 15 | # We also maintain a [static list of the tax rates for each 16 | # jurisdiction](#appendix-tax-rates). 17 | class TaxRate 18 | attr_reader :end_date, :id, :jurisdiction, :percentage, :start_date, :type 19 | 20 | # Initialize a tax_rate resource instance 21 | # @param object [Hash] an object returned from the API 22 | def initialize(object, response = nil) 23 | @object = object 24 | 25 | @end_date = object['end_date'] 26 | @id = object['id'] 27 | @jurisdiction = object['jurisdiction'] 28 | @percentage = object['percentage'] 29 | @start_date = object['start_date'] 30 | @type = object['type'] 31 | @response = response 32 | end 33 | 34 | def api_response 35 | ApiResponse.new(@response) 36 | end 37 | 38 | # Provides the tax_rate resource as a hash of all its readable attributes 39 | def to_h 40 | @object 41 | end 42 | end 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /lib/gocardless_pro/services/payer_themes_service.rb: -------------------------------------------------------------------------------- 1 | require_relative './base_service' 2 | 3 | # encoding: utf-8 4 | # 5 | # This client is automatically generated from a template and JSON schema definition. 6 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 7 | # 8 | 9 | module GoCardlessPro 10 | module Services 11 | # Service for making requests to the PayerTheme endpoints 12 | class PayerThemesService < BaseService 13 | # Creates a new payer theme associated with a creditor. If a creditor already 14 | # has payer themes, this will update the existing payer theme linked to the 15 | # creditor. 16 | # Example URL: /branding/payer_themes 17 | # @param options [Hash] parameters as a hash, under a params key. 18 | def create_for_creditor(options = {}) 19 | path = '/branding/payer_themes' 20 | 21 | params = options.delete(:params) || {} 22 | options[:params] = {} 23 | options[:params][envelope_key] = params 24 | 25 | options[:retry_failures] = true 26 | 27 | response = make_request(:post, path, options) 28 | 29 | return if response.body.nil? 30 | 31 | Resources::PayerTheme.new(unenvelope_body(response.body), response) 32 | end 33 | 34 | private 35 | 36 | # Unenvelope the response of the body using the service's `envelope_key` 37 | # 38 | # @param body [Hash] 39 | def unenvelope_body(body) 40 | body[envelope_key] || body['data'] 41 | end 42 | 43 | # return the key which API responses will envelope data under 44 | def envelope_key 45 | 'payer_themes' 46 | end 47 | end 48 | end 49 | end 50 | -------------------------------------------------------------------------------- /lib/gocardless_pro/services/bank_account_details_service.rb: -------------------------------------------------------------------------------- 1 | require_relative './base_service' 2 | 3 | # encoding: utf-8 4 | # 5 | # This client is automatically generated from a template and JSON schema definition. 6 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 7 | # 8 | 9 | module GoCardlessPro 10 | module Services 11 | # Service for making requests to the BankAccountDetail endpoints 12 | class BankAccountDetailsService < BaseService 13 | # Returns bank account details in the flattened JSON Web Encryption format 14 | # described in RFC 7516 15 | # Example URL: /bank_account_details/:identity 16 | # 17 | # @param identity # Unique identifier, beginning with "BA". 18 | # @param options [Hash] parameters as a hash, under a params key. 19 | def get(identity, options = {}) 20 | path = sub_url('/bank_account_details/:identity', { 21 | 'identity' => identity 22 | }) 23 | 24 | options[:retry_failures] = true 25 | 26 | response = make_request(:get, path, options) 27 | 28 | return if response.body.nil? 29 | 30 | Resources::BankAccountDetail.new(unenvelope_body(response.body), response) 31 | end 32 | 33 | private 34 | 35 | # Unenvelope the response of the body using the service's `envelope_key` 36 | # 37 | # @param body [Hash] 38 | def unenvelope_body(body) 39 | body[envelope_key] || body['data'] 40 | end 41 | 42 | # return the key which API responses will envelope data under 43 | def envelope_key 44 | 'bank_account_details' 45 | end 46 | end 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /lib/gocardless_pro/services/base_service.rb: -------------------------------------------------------------------------------- 1 | require 'cgi' 2 | 3 | module GoCardlessPro 4 | # Module that contains all services for making requests to the API. 5 | module Services 6 | # Base Service that all services inherit from. 7 | class BaseService 8 | # Create a new service instance to make requests against 9 | # 10 | # @param api_service [GoCardlessPro::ApiService}}] an instance of the ApiService 11 | def initialize(api_service) 12 | @api_service = api_service 13 | end 14 | 15 | # Make a request to the API using the API service instance 16 | # 17 | # @param method [Symbol] the method to use to make the request 18 | # @param path [String] the URL (without the base domain) to make the request to 19 | # @param options [Hash] the options hash - either the query parameters for a GET, or the body if POST/PUT 20 | def make_request(method, path, options = {}) 21 | @api_service.make_request(method, path, options.merge(envelope_key: envelope_key)) 22 | end 23 | 24 | # Get the envelope key for the given service. Children are expected to implement this method. 25 | def envelope_key 26 | raise NotImplementedError 27 | end 28 | 29 | # take a URL with placeholder params and substitute them out for the actual value 30 | # @param url [String] the URL with placeholders in 31 | # @param param_map [Hash] a hash of placeholders and their actual values (which will be escaped) 32 | def sub_url(url, param_map) 33 | param_map.reduce(url) do |new_url, (param, value)| 34 | new_url.gsub(":#{param}", CGI.escape(value)) 35 | end 36 | end 37 | end 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /lib/gocardless_pro/resources/billing_request_with_action.rb: -------------------------------------------------------------------------------- 1 | # 2 | # This client is automatically generated from a template and JSON schema definition. 3 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 4 | # 5 | 6 | require 'uri' 7 | 8 | module GoCardlessPro 9 | # A module containing classes for each of the resources in the GC Api 10 | module Resources 11 | # Represents an instance of a billing_request_with_action resource returned from the API 12 | 13 | # Billing Requests help create resources that require input or action from 14 | # a customer. An example of required input might be additional customer 15 | # billing details, while an action would be asking a customer to authorise a 16 | # payment using their mobile banking app. 17 | # 18 | # See [Billing Requests: 19 | # Overview](https://developer.gocardless.com/getting-started/billing-requests/overview/) 20 | # for how-to's, explanations and tutorials. 21 | class BillingRequestWithAction 22 | attr_reader :bank_authorisations, :billing_requests 23 | 24 | # Initialize a billing_request_with_action resource instance 25 | # @param object [Hash] an object returned from the API 26 | def initialize(object, response = nil) 27 | @object = object 28 | 29 | @bank_authorisations = object['bank_authorisations'] 30 | @billing_requests = object['billing_requests'] 31 | @response = response 32 | end 33 | 34 | def api_response 35 | ApiResponse.new(@response) 36 | end 37 | 38 | # Provides the billing_request_with_action resource as a hash of all its readable attributes 39 | def to_h 40 | @object 41 | end 42 | end 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /lib/gocardless_pro/services/transferred_mandates_service.rb: -------------------------------------------------------------------------------- 1 | require_relative './base_service' 2 | 3 | # encoding: utf-8 4 | # 5 | # This client is automatically generated from a template and JSON schema definition. 6 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 7 | # 8 | 9 | module GoCardlessPro 10 | module Services 11 | # Service for making requests to the TransferredMandate endpoints 12 | class TransferredMandatesService < BaseService 13 | # Returns new customer bank details for a mandate that's been recently 14 | # transferred 15 | # Example URL: /transferred_mandates/:identity 16 | # 17 | # @param identity # Unique identifier, beginning with "MD". Note that this prefix may not 18 | # apply to mandates created before 2016. 19 | # @param options [Hash] parameters as a hash, under a params key. 20 | def transferred_mandates(identity, options = {}) 21 | path = sub_url('/transferred_mandates/:identity', { 22 | 'identity' => identity 23 | }) 24 | 25 | options[:retry_failures] = false 26 | 27 | response = make_request(:get, path, options) 28 | 29 | return if response.body.nil? 30 | 31 | Resources::TransferredMandate.new(unenvelope_body(response.body), response) 32 | end 33 | 34 | private 35 | 36 | # Unenvelope the response of the body using the service's `envelope_key` 37 | # 38 | # @param body [Hash] 39 | def unenvelope_body(body) 40 | body[envelope_key] || body['data'] 41 | end 42 | 43 | # return the key which API responses will envelope data under 44 | def envelope_key 45 | 'transferred_mandates' 46 | end 47 | end 48 | end 49 | end 50 | -------------------------------------------------------------------------------- /lib/gocardless_pro/resources/institution.rb: -------------------------------------------------------------------------------- 1 | # 2 | # This client is automatically generated from a template and JSON schema definition. 3 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 4 | # 5 | 6 | require 'uri' 7 | 8 | module GoCardlessPro 9 | # A module containing classes for each of the resources in the GC Api 10 | module Resources 11 | # Represents an instance of a institution resource returned from the API 12 | 13 | # Institutions that are supported when creating [Bank 14 | # Authorisations](#billing-requests-bank-authorisations) for a particular 15 | # country or purpose. 16 | # 17 | # Not all institutions support both Payment Initiation (PIS) and Account 18 | # Information (AIS) services. 19 | class Institution 20 | attr_reader :autocompletes_collect_bank_account, :country_code, :icon_url, :id, :limits, :logo_url, :name, :status 21 | 22 | # Initialize a institution resource instance 23 | # @param object [Hash] an object returned from the API 24 | def initialize(object, response = nil) 25 | @object = object 26 | 27 | @autocompletes_collect_bank_account = object['autocompletes_collect_bank_account'] 28 | @country_code = object['country_code'] 29 | @icon_url = object['icon_url'] 30 | @id = object['id'] 31 | @limits = object['limits'] 32 | @logo_url = object['logo_url'] 33 | @name = object['name'] 34 | @status = object['status'] 35 | @response = response 36 | end 37 | 38 | def api_response 39 | ApiResponse.new(@response) 40 | end 41 | 42 | # Provides the institution resource as a hash of all its readable attributes 43 | def to_h 44 | @object 45 | end 46 | end 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /lib/gocardless_pro/services/billing_request_with_actions_service.rb: -------------------------------------------------------------------------------- 1 | require_relative './base_service' 2 | 3 | # encoding: utf-8 4 | # 5 | # This client is automatically generated from a template and JSON schema definition. 6 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 7 | # 8 | 9 | module GoCardlessPro 10 | module Services 11 | # Service for making requests to the BillingRequestWithAction endpoints 12 | class BillingRequestWithActionsService < BaseService 13 | # Creates a billing request and completes any specified actions in a single 14 | # request. 15 | # This endpoint allows you to create a billing request and immediately complete 16 | # actions 17 | # such as collecting customer details, bank account details, or other required 18 | # actions. 19 | # Example URL: /billing_requests/create_with_actions 20 | # @param options [Hash] parameters as a hash, under a params key. 21 | def create_with_actions(options = {}) 22 | path = '/billing_requests/create_with_actions' 23 | 24 | params = options.delete(:params) || {} 25 | options[:params] = {} 26 | options[:params][envelope_key] = params 27 | 28 | options[:retry_failures] = true 29 | 30 | response = make_request(:post, path, options) 31 | 32 | return if response.body.nil? 33 | 34 | Resources::BillingRequestWithAction.new(unenvelope_body(response.body), response) 35 | end 36 | 37 | private 38 | 39 | # Unenvelope the response of the body using the service's `envelope_key` 40 | # 41 | # @param body [Hash] 42 | def unenvelope_body(body) 43 | body[envelope_key] || body['data'] 44 | end 45 | 46 | # return the key which API responses will envelope data under 47 | def envelope_key 48 | 'billing_request_with_actions' 49 | end 50 | end 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /lib/gocardless_pro/resources/transferred_mandate.rb: -------------------------------------------------------------------------------- 1 | # 2 | # This client is automatically generated from a template and JSON schema definition. 3 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 4 | # 5 | 6 | require 'uri' 7 | 8 | module GoCardlessPro 9 | # A module containing classes for each of the resources in the GC Api 10 | module Resources 11 | # Represents an instance of a transferred_mandate resource returned from the API 12 | 13 | # Mandates that have been transferred using Current Account Switch Service 14 | class TransferredMandate 15 | attr_reader :encrypted_customer_bank_details, :encrypted_decryption_key, :public_key_id 16 | 17 | # Initialize a transferred_mandate resource instance 18 | # @param object [Hash] an object returned from the API 19 | def initialize(object, response = nil) 20 | @object = object 21 | 22 | @encrypted_customer_bank_details = object['encrypted_customer_bank_details'] 23 | @encrypted_decryption_key = object['encrypted_decryption_key'] 24 | @links = object['links'] 25 | @public_key_id = object['public_key_id'] 26 | @response = response 27 | end 28 | 29 | def api_response 30 | ApiResponse.new(@response) 31 | end 32 | 33 | # Return the links that the resource has 34 | def links 35 | @transferred_mandate_links ||= Links.new(@links) 36 | end 37 | 38 | # Provides the transferred_mandate resource as a hash of all its readable attributes 39 | def to_h 40 | @object 41 | end 42 | 43 | class Links 44 | def initialize(links) 45 | @links = links || {} 46 | end 47 | 48 | def customer_bank_account 49 | @links['customer_bank_account'] 50 | end 51 | 52 | def mandate 53 | @links['mandate'] 54 | end 55 | end 56 | end 57 | end 58 | end 59 | -------------------------------------------------------------------------------- /lib/gocardless_pro/services/logos_service.rb: -------------------------------------------------------------------------------- 1 | require_relative './base_service' 2 | 3 | # encoding: utf-8 4 | # 5 | # This client is automatically generated from a template and JSON schema definition. 6 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 7 | # 8 | 9 | module GoCardlessPro 10 | module Services 11 | # Service for making requests to the Logo endpoints 12 | class LogosService < BaseService 13 | # Creates a new logo associated with a creditor. If a creditor already has a 14 | # logo, this will update the existing logo linked to the creditor. 15 | # 16 | # We support JPG and PNG formats. Your logo will be scaled to a maximum of 300px 17 | # by 40px. For more guidance on how to upload logos that will look 18 | # great across your customer payment page and notification emails see 19 | # [here](https://developer.gocardless.com/gc-embed/setting-up-branding#tips_for_uploading_your_logo). 20 | # Example URL: /branding/logos 21 | # @param options [Hash] parameters as a hash, under a params key. 22 | def create_for_creditor(options = {}) 23 | path = '/branding/logos' 24 | 25 | params = options.delete(:params) || {} 26 | options[:params] = {} 27 | options[:params][envelope_key] = params 28 | 29 | options[:retry_failures] = true 30 | 31 | response = make_request(:post, path, options) 32 | 33 | return if response.body.nil? 34 | 35 | Resources::Logo.new(unenvelope_body(response.body), response) 36 | end 37 | 38 | private 39 | 40 | # Unenvelope the response of the body using the service's `envelope_key` 41 | # 42 | # @param body [Hash] 43 | def unenvelope_body(body) 44 | body[envelope_key] || body['data'] 45 | end 46 | 47 | # return the key which API responses will envelope data under 48 | def envelope_key 49 | 'logos' 50 | end 51 | end 52 | end 53 | end 54 | -------------------------------------------------------------------------------- /lib/gocardless_pro/resources/webhook.rb: -------------------------------------------------------------------------------- 1 | # 2 | # This client is automatically generated from a template and JSON schema definition. 3 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 4 | # 5 | 6 | require 'uri' 7 | 8 | module GoCardlessPro 9 | # A module containing classes for each of the resources in the GC Api 10 | module Resources 11 | # Represents an instance of a webhook resource returned from the API 12 | 13 | # Basic description of a webhook 14 | class Webhook 15 | attr_reader :created_at, :id, :is_test, :request_body, :request_headers, :response_body, 16 | :response_body_truncated, :response_code, :response_headers, :response_headers_content_truncated, :response_headers_count_truncated, :successful, :url 17 | 18 | # Initialize a webhook resource instance 19 | # @param object [Hash] an object returned from the API 20 | def initialize(object, response = nil) 21 | @object = object 22 | 23 | @created_at = object['created_at'] 24 | @id = object['id'] 25 | @is_test = object['is_test'] 26 | @request_body = object['request_body'] 27 | @request_headers = object['request_headers'] 28 | @response_body = object['response_body'] 29 | @response_body_truncated = object['response_body_truncated'] 30 | @response_code = object['response_code'] 31 | @response_headers = object['response_headers'] 32 | @response_headers_content_truncated = object['response_headers_content_truncated'] 33 | @response_headers_count_truncated = object['response_headers_count_truncated'] 34 | @successful = object['successful'] 35 | @url = object['url'] 36 | @response = response 37 | end 38 | 39 | def api_response 40 | ApiResponse.new(@response) 41 | end 42 | 43 | # Provides the webhook resource as a hash of all its readable attributes 44 | def to_h 45 | @object 46 | end 47 | end 48 | end 49 | end 50 | -------------------------------------------------------------------------------- /spec/error_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe GoCardlessPro::Error do 4 | subject(:error) { described_class.new(api_error) } 5 | 6 | let(:api_error) do 7 | { 8 | 'documentation_url' => 'https://developer.gocardless.com/pro#validation_failed', 9 | 'message' => 'Validation failed', 10 | 'type' => 'validation_failed', 11 | 'code' => 422, 12 | 'request_id' => 'dd50eaaf-8213-48fe-90d6-5466872efbc4', 13 | 'errors' => [ 14 | { 15 | 'message' => 'must be a number', 16 | 'field' => 'branch_code' 17 | }, { 18 | 'message' => 'is the wrong length (should be 8 characters)', 19 | 'field' => 'branch_code' 20 | } 21 | ] 22 | } 23 | end 24 | 25 | specify do 26 | expect(error.documentation_url).to eq('https://developer.gocardless.com/pro#validation_failed') 27 | end 28 | 29 | specify { expect(error.message).to eq('Validation failed') } 30 | specify do 31 | expect(error.to_s) 32 | .to eq('branch_code must be a number, '\ 33 | 'branch_code is the wrong length (should be 8 characters)') 34 | end 35 | specify { expect(error.type).to eq('validation_failed') } 36 | specify { expect(error.code).to eq(422) } 37 | specify { expect(error.request_id).to eq('dd50eaaf-8213-48fe-90d6-5466872efbc4') } 38 | specify do 39 | expect(error.errors).to eq([ 40 | { 41 | 'message' => 'must be a number', 42 | 'field' => 'branch_code' 43 | }, { 44 | 'message' => 'is the wrong length (should be 8 characters)', 45 | 'field' => 'branch_code' 46 | } 47 | ]) 48 | end 49 | 50 | context 'when initializing an error with a string' do 51 | specify { expect { described_class.new('FOO') }.to raise_error(ArgumentError) } 52 | end 53 | end 54 | -------------------------------------------------------------------------------- /lib/gocardless_pro/resources/balance.rb: -------------------------------------------------------------------------------- 1 | # 2 | # This client is automatically generated from a template and JSON schema definition. 3 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 4 | # 5 | 6 | require 'uri' 7 | 8 | module GoCardlessPro 9 | # A module containing classes for each of the resources in the GC Api 10 | module Resources 11 | # Represents an instance of a balance resource returned from the API 12 | 13 | # Returns the balances for a creditor. These balances are the same as what’s 14 | # shown in the dashboard with one exception (mentioned below under 15 | # balance_type). 16 | # 17 | # These balances will typically be 3-5 minutes old. The balance amounts 18 | # likely won’t match what’s shown in the dashboard as the dashboard balances 19 | # are updated much less frequently (once per day). 20 | class Balance 21 | attr_reader :amount, :balance_type, :currency, :last_updated_at 22 | 23 | # Initialize a balance resource instance 24 | # @param object [Hash] an object returned from the API 25 | def initialize(object, response = nil) 26 | @object = object 27 | 28 | @amount = object['amount'] 29 | @balance_type = object['balance_type'] 30 | @currency = object['currency'] 31 | @last_updated_at = object['last_updated_at'] 32 | @links = object['links'] 33 | @response = response 34 | end 35 | 36 | def api_response 37 | ApiResponse.new(@response) 38 | end 39 | 40 | # Return the links that the resource has 41 | def links 42 | @balance_links ||= Links.new(@links) 43 | end 44 | 45 | # Provides the balance resource as a hash of all its readable attributes 46 | def to_h 47 | @object 48 | end 49 | 50 | class Links 51 | def initialize(links) 52 | @links = links || {} 53 | end 54 | 55 | def creditor 56 | @links['creditor'] 57 | end 58 | end 59 | end 60 | end 61 | end 62 | -------------------------------------------------------------------------------- /lib/gocardless_pro/services/balances_service.rb: -------------------------------------------------------------------------------- 1 | require_relative './base_service' 2 | 3 | # encoding: utf-8 4 | # 5 | # This client is automatically generated from a template and JSON schema definition. 6 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 7 | # 8 | 9 | module GoCardlessPro 10 | module Services 11 | # Service for making requests to the Balance endpoints 12 | class BalancesService < BaseService 13 | # Returns a [cursor-paginated](#api-usage-cursor-pagination) list of balances 14 | # for a given creditor. This endpoint is rate limited to 60 requests per minute. 15 | # Example URL: /balances 16 | # @param options [Hash] parameters as a hash, under a params key. 17 | def list(options = {}) 18 | path = '/balances' 19 | 20 | options[:retry_failures] = true 21 | 22 | response = make_request(:get, path, options) 23 | 24 | ListResponse.new( 25 | response: response, 26 | unenveloped_body: unenvelope_body(response.body), 27 | resource_class: Resources::Balance 28 | ) 29 | end 30 | 31 | # Get a lazily enumerated list of all the items returned. This is similar to the `list` method but will paginate for you automatically. 32 | # 33 | # @param options [Hash] parameters as a hash. If the request is a GET, these will be converted to query parameters. 34 | # Otherwise they will be the body of the request. 35 | def all(options = {}) 36 | Paginator.new( 37 | service: self, 38 | options: options 39 | ).enumerator 40 | end 41 | 42 | private 43 | 44 | # Unenvelope the response of the body using the service's `envelope_key` 45 | # 46 | # @param body [Hash] 47 | def unenvelope_body(body) 48 | body[envelope_key] || body['data'] 49 | end 50 | 51 | # return the key which API responses will envelope data under 52 | def envelope_key 53 | 'balances' 54 | end 55 | end 56 | end 57 | end 58 | -------------------------------------------------------------------------------- /lib/gocardless_pro/resources/negative_balance_limit.rb: -------------------------------------------------------------------------------- 1 | # 2 | # This client is automatically generated from a template and JSON schema definition. 3 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 4 | # 5 | 6 | require 'uri' 7 | 8 | module GoCardlessPro 9 | # A module containing classes for each of the resources in the GC Api 10 | module Resources 11 | # Represents an instance of a negative_balance_limit resource returned from the API 12 | 13 | # The negative balance limit is a threshold for the creditor balance beyond 14 | # which refunds are not permitted. The default limit is zero — refunds are 15 | # not permitted if the creditor has a negative balance. The limit can be 16 | # changed on a per-creditor basis. 17 | # 18 | class NegativeBalanceLimit 19 | attr_reader :balance_limit, :created_at, :currency, :id 20 | 21 | # Initialize a negative_balance_limit resource instance 22 | # @param object [Hash] an object returned from the API 23 | def initialize(object, response = nil) 24 | @object = object 25 | 26 | @balance_limit = object['balance_limit'] 27 | @created_at = object['created_at'] 28 | @currency = object['currency'] 29 | @id = object['id'] 30 | @links = object['links'] 31 | @response = response 32 | end 33 | 34 | def api_response 35 | ApiResponse.new(@response) 36 | end 37 | 38 | # Return the links that the resource has 39 | def links 40 | @negative_balance_limit_links ||= Links.new(@links) 41 | end 42 | 43 | # Provides the negative_balance_limit resource as a hash of all its readable attributes 44 | def to_h 45 | @object 46 | end 47 | 48 | class Links 49 | def initialize(links) 50 | @links = links || {} 51 | end 52 | 53 | def creator_user 54 | @links['creator_user'] 55 | end 56 | 57 | def creditor 58 | @links['creditor'] 59 | end 60 | end 61 | end 62 | end 63 | end 64 | -------------------------------------------------------------------------------- /lib/gocardless_pro/services/currency_exchange_rates_service.rb: -------------------------------------------------------------------------------- 1 | require_relative './base_service' 2 | 3 | # encoding: utf-8 4 | # 5 | # This client is automatically generated from a template and JSON schema definition. 6 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 7 | # 8 | 9 | module GoCardlessPro 10 | module Services 11 | # Service for making requests to the CurrencyExchangeRate endpoints 12 | class CurrencyExchangeRatesService < BaseService 13 | # Returns a [cursor-paginated](#api-usage-cursor-pagination) list of all 14 | # exchange rates. 15 | # Example URL: /currency_exchange_rates 16 | # @param options [Hash] parameters as a hash, under a params key. 17 | def list(options = {}) 18 | path = '/currency_exchange_rates' 19 | 20 | options[:retry_failures] = true 21 | 22 | response = make_request(:get, path, options) 23 | 24 | ListResponse.new( 25 | response: response, 26 | unenveloped_body: unenvelope_body(response.body), 27 | resource_class: Resources::CurrencyExchangeRate 28 | ) 29 | end 30 | 31 | # Get a lazily enumerated list of all the items returned. This is similar to the `list` method but will paginate for you automatically. 32 | # 33 | # @param options [Hash] parameters as a hash. If the request is a GET, these will be converted to query parameters. 34 | # Otherwise they will be the body of the request. 35 | def all(options = {}) 36 | Paginator.new( 37 | service: self, 38 | options: options 39 | ).enumerator 40 | end 41 | 42 | private 43 | 44 | # Unenvelope the response of the body using the service's `envelope_key` 45 | # 46 | # @param body [Hash] 47 | def unenvelope_body(body) 48 | body[envelope_key] || body['data'] 49 | end 50 | 51 | # return the key which API responses will envelope data under 52 | def envelope_key 53 | 'currency_exchange_rates' 54 | end 55 | end 56 | end 57 | end 58 | -------------------------------------------------------------------------------- /lib/gocardless_pro/services/negative_balance_limits_service.rb: -------------------------------------------------------------------------------- 1 | require_relative './base_service' 2 | 3 | # encoding: utf-8 4 | # 5 | # This client is automatically generated from a template and JSON schema definition. 6 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 7 | # 8 | 9 | module GoCardlessPro 10 | module Services 11 | # Service for making requests to the NegativeBalanceLimit endpoints 12 | class NegativeBalanceLimitsService < BaseService 13 | # Returns a [cursor-paginated](#api-usage-cursor-pagination) list of negative 14 | # balance limits. 15 | # Example URL: /negative_balance_limits 16 | # @param options [Hash] parameters as a hash, under a params key. 17 | def list(options = {}) 18 | path = '/negative_balance_limits' 19 | 20 | options[:retry_failures] = true 21 | 22 | response = make_request(:get, path, options) 23 | 24 | ListResponse.new( 25 | response: response, 26 | unenveloped_body: unenvelope_body(response.body), 27 | resource_class: Resources::NegativeBalanceLimit 28 | ) 29 | end 30 | 31 | # Get a lazily enumerated list of all the items returned. This is similar to the `list` method but will paginate for you automatically. 32 | # 33 | # @param options [Hash] parameters as a hash. If the request is a GET, these will be converted to query parameters. 34 | # Otherwise they will be the body of the request. 35 | def all(options = {}) 36 | Paginator.new( 37 | service: self, 38 | options: options 39 | ).enumerator 40 | end 41 | 42 | private 43 | 44 | # Unenvelope the response of the body using the service's `envelope_key` 45 | # 46 | # @param body [Hash] 47 | def unenvelope_body(body) 48 | body[envelope_key] || body['data'] 49 | end 50 | 51 | # return the key which API responses will envelope data under 52 | def envelope_key 53 | 'negative_balance_limits' 54 | end 55 | end 56 | end 57 | end 58 | -------------------------------------------------------------------------------- /spec/resources/scenario_simulator_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe GoCardlessPro::Resources::ScenarioSimulator do 4 | let(:client) do 5 | GoCardlessPro::Client.new( 6 | access_token: 'SECRET_TOKEN' 7 | ) 8 | end 9 | 10 | let(:response_headers) { { 'Content-Type' => 'application/json' } } 11 | 12 | describe '#run' do 13 | subject(:post_response) { client.scenario_simulators.run(resource_id) } 14 | 15 | let(:resource_id) { 'ABC123' } 16 | 17 | let!(:stub) do 18 | # /scenario_simulators/%v/actions/run 19 | stub_url = '/scenario_simulators/:identity/actions/run'.gsub(':identity', resource_id) 20 | stub_request(:post, /.*api.gocardless.com#{stub_url}/).to_return( 21 | body: { 22 | 'scenario_simulators' => { 23 | 24 | 'id' => 'id-input' 25 | } 26 | }.to_json, 27 | 28 | headers: response_headers 29 | ) 30 | end 31 | 32 | it 'wraps the response and calls the right endpoint' do 33 | expect(post_response).to be_a(GoCardlessPro::Resources::ScenarioSimulator) 34 | 35 | expect(stub).to have_been_requested 36 | end 37 | 38 | context 'when the request needs a body and custom header' do 39 | let(:body) { { foo: 'bar' } } 40 | let(:headers) { { 'Foo' => 'Bar' } } 41 | subject(:post_response) { client.scenario_simulators.run(resource_id, body, headers) } 42 | 43 | let(:resource_id) { 'ABC123' } 44 | 45 | let!(:stub) do 46 | # /scenario_simulators/%v/actions/run 47 | stub_url = '/scenario_simulators/:identity/actions/run'.gsub(':identity', resource_id) 48 | stub_request(:post, /.*api.gocardless.com#{stub_url}/) 49 | .with( 50 | body: { foo: 'bar' }, 51 | headers: { 'Foo' => 'Bar' } 52 | ).to_return( 53 | body: { 54 | 'scenario_simulators' => { 55 | 56 | 'id' => 'id-input' 57 | } 58 | }.to_json, 59 | headers: response_headers 60 | ) 61 | end 62 | end 63 | end 64 | end 65 | -------------------------------------------------------------------------------- /lib/gocardless_pro/services/customer_notifications_service.rb: -------------------------------------------------------------------------------- 1 | require_relative './base_service' 2 | 3 | # encoding: utf-8 4 | # 5 | # This client is automatically generated from a template and JSON schema definition. 6 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 7 | # 8 | 9 | module GoCardlessPro 10 | module Services 11 | # Service for making requests to the CustomerNotification endpoints 12 | class CustomerNotificationsService < BaseService 13 | # "Handling" a notification means that you have sent the notification yourself 14 | # (and 15 | # don't want GoCardless to send it). 16 | # If the notification has already been actioned, or the deadline to notify has 17 | # passed, 18 | # this endpoint will return an `already_actioned` error and you should not take 19 | # further action. This endpoint takes no additional parameters. 20 | # 21 | # Example URL: /customer_notifications/:identity/actions/handle 22 | # 23 | # @param identity # The id of the notification. 24 | # @param options [Hash] parameters as a hash, under a params key. 25 | def handle(identity, options = {}) 26 | path = sub_url('/customer_notifications/:identity/actions/handle', { 27 | 'identity' => identity 28 | }) 29 | 30 | params = options.delete(:params) || {} 31 | options[:params] = {} 32 | options[:params]['data'] = params 33 | 34 | options[:retry_failures] = false 35 | 36 | response = make_request(:post, path, options) 37 | 38 | return if response.body.nil? 39 | 40 | Resources::CustomerNotification.new(unenvelope_body(response.body), response) 41 | end 42 | 43 | private 44 | 45 | # Unenvelope the response of the body using the service's `envelope_key` 46 | # 47 | # @param body [Hash] 48 | def unenvelope_body(body) 49 | body[envelope_key] || body['data'] 50 | end 51 | 52 | # return the key which API responses will envelope data under 53 | def envelope_key 54 | 'customer_notifications' 55 | end 56 | end 57 | end 58 | end 59 | -------------------------------------------------------------------------------- /lib/gocardless_pro/resources/refund.rb: -------------------------------------------------------------------------------- 1 | # 2 | # This client is automatically generated from a template and JSON schema definition. 3 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 4 | # 5 | 6 | require 'uri' 7 | 8 | module GoCardlessPro 9 | # A module containing classes for each of the resources in the GC Api 10 | module Resources 11 | # Represents an instance of a refund resource returned from the API 12 | 13 | # Refund objects represent (partial) refunds of a 14 | # [payment](#core-endpoints-payments) back to the 15 | # [customer](#core-endpoints-customers). 16 | # 17 | # GoCardless will notify you via a [webhook](#appendix-webhooks) whenever a 18 | # refund is created, and will update the `amount_refunded` property of the 19 | # payment. 20 | class Refund 21 | attr_reader :amount, :created_at, :currency, :fx, :id, :metadata, :reference, :status 22 | 23 | # Initialize a refund resource instance 24 | # @param object [Hash] an object returned from the API 25 | def initialize(object, response = nil) 26 | @object = object 27 | 28 | @amount = object['amount'] 29 | @created_at = object['created_at'] 30 | @currency = object['currency'] 31 | @fx = object['fx'] 32 | @id = object['id'] 33 | @links = object['links'] 34 | @metadata = object['metadata'] 35 | @reference = object['reference'] 36 | @status = object['status'] 37 | @response = response 38 | end 39 | 40 | def api_response 41 | ApiResponse.new(@response) 42 | end 43 | 44 | # Return the links that the resource has 45 | def links 46 | @refund_links ||= Links.new(@links) 47 | end 48 | 49 | # Provides the refund resource as a hash of all its readable attributes 50 | def to_h 51 | @object 52 | end 53 | 54 | class Links 55 | def initialize(links) 56 | @links = links || {} 57 | end 58 | 59 | def mandate 60 | @links['mandate'] 61 | end 62 | 63 | def payment 64 | @links['payment'] 65 | end 66 | end 67 | end 68 | end 69 | end 70 | -------------------------------------------------------------------------------- /lib/gocardless_pro/services/payout_items_service.rb: -------------------------------------------------------------------------------- 1 | require_relative './base_service' 2 | 3 | # encoding: utf-8 4 | # 5 | # This client is automatically generated from a template and JSON schema definition. 6 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 7 | # 8 | 9 | module GoCardlessPro 10 | module Services 11 | # Service for making requests to the PayoutItem endpoints 12 | class PayoutItemsService < BaseService 13 | # Returns a [cursor-paginated](#api-usage-cursor-pagination) list of items in 14 | # the payout. 15 | # 16 | # This endpoint only serves requests for payouts created in the last 6 17 | # months. Requests for older payouts will return an HTTP status 410 18 | # Gone. 19 | # 20 | # Example URL: /payout_items 21 | # @param options [Hash] parameters as a hash, under a params key. 22 | def list(options = {}) 23 | path = '/payout_items' 24 | 25 | options[:retry_failures] = true 26 | 27 | response = make_request(:get, path, options) 28 | 29 | ListResponse.new( 30 | response: response, 31 | unenveloped_body: unenvelope_body(response.body), 32 | resource_class: Resources::PayoutItem 33 | ) 34 | end 35 | 36 | # Get a lazily enumerated list of all the items returned. This is similar to the `list` method but will paginate for you automatically. 37 | # 38 | # @param options [Hash] parameters as a hash. If the request is a GET, these will be converted to query parameters. 39 | # Otherwise they will be the body of the request. 40 | def all(options = {}) 41 | Paginator.new( 42 | service: self, 43 | options: options 44 | ).enumerator 45 | end 46 | 47 | private 48 | 49 | # Unenvelope the response of the body using the service's `envelope_key` 50 | # 51 | # @param body [Hash] 52 | def unenvelope_body(body) 53 | body[envelope_key] || body['data'] 54 | end 55 | 56 | # return the key which API responses will envelope data under 57 | def envelope_key 58 | 'payout_items' 59 | end 60 | end 61 | end 62 | end 63 | -------------------------------------------------------------------------------- /lib/gocardless_pro/middlewares/raise_gocardless_errors.rb: -------------------------------------------------------------------------------- 1 | module GoCardlessPro 2 | module Middlewares 3 | class RaiseGoCardlessErrors < Faraday::Middleware 4 | API_ERROR_STATUSES = 501..599 5 | CLIENT_ERROR_STATUSES = 400..500 6 | API_STATUS_NO_CONTENT = 204 7 | 8 | def on_complete(env) 9 | if !(env.status == API_STATUS_NO_CONTENT || json?(env)) || API_ERROR_STATUSES.include?(env.status) 10 | raise ApiError, generate_error_data(env) 11 | end 12 | 13 | return unless CLIENT_ERROR_STATUSES.include?(env.status) 14 | 15 | json_body ||= JSON.parse(env.body) unless env.body.empty? 16 | error_type = json_body['error']['type'] 17 | 18 | error_class = error_class_for_status(env.status) || error_class_for_type(error_type) 19 | 20 | raise(error_class, json_body['error']) 21 | end 22 | 23 | private 24 | 25 | def error_class_for_status(code) 26 | { 27 | 401 => GoCardlessPro::AuthenticationError, 28 | 403 => GoCardlessPro::PermissionError, 29 | 429 => GoCardlessPro::RateLimitError 30 | }.fetch(code, nil) 31 | end 32 | 33 | def error_class_for_type(type) 34 | { 35 | validation_failed: GoCardlessPro::ValidationError, 36 | gocardless: GoCardlessPro::GoCardlessError, 37 | invalid_api_usage: GoCardlessPro::InvalidApiUsageError, 38 | invalid_state: GoCardlessPro::InvalidStateError 39 | }.fetch(type.to_sym) 40 | end 41 | 42 | def generate_error_data(env) 43 | { 44 | 'message' => "Something went wrong with this request\n" \ 45 | "code: #{env.status}\n" \ 46 | "headers: #{env.response_headers}\n" \ 47 | "body: #{env.body}", 48 | 'code' => env.status 49 | } 50 | end 51 | 52 | def json?(env) 53 | content_type = env.response_headers['Content-Type'] || 54 | env.response_headers['content-type'] || '' 55 | 56 | content_type.include?('application/json') 57 | end 58 | end 59 | end 60 | end 61 | 62 | Faraday::Response.register_middleware raise_gocardless_errors: GoCardlessPro::Middlewares::RaiseGoCardlessErrors 63 | -------------------------------------------------------------------------------- /lib/gocardless_pro/resources/scheme_identifier.rb: -------------------------------------------------------------------------------- 1 | # 2 | # This client is automatically generated from a template and JSON schema definition. 3 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 4 | # 5 | 6 | require 'uri' 7 | 8 | module GoCardlessPro 9 | # A module containing classes for each of the resources in the GC Api 10 | module Resources 11 | # Represents an instance of a scheme_identifier resource returned from the API 12 | 13 | # This represents a scheme identifier (e.g. a SUN in Bacs or a CID in SEPA). 14 | # Scheme identifiers are used to specify the beneficiary name that appears 15 | # on customers' bank statements. 16 | # 17 | class SchemeIdentifier 18 | attr_reader :address_line1, :address_line2, :address_line3, :can_specify_mandate_reference, :city, :country_code, 19 | :created_at, :currency, :email, :id, :minimum_advance_notice, :name, :phone_number, :postal_code, :reference, :region, :scheme, :status 20 | 21 | # Initialize a scheme_identifier resource instance 22 | # @param object [Hash] an object returned from the API 23 | def initialize(object, response = nil) 24 | @object = object 25 | 26 | @address_line1 = object['address_line1'] 27 | @address_line2 = object['address_line2'] 28 | @address_line3 = object['address_line3'] 29 | @can_specify_mandate_reference = object['can_specify_mandate_reference'] 30 | @city = object['city'] 31 | @country_code = object['country_code'] 32 | @created_at = object['created_at'] 33 | @currency = object['currency'] 34 | @email = object['email'] 35 | @id = object['id'] 36 | @minimum_advance_notice = object['minimum_advance_notice'] 37 | @name = object['name'] 38 | @phone_number = object['phone_number'] 39 | @postal_code = object['postal_code'] 40 | @reference = object['reference'] 41 | @region = object['region'] 42 | @scheme = object['scheme'] 43 | @status = object['status'] 44 | @response = response 45 | end 46 | 47 | def api_response 48 | ApiResponse.new(@response) 49 | end 50 | 51 | # Provides the scheme_identifier resource as a hash of all its readable attributes 52 | def to_h 53 | @object 54 | end 55 | end 56 | end 57 | end 58 | -------------------------------------------------------------------------------- /lib/gocardless_pro/resources/customer.rb: -------------------------------------------------------------------------------- 1 | # 2 | # This client is automatically generated from a template and JSON schema definition. 3 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 4 | # 5 | 6 | require 'uri' 7 | 8 | module GoCardlessPro 9 | # A module containing classes for each of the resources in the GC Api 10 | module Resources 11 | # Represents an instance of a customer resource returned from the API 12 | 13 | # Customer objects hold the contact details for a customer. A customer can 14 | # have several [customer bank 15 | # accounts](#core-endpoints-customer-bank-accounts), which in turn can have 16 | # several Direct Debit [mandates](#core-endpoints-mandates). 17 | class Customer 18 | attr_reader :address_line1, :address_line2, :address_line3, :city, :company_name, :country_code, :created_at, 19 | :danish_identity_number, :email, :family_name, :given_name, :id, :language, :metadata, :phone_number, :postal_code, :region, :swedish_identity_number 20 | 21 | # Initialize a customer resource instance 22 | # @param object [Hash] an object returned from the API 23 | def initialize(object, response = nil) 24 | @object = object 25 | 26 | @address_line1 = object['address_line1'] 27 | @address_line2 = object['address_line2'] 28 | @address_line3 = object['address_line3'] 29 | @city = object['city'] 30 | @company_name = object['company_name'] 31 | @country_code = object['country_code'] 32 | @created_at = object['created_at'] 33 | @danish_identity_number = object['danish_identity_number'] 34 | @email = object['email'] 35 | @family_name = object['family_name'] 36 | @given_name = object['given_name'] 37 | @id = object['id'] 38 | @language = object['language'] 39 | @metadata = object['metadata'] 40 | @phone_number = object['phone_number'] 41 | @postal_code = object['postal_code'] 42 | @region = object['region'] 43 | @swedish_identity_number = object['swedish_identity_number'] 44 | @response = response 45 | end 46 | 47 | def api_response 48 | ApiResponse.new(@response) 49 | end 50 | 51 | # Provides the customer resource as a hash of all its readable attributes 52 | def to_h 53 | @object 54 | end 55 | end 56 | end 57 | end 58 | -------------------------------------------------------------------------------- /lib/gocardless_pro/api_service.rb: -------------------------------------------------------------------------------- 1 | # 2 | # This client is automatically generated from a template and JSON schema definition. 3 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 4 | # 5 | 6 | require 'uri' 7 | require 'base64' 8 | 9 | module GoCardlessPro 10 | # GoCardless API 11 | class ApiService 12 | attr_reader :on_idempotency_conflict 13 | 14 | # Initialize an APIService 15 | # 16 | # @param url [String] the URL to make requests to 17 | # @param key [String] the API Key ID to use 18 | # @param secret [String] the API key secret to use 19 | # @param options [Hash] additional options to use when creating the service 20 | def initialize(url, token, options = {}) 21 | @url = url 22 | root_url, @path_prefix = unpack_url(url) 23 | http_adapter = options[:http_adapter] || [:net_http] 24 | connection_options = options.fetch(:connection_options, {}) 25 | 26 | @connection = Faraday.new(root_url, connection_options) do |faraday| 27 | faraday.response :raise_gocardless_errors 28 | 29 | faraday.adapter(*http_adapter) 30 | end 31 | 32 | @headers = options[:default_headers] || {} 33 | @headers['Authorization'] = "Bearer #{token}" 34 | @on_idempotency_conflict = options[:on_idempotency_conflict] || :fetch 35 | 36 | return if %i[fetch raise].include?(@on_idempotency_conflict) 37 | 38 | raise ArgumentError, 'Unknown mode for :on_idempotency_conflict' 39 | end 40 | 41 | # Make a request to the API 42 | # 43 | # @param method [Symbol] the method to use to make the request 44 | # @param path [String] the URL (without the base domain) to make the request to 45 | # @param options [Hash] the options hash 46 | def make_request(method, path, options = {}) 47 | raise ArgumentError, 'options must be a hash' unless options.is_a?(Hash) 48 | 49 | options[:headers] ||= {} 50 | options[:headers] = @headers.merge(options[:headers]) 51 | Request.new(@connection, method, @path_prefix + path, options).request 52 | end 53 | 54 | # inspect the API Service 55 | def inspect 56 | url = URI.parse(@url) 57 | url.password = 'REDACTED' unless url.password.nil? 58 | "#" 59 | end 60 | alias to_s inspect 61 | 62 | private 63 | 64 | def unpack_url(url) 65 | path = URI.parse(url).path 66 | [URI.join(url).to_s, path == '/' ? '' : path] 67 | end 68 | end 69 | end 70 | -------------------------------------------------------------------------------- /lib/gocardless_pro/resources/verification_detail.rb: -------------------------------------------------------------------------------- 1 | # 2 | # This client is automatically generated from a template and JSON schema definition. 3 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 4 | # 5 | 6 | require 'uri' 7 | 8 | module GoCardlessPro 9 | # A module containing classes for each of the resources in the GC Api 10 | module Resources 11 | # Represents an instance of a verification_detail resource returned from the API 12 | 13 | # Verification details represent any information needed by GoCardless to 14 | # verify a creditor. 15 | # 16 | #

Restricted: 17 | # These endpoints are restricted to customers who want to collect their 18 | # merchant's 19 | # verification details and pass them to GoCardless via our API. Please 20 | # [get in 21 | # touch](mailto:help@gocardless.com) if you wish to enable this feature on 22 | # your 23 | # account.

24 | class VerificationDetail 25 | attr_reader :address_line1, :address_line2, :address_line3, :city, :company_number, :description, :directors, 26 | :name, :postal_code 27 | 28 | # Initialize a verification_detail resource instance 29 | # @param object [Hash] an object returned from the API 30 | def initialize(object, response = nil) 31 | @object = object 32 | 33 | @address_line1 = object['address_line1'] 34 | @address_line2 = object['address_line2'] 35 | @address_line3 = object['address_line3'] 36 | @city = object['city'] 37 | @company_number = object['company_number'] 38 | @description = object['description'] 39 | @directors = object['directors'] 40 | @links = object['links'] 41 | @name = object['name'] 42 | @postal_code = object['postal_code'] 43 | @response = response 44 | end 45 | 46 | def api_response 47 | ApiResponse.new(@response) 48 | end 49 | 50 | # Return the links that the resource has 51 | def links 52 | @verification_detail_links ||= Links.new(@links) 53 | end 54 | 55 | # Provides the verification_detail resource as a hash of all its readable attributes 56 | def to_h 57 | @object 58 | end 59 | 60 | class Links 61 | def initialize(links) 62 | @links = links || {} 63 | end 64 | 65 | def creditor 66 | @links['creditor'] 67 | end 68 | end 69 | end 70 | end 71 | end 72 | -------------------------------------------------------------------------------- /spec/services/scenario_simulators_service_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe GoCardlessPro::Services::ScenarioSimulatorsService do 4 | let(:client) do 5 | GoCardlessPro::Client.new( 6 | access_token: 'SECRET_TOKEN' 7 | ) 8 | end 9 | 10 | let(:response_headers) { { 'Content-Type' => 'application/json' } } 11 | 12 | describe '#run' do 13 | subject(:post_response) { client.scenario_simulators.run(resource_id) } 14 | 15 | let(:resource_id) { 'ABC123' } 16 | 17 | let!(:stub) do 18 | # /scenario_simulators/%v/actions/run 19 | stub_url = '/scenario_simulators/:identity/actions/run'.gsub(':identity', resource_id) 20 | stub_request(:post, /.*api.gocardless.com#{stub_url}/).to_return( 21 | body: { 22 | 'scenario_simulators' => { 23 | 24 | 'id' => 'id-input' 25 | } 26 | }.to_json, 27 | 28 | headers: response_headers 29 | ) 30 | end 31 | 32 | it 'wraps the response and calls the right endpoint' do 33 | expect(post_response).to be_a(GoCardlessPro::Resources::ScenarioSimulator) 34 | 35 | expect(stub).to have_been_requested 36 | end 37 | 38 | describe 'retry behaviour' do 39 | it "doesn't retry errors" do 40 | stub_url = '/scenario_simulators/:identity/actions/run'.gsub(':identity', resource_id) 41 | stub = stub_request(:post, /.*api.gocardless.com#{stub_url}/) 42 | .to_timeout 43 | 44 | expect { post_response }.to raise_error(Faraday::ConnectionFailed) 45 | expect(stub).to have_been_requested 46 | end 47 | end 48 | 49 | context 'when the request needs a body and custom header' do 50 | let(:body) { { foo: 'bar' } } 51 | let(:headers) { { 'Foo' => 'Bar' } } 52 | subject(:post_response) { client.scenario_simulators.run(resource_id, body, headers) } 53 | 54 | let(:resource_id) { 'ABC123' } 55 | 56 | let!(:stub) do 57 | # /scenario_simulators/%v/actions/run 58 | stub_url = '/scenario_simulators/:identity/actions/run'.gsub(':identity', resource_id) 59 | stub_request(:post, /.*api.gocardless.com#{stub_url}/) 60 | .with( 61 | body: { foo: 'bar' }, 62 | headers: { 'Foo' => 'Bar' } 63 | ).to_return( 64 | body: { 65 | 'scenario_simulators' => { 66 | 67 | 'id' => 'id-input' 68 | } 69 | }.to_json, 70 | headers: response_headers 71 | ) 72 | end 73 | end 74 | end 75 | end 76 | -------------------------------------------------------------------------------- /lib/gocardless_pro/resources/bank_authorisation.rb: -------------------------------------------------------------------------------- 1 | # 2 | # This client is automatically generated from a template and JSON schema definition. 3 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 4 | # 5 | 6 | require 'uri' 7 | 8 | module GoCardlessPro 9 | # A module containing classes for each of the resources in the GC Api 10 | module Resources 11 | # Represents an instance of a bank_authorisation resource returned from the API 12 | 13 | # Bank Authorisations can be used to authorise Billing Requests. 14 | # Authorisations 15 | # are created against a specific bank, usually the bank that provides the 16 | # payer's 17 | # account. 18 | # 19 | # Creation of Bank Authorisations is only permitted from GoCardless hosted 20 | # UIs 21 | # (see Billing Request Flows) to ensure we meet regulatory requirements for 22 | # checkout flows. 23 | class BankAuthorisation 24 | attr_reader :authorisation_type, :authorised_at, :created_at, :expires_at, :id, :last_visited_at, :qr_code_url, 25 | :redirect_uri, :url 26 | 27 | # Initialize a bank_authorisation resource instance 28 | # @param object [Hash] an object returned from the API 29 | def initialize(object, response = nil) 30 | @object = object 31 | 32 | @authorisation_type = object['authorisation_type'] 33 | @authorised_at = object['authorised_at'] 34 | @created_at = object['created_at'] 35 | @expires_at = object['expires_at'] 36 | @id = object['id'] 37 | @last_visited_at = object['last_visited_at'] 38 | @links = object['links'] 39 | @qr_code_url = object['qr_code_url'] 40 | @redirect_uri = object['redirect_uri'] 41 | @url = object['url'] 42 | @response = response 43 | end 44 | 45 | def api_response 46 | ApiResponse.new(@response) 47 | end 48 | 49 | # Return the links that the resource has 50 | def links 51 | @bank_authorisation_links ||= Links.new(@links) 52 | end 53 | 54 | # Provides the bank_authorisation resource as a hash of all its readable attributes 55 | def to_h 56 | @object 57 | end 58 | 59 | class Links 60 | def initialize(links) 61 | @links = links || {} 62 | end 63 | 64 | def billing_request 65 | @links['billing_request'] 66 | end 67 | 68 | def institution 69 | @links['institution'] 70 | end 71 | end 72 | end 73 | end 74 | end 75 | -------------------------------------------------------------------------------- /lib/gocardless_pro/resources/payout.rb: -------------------------------------------------------------------------------- 1 | # 2 | # This client is automatically generated from a template and JSON schema definition. 3 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 4 | # 5 | 6 | require 'uri' 7 | 8 | module GoCardlessPro 9 | # A module containing classes for each of the resources in the GC Api 10 | module Resources 11 | # Represents an instance of a payout resource returned from the API 12 | 13 | # Payouts represent transfers from GoCardless to a 14 | # [creditor](#core-endpoints-creditors). Each payout contains the funds 15 | # collected from one or many [payments](#core-endpoints-payments). All the 16 | # payments in a payout will have been collected in the same currency. 17 | # Payouts are created automatically after a payment has been successfully 18 | # collected. 19 | class Payout 20 | attr_reader :amount, :arrival_date, :created_at, :currency, :deducted_fees, :fx, :id, :metadata, :payout_type, 21 | :reference, :status, :tax_currency 22 | 23 | # Initialize a payout resource instance 24 | # @param object [Hash] an object returned from the API 25 | def initialize(object, response = nil) 26 | @object = object 27 | 28 | @amount = object['amount'] 29 | @arrival_date = object['arrival_date'] 30 | @created_at = object['created_at'] 31 | @currency = object['currency'] 32 | @deducted_fees = object['deducted_fees'] 33 | @fx = object['fx'] 34 | @id = object['id'] 35 | @links = object['links'] 36 | @metadata = object['metadata'] 37 | @payout_type = object['payout_type'] 38 | @reference = object['reference'] 39 | @status = object['status'] 40 | @tax_currency = object['tax_currency'] 41 | @response = response 42 | end 43 | 44 | def api_response 45 | ApiResponse.new(@response) 46 | end 47 | 48 | # Return the links that the resource has 49 | def links 50 | @payout_links ||= Links.new(@links) 51 | end 52 | 53 | # Provides the payout resource as a hash of all its readable attributes 54 | def to_h 55 | @object 56 | end 57 | 58 | class Links 59 | def initialize(links) 60 | @links = links || {} 61 | end 62 | 63 | def creditor 64 | @links['creditor'] 65 | end 66 | 67 | def creditor_bank_account 68 | @links['creditor_bank_account'] 69 | end 70 | end 71 | end 72 | end 73 | end 74 | -------------------------------------------------------------------------------- /spec/resources/transferred_mandate_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe GoCardlessPro::Resources::TransferredMandate do 4 | let(:client) do 5 | GoCardlessPro::Client.new( 6 | access_token: 'SECRET_TOKEN' 7 | ) 8 | end 9 | 10 | let(:response_headers) { { 'Content-Type' => 'application/json' } } 11 | 12 | describe '#transferred_mandates' do 13 | subject(:get_response) { client.transferred_mandates.transferred_mandates(resource_id) } 14 | 15 | let(:resource_id) { 'ABC123' } 16 | 17 | let!(:stub) do 18 | # /transferred_mandates/%v 19 | stub_url = '/transferred_mandates/:identity'.gsub(':identity', resource_id) 20 | stub_request(:get, /.*api.gocardless.com#{stub_url}/).to_return( 21 | body: { 22 | 'transferred_mandates' => { 23 | 24 | 'encrypted_customer_bank_details' => 'encrypted_customer_bank_details-input', 25 | 'encrypted_decryption_key' => 'encrypted_decryption_key-input', 26 | 'links' => 'links-input', 27 | 'public_key_id' => 'public_key_id-input' 28 | } 29 | }.to_json, 30 | 31 | headers: response_headers 32 | ) 33 | end 34 | 35 | it 'wraps the response and calls the right endpoint' do 36 | expect(get_response).to be_a(GoCardlessPro::Resources::TransferredMandate) 37 | 38 | expect(stub).to have_been_requested 39 | end 40 | 41 | context 'when the request needs a body and custom header' do 42 | let(:body) { { foo: 'bar' } } 43 | let(:headers) { { 'Foo' => 'Bar' } } 44 | subject(:get_response) { client.transferred_mandates.transferred_mandates(resource_id, body, headers) } 45 | 46 | let(:resource_id) { 'ABC123' } 47 | 48 | let!(:stub) do 49 | # /transferred_mandates/%v 50 | stub_url = '/transferred_mandates/:identity'.gsub(':identity', resource_id) 51 | stub_request(:get, /.*api.gocardless.com#{stub_url}/) 52 | .with( 53 | body: { foo: 'bar' }, 54 | headers: { 'Foo' => 'Bar' } 55 | ).to_return( 56 | body: { 57 | 'transferred_mandates' => { 58 | 59 | 'encrypted_customer_bank_details' => 'encrypted_customer_bank_details-input', 60 | 'encrypted_decryption_key' => 'encrypted_decryption_key-input', 61 | 'links' => 'links-input', 62 | 'public_key_id' => 'public_key_id-input' 63 | } 64 | }.to_json, 65 | headers: response_headers 66 | ) 67 | end 68 | end 69 | end 70 | end 71 | -------------------------------------------------------------------------------- /lib/gocardless_pro/services/billing_request_flows_service.rb: -------------------------------------------------------------------------------- 1 | require_relative './base_service' 2 | 3 | # encoding: utf-8 4 | # 5 | # This client is automatically generated from a template and JSON schema definition. 6 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 7 | # 8 | 9 | module GoCardlessPro 10 | module Services 11 | # Service for making requests to the BillingRequestFlow endpoints 12 | class BillingRequestFlowsService < BaseService 13 | # Creates a new billing request flow. 14 | # Example URL: /billing_request_flows 15 | # @param options [Hash] parameters as a hash, under a params key. 16 | def create(options = {}) 17 | path = '/billing_request_flows' 18 | 19 | params = options.delete(:params) || {} 20 | options[:params] = {} 21 | options[:params][envelope_key] = params 22 | 23 | options[:retry_failures] = true 24 | 25 | response = make_request(:post, path, options) 26 | 27 | return if response.body.nil? 28 | 29 | Resources::BillingRequestFlow.new(unenvelope_body(response.body), response) 30 | end 31 | 32 | # Returns the flow having generated a fresh session token which can be used to 33 | # power 34 | # integrations that manipulate the flow. 35 | # Example URL: /billing_request_flows/:identity/actions/initialise 36 | # 37 | # @param identity # Unique identifier, beginning with "BRF". 38 | # @param options [Hash] parameters as a hash, under a params key. 39 | def initialise(identity, options = {}) 40 | path = sub_url('/billing_request_flows/:identity/actions/initialise', { 41 | 'identity' => identity 42 | }) 43 | 44 | params = options.delete(:params) || {} 45 | options[:params] = {} 46 | options[:params]['data'] = params 47 | 48 | options[:retry_failures] = false 49 | 50 | response = make_request(:post, path, options) 51 | 52 | return if response.body.nil? 53 | 54 | Resources::BillingRequestFlow.new(unenvelope_body(response.body), response) 55 | end 56 | 57 | private 58 | 59 | # Unenvelope the response of the body using the service's `envelope_key` 60 | # 61 | # @param body [Hash] 62 | def unenvelope_body(body) 63 | body[envelope_key] || body['data'] 64 | end 65 | 66 | # return the key which API responses will envelope data under 67 | def envelope_key 68 | 'billing_request_flows' 69 | end 70 | end 71 | end 72 | end 73 | -------------------------------------------------------------------------------- /lib/gocardless_pro/services/exports_service.rb: -------------------------------------------------------------------------------- 1 | require_relative './base_service' 2 | 3 | # encoding: utf-8 4 | # 5 | # This client is automatically generated from a template and JSON schema definition. 6 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 7 | # 8 | 9 | module GoCardlessPro 10 | module Services 11 | # Service for making requests to the Export endpoints 12 | class ExportsService < BaseService 13 | # Returns a single export. 14 | # Example URL: /exports/:identity 15 | # 16 | # @param identity # Unique identifier, beginning with "EX". 17 | # @param options [Hash] parameters as a hash, under a params key. 18 | def get(identity, options = {}) 19 | path = sub_url('/exports/:identity', { 20 | 'identity' => identity 21 | }) 22 | 23 | options[:retry_failures] = true 24 | 25 | response = make_request(:get, path, options) 26 | 27 | return if response.body.nil? 28 | 29 | Resources::Export.new(unenvelope_body(response.body), response) 30 | end 31 | 32 | # Returns a list of exports which are available for download. 33 | # Example URL: /exports 34 | # @param options [Hash] parameters as a hash, under a params key. 35 | def list(options = {}) 36 | path = '/exports' 37 | 38 | options[:retry_failures] = true 39 | 40 | response = make_request(:get, path, options) 41 | 42 | ListResponse.new( 43 | response: response, 44 | unenveloped_body: unenvelope_body(response.body), 45 | resource_class: Resources::Export 46 | ) 47 | end 48 | 49 | # Get a lazily enumerated list of all the items returned. This is similar to the `list` method but will paginate for you automatically. 50 | # 51 | # @param options [Hash] parameters as a hash. If the request is a GET, these will be converted to query parameters. 52 | # Otherwise they will be the body of the request. 53 | def all(options = {}) 54 | Paginator.new( 55 | service: self, 56 | options: options 57 | ).enumerator 58 | end 59 | 60 | private 61 | 62 | # Unenvelope the response of the body using the service's `envelope_key` 63 | # 64 | # @param body [Hash] 65 | def unenvelope_body(body) 66 | body[envelope_key] || body['data'] 67 | end 68 | 69 | # return the key which API responses will envelope data under 70 | def envelope_key 71 | 'exports' 72 | end 73 | end 74 | end 75 | end 76 | -------------------------------------------------------------------------------- /lib/gocardless_pro/services/events_service.rb: -------------------------------------------------------------------------------- 1 | require_relative './base_service' 2 | 3 | # encoding: utf-8 4 | # 5 | # This client is automatically generated from a template and JSON schema definition. 6 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 7 | # 8 | 9 | module GoCardlessPro 10 | module Services 11 | # Service for making requests to the Event endpoints 12 | class EventsService < BaseService 13 | # Returns a [cursor-paginated](#api-usage-cursor-pagination) list of your 14 | # events. 15 | # Example URL: /events 16 | # @param options [Hash] parameters as a hash, under a params key. 17 | def list(options = {}) 18 | path = '/events' 19 | 20 | options[:retry_failures] = true 21 | 22 | response = make_request(:get, path, options) 23 | 24 | ListResponse.new( 25 | response: response, 26 | unenveloped_body: unenvelope_body(response.body), 27 | resource_class: Resources::Event 28 | ) 29 | end 30 | 31 | # Get a lazily enumerated list of all the items returned. This is similar to the `list` method but will paginate for you automatically. 32 | # 33 | # @param options [Hash] parameters as a hash. If the request is a GET, these will be converted to query parameters. 34 | # Otherwise they will be the body of the request. 35 | def all(options = {}) 36 | Paginator.new( 37 | service: self, 38 | options: options 39 | ).enumerator 40 | end 41 | 42 | # Retrieves the details of a single event. 43 | # Example URL: /events/:identity 44 | # 45 | # @param identity # Unique identifier, beginning with "EV". 46 | # @param options [Hash] parameters as a hash, under a params key. 47 | def get(identity, options = {}) 48 | path = sub_url('/events/:identity', { 49 | 'identity' => identity 50 | }) 51 | 52 | options[:retry_failures] = true 53 | 54 | response = make_request(:get, path, options) 55 | 56 | return if response.body.nil? 57 | 58 | Resources::Event.new(unenvelope_body(response.body), response) 59 | end 60 | 61 | private 62 | 63 | # Unenvelope the response of the body using the service's `envelope_key` 64 | # 65 | # @param body [Hash] 66 | def unenvelope_body(body) 67 | body[envelope_key] || body['data'] 68 | end 69 | 70 | # return the key which API responses will envelope data under 71 | def envelope_key 72 | 'events' 73 | end 74 | end 75 | end 76 | end 77 | -------------------------------------------------------------------------------- /spec/resources/customer_notification_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe GoCardlessPro::Resources::CustomerNotification do 4 | let(:client) do 5 | GoCardlessPro::Client.new( 6 | access_token: 'SECRET_TOKEN' 7 | ) 8 | end 9 | 10 | let(:response_headers) { { 'Content-Type' => 'application/json' } } 11 | 12 | describe '#handle' do 13 | subject(:post_response) { client.customer_notifications.handle(resource_id) } 14 | 15 | let(:resource_id) { 'ABC123' } 16 | 17 | let!(:stub) do 18 | # /customer_notifications/%v/actions/handle 19 | stub_url = '/customer_notifications/:identity/actions/handle'.gsub(':identity', resource_id) 20 | stub_request(:post, /.*api.gocardless.com#{stub_url}/).to_return( 21 | body: { 22 | 'customer_notifications' => { 23 | 24 | 'action_taken' => 'action_taken-input', 25 | 'action_taken_at' => 'action_taken_at-input', 26 | 'action_taken_by' => 'action_taken_by-input', 27 | 'id' => 'id-input', 28 | 'links' => 'links-input', 29 | 'type' => 'type-input' 30 | } 31 | }.to_json, 32 | 33 | headers: response_headers 34 | ) 35 | end 36 | 37 | it 'wraps the response and calls the right endpoint' do 38 | expect(post_response).to be_a(GoCardlessPro::Resources::CustomerNotification) 39 | 40 | expect(stub).to have_been_requested 41 | end 42 | 43 | context 'when the request needs a body and custom header' do 44 | let(:body) { { foo: 'bar' } } 45 | let(:headers) { { 'Foo' => 'Bar' } } 46 | subject(:post_response) { client.customer_notifications.handle(resource_id, body, headers) } 47 | 48 | let(:resource_id) { 'ABC123' } 49 | 50 | let!(:stub) do 51 | # /customer_notifications/%v/actions/handle 52 | stub_url = '/customer_notifications/:identity/actions/handle'.gsub(':identity', resource_id) 53 | stub_request(:post, /.*api.gocardless.com#{stub_url}/) 54 | .with( 55 | body: { foo: 'bar' }, 56 | headers: { 'Foo' => 'Bar' } 57 | ).to_return( 58 | body: { 59 | 'customer_notifications' => { 60 | 61 | 'action_taken' => 'action_taken-input', 62 | 'action_taken_at' => 'action_taken_at-input', 63 | 'action_taken_by' => 'action_taken_by-input', 64 | 'id' => 'id-input', 65 | 'links' => 'links-input', 66 | 'type' => 'type-input' 67 | } 68 | }.to_json, 69 | headers: response_headers 70 | ) 71 | end 72 | end 73 | end 74 | end 75 | -------------------------------------------------------------------------------- /lib/gocardless_pro/services/verification_details_service.rb: -------------------------------------------------------------------------------- 1 | require_relative './base_service' 2 | 3 | # encoding: utf-8 4 | # 5 | # This client is automatically generated from a template and JSON schema definition. 6 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 7 | # 8 | 9 | module GoCardlessPro 10 | module Services 11 | # Service for making requests to the VerificationDetail endpoints 12 | class VerificationDetailsService < BaseService 13 | # Creates a new verification detail 14 | # Example URL: /verification_details 15 | # @param options [Hash] parameters as a hash, under a params key. 16 | def create(options = {}) 17 | path = '/verification_details' 18 | 19 | params = options.delete(:params) || {} 20 | options[:params] = {} 21 | options[:params][envelope_key] = params 22 | 23 | options[:retry_failures] = true 24 | 25 | response = make_request(:post, path, options) 26 | 27 | return if response.body.nil? 28 | 29 | Resources::VerificationDetail.new(unenvelope_body(response.body), response) 30 | end 31 | 32 | # Returns a list of verification details belonging to a creditor. 33 | # Example URL: /verification_details 34 | # @param options [Hash] parameters as a hash, under a params key. 35 | def list(options = {}) 36 | path = '/verification_details' 37 | 38 | options[:retry_failures] = true 39 | 40 | response = make_request(:get, path, options) 41 | 42 | ListResponse.new( 43 | response: response, 44 | unenveloped_body: unenvelope_body(response.body), 45 | resource_class: Resources::VerificationDetail 46 | ) 47 | end 48 | 49 | # Get a lazily enumerated list of all the items returned. This is similar to the `list` method but will paginate for you automatically. 50 | # 51 | # @param options [Hash] parameters as a hash. If the request is a GET, these will be converted to query parameters. 52 | # Otherwise they will be the body of the request. 53 | def all(options = {}) 54 | Paginator.new( 55 | service: self, 56 | options: options 57 | ).enumerator 58 | end 59 | 60 | private 61 | 62 | # Unenvelope the response of the body using the service's `envelope_key` 63 | # 64 | # @param body [Hash] 65 | def unenvelope_body(body) 66 | body[envelope_key] || body['data'] 67 | end 68 | 69 | # return the key which API responses will envelope data under 70 | def envelope_key 71 | 'verification_details' 72 | end 73 | end 74 | end 75 | end 76 | -------------------------------------------------------------------------------- /lib/gocardless_pro/resources/payout_item.rb: -------------------------------------------------------------------------------- 1 | # 2 | # This client is automatically generated from a template and JSON schema definition. 3 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 4 | # 5 | 6 | require 'uri' 7 | 8 | module GoCardlessPro 9 | # A module containing classes for each of the resources in the GC Api 10 | module Resources 11 | # Represents an instance of a payout_item resource returned from the API 12 | 13 | # When we collect a payment on your behalf, we add the money you've 14 | # collected to your 15 | # GoCardless balance, minus any fees paid. Periodically (usually every 16 | # working day), 17 | # we take any positive balance in your GoCardless account, and pay it out to 18 | # your 19 | # nominated bank account. 20 | # 21 | # Other actions in your GoCardless account can also affect your balance. For 22 | # example, 23 | # if a customer charges back a payment, we'll deduct the payment's amount 24 | # from your 25 | # balance, but add any fees you paid for that payment back to your balance. 26 | # 27 | # The Payout Items API allows you to view, on a per-payout basis, the credit 28 | # and debit 29 | # items that make up that payout's amount. Payout items can only be 30 | # retrieved for payouts 31 | # created in the last 6 months. Requests for older payouts will return an 32 | # HTTP status 33 | # 410 Gone. 34 | # 35 | class PayoutItem 36 | attr_reader :amount, :taxes, :type 37 | 38 | # Initialize a payout_item resource instance 39 | # @param object [Hash] an object returned from the API 40 | def initialize(object, response = nil) 41 | @object = object 42 | 43 | @amount = object['amount'] 44 | @links = object['links'] 45 | @taxes = object['taxes'] 46 | @type = object['type'] 47 | @response = response 48 | end 49 | 50 | def api_response 51 | ApiResponse.new(@response) 52 | end 53 | 54 | # Return the links that the resource has 55 | def links 56 | @payout_item_links ||= Links.new(@links) 57 | end 58 | 59 | # Provides the payout_item resource as a hash of all its readable attributes 60 | def to_h 61 | @object 62 | end 63 | 64 | class Links 65 | def initialize(links) 66 | @links = links || {} 67 | end 68 | 69 | def mandate 70 | @links['mandate'] 71 | end 72 | 73 | def payment 74 | @links['payment'] 75 | end 76 | 77 | def refund 78 | @links['refund'] 79 | end 80 | end 81 | end 82 | end 83 | end 84 | -------------------------------------------------------------------------------- /lib/gocardless_pro/services/tax_rates_service.rb: -------------------------------------------------------------------------------- 1 | require_relative './base_service' 2 | 3 | # encoding: utf-8 4 | # 5 | # This client is automatically generated from a template and JSON schema definition. 6 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 7 | # 8 | 9 | module GoCardlessPro 10 | module Services 11 | # Service for making requests to the TaxRate endpoints 12 | class TaxRatesService < BaseService 13 | # Returns a [cursor-paginated](#api-usage-cursor-pagination) list of all tax 14 | # rates. 15 | # Example URL: /tax_rates 16 | # @param options [Hash] parameters as a hash, under a params key. 17 | def list(options = {}) 18 | path = '/tax_rates' 19 | 20 | options[:retry_failures] = true 21 | 22 | response = make_request(:get, path, options) 23 | 24 | ListResponse.new( 25 | response: response, 26 | unenveloped_body: unenvelope_body(response.body), 27 | resource_class: Resources::TaxRate 28 | ) 29 | end 30 | 31 | # Get a lazily enumerated list of all the items returned. This is similar to the `list` method but will paginate for you automatically. 32 | # 33 | # @param options [Hash] parameters as a hash. If the request is a GET, these will be converted to query parameters. 34 | # Otherwise they will be the body of the request. 35 | def all(options = {}) 36 | Paginator.new( 37 | service: self, 38 | options: options 39 | ).enumerator 40 | end 41 | 42 | # Retrieves the details of a tax rate. 43 | # Example URL: /tax_rates/:identity 44 | # 45 | # @param identity # The unique identifier created by the jurisdiction, tax type and version 46 | # @param options [Hash] parameters as a hash, under a params key. 47 | def get(identity, options = {}) 48 | path = sub_url('/tax_rates/:identity', { 49 | 'identity' => identity 50 | }) 51 | 52 | options[:retry_failures] = true 53 | 54 | response = make_request(:get, path, options) 55 | 56 | return if response.body.nil? 57 | 58 | Resources::TaxRate.new(unenvelope_body(response.body), response) 59 | end 60 | 61 | private 62 | 63 | # Unenvelope the response of the body using the service's `envelope_key` 64 | # 65 | # @param body [Hash] 66 | def unenvelope_body(body) 67 | body[envelope_key] || body['data'] 68 | end 69 | 70 | # return the key which API responses will envelope data under 71 | def envelope_key 72 | 'tax_rates' 73 | end 74 | end 75 | end 76 | end 77 | -------------------------------------------------------------------------------- /lib/gocardless_pro/services/bank_authorisations_service.rb: -------------------------------------------------------------------------------- 1 | require_relative './base_service' 2 | 3 | # encoding: utf-8 4 | # 5 | # This client is automatically generated from a template and JSON schema definition. 6 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 7 | # 8 | 9 | module GoCardlessPro 10 | module Services 11 | # Service for making requests to the BankAuthorisation endpoints 12 | class BankAuthorisationsService < BaseService 13 | # Create a Bank Authorisation. 14 | # Example URL: /bank_authorisations 15 | # @param options [Hash] parameters as a hash, under a params key. 16 | def create(options = {}) 17 | path = '/bank_authorisations' 18 | 19 | params = options.delete(:params) || {} 20 | options[:params] = {} 21 | options[:params][envelope_key] = params 22 | 23 | options[:retry_failures] = true 24 | 25 | begin 26 | response = make_request(:post, path, options) 27 | 28 | # Response doesn't raise any errors until #body is called 29 | response.tap(&:body) 30 | rescue InvalidStateError => e 31 | if e.idempotent_creation_conflict? 32 | case @api_service.on_idempotency_conflict 33 | when :raise 34 | raise IdempotencyConflict, e.error 35 | when :fetch 36 | return get(e.conflicting_resource_id) 37 | end 38 | end 39 | 40 | raise e 41 | end 42 | 43 | return if response.body.nil? 44 | 45 | Resources::BankAuthorisation.new(unenvelope_body(response.body), response) 46 | end 47 | 48 | # Get a single bank authorisation. 49 | # Example URL: /bank_authorisations/:identity 50 | # 51 | # @param identity # Unique identifier, beginning with "BAU". 52 | # @param options [Hash] parameters as a hash, under a params key. 53 | def get(identity, options = {}) 54 | path = sub_url('/bank_authorisations/:identity', { 55 | 'identity' => identity 56 | }) 57 | 58 | options[:retry_failures] = true 59 | 60 | response = make_request(:get, path, options) 61 | 62 | return if response.body.nil? 63 | 64 | Resources::BankAuthorisation.new(unenvelope_body(response.body), response) 65 | end 66 | 67 | private 68 | 69 | # Unenvelope the response of the body using the service's `envelope_key` 70 | # 71 | # @param body [Hash] 72 | def unenvelope_body(body) 73 | body[envelope_key] || body['data'] 74 | end 75 | 76 | # return the key which API responses will envelope data under 77 | def envelope_key 78 | 'bank_authorisations' 79 | end 80 | end 81 | end 82 | end 83 | -------------------------------------------------------------------------------- /lib/gocardless_pro/resources/instalment_schedule.rb: -------------------------------------------------------------------------------- 1 | # 2 | # This client is automatically generated from a template and JSON schema definition. 3 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 4 | # 5 | 6 | require 'uri' 7 | 8 | module GoCardlessPro 9 | # A module containing classes for each of the resources in the GC Api 10 | module Resources 11 | # Represents an instance of a instalment_schedule resource returned from the API 12 | 13 | # Instalment schedules are objects which represent a collection of related 14 | # payments, with the 15 | # intention to collect the `total_amount` specified. The API supports both 16 | # schedule-based 17 | # creation (similar to subscriptions) as well as explicit selection of 18 | # differing payment 19 | # amounts and charge dates. 20 | # 21 | # Unlike subscriptions, the payments are created immediately, so the 22 | # instalment schedule 23 | # cannot be modified once submitted and instead can only be cancelled (which 24 | # will cancel 25 | # any of the payments which have not yet been submitted). 26 | # 27 | # Customers will receive a single notification about the complete schedule 28 | # of collection. 29 | # 30 | class InstalmentSchedule 31 | attr_reader :created_at, :currency, :id, :metadata, :name, :payment_errors, :status, :total_amount 32 | 33 | # Initialize a instalment_schedule resource instance 34 | # @param object [Hash] an object returned from the API 35 | def initialize(object, response = nil) 36 | @object = object 37 | 38 | @created_at = object['created_at'] 39 | @currency = object['currency'] 40 | @id = object['id'] 41 | @links = object['links'] 42 | @metadata = object['metadata'] 43 | @name = object['name'] 44 | @payment_errors = object['payment_errors'] 45 | @status = object['status'] 46 | @total_amount = object['total_amount'] 47 | @response = response 48 | end 49 | 50 | def api_response 51 | ApiResponse.new(@response) 52 | end 53 | 54 | # Return the links that the resource has 55 | def links 56 | @instalment_schedule_links ||= Links.new(@links) 57 | end 58 | 59 | # Provides the instalment_schedule resource as a hash of all its readable attributes 60 | def to_h 61 | @object 62 | end 63 | 64 | class Links 65 | def initialize(links) 66 | @links = links || {} 67 | end 68 | 69 | def customer 70 | @links['customer'] 71 | end 72 | 73 | def mandate 74 | @links['mandate'] 75 | end 76 | 77 | def payments 78 | @links['payments'] 79 | end 80 | end 81 | end 82 | end 83 | end 84 | -------------------------------------------------------------------------------- /lib/gocardless_pro/resources/payment.rb: -------------------------------------------------------------------------------- 1 | # 2 | # This client is automatically generated from a template and JSON schema definition. 3 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 4 | # 5 | 6 | require 'uri' 7 | 8 | module GoCardlessPro 9 | # A module containing classes for each of the resources in the GC Api 10 | module Resources 11 | # Represents an instance of a payment resource returned from the API 12 | 13 | # Payment objects represent payments from a 14 | # [customer](#core-endpoints-customers) to a 15 | # [creditor](#core-endpoints-creditors), taken against a Direct Debit 16 | # [mandate](#core-endpoints-mandates). 17 | # 18 | # GoCardless will notify you via a [webhook](#appendix-webhooks) whenever 19 | # the state of a payment changes. 20 | class Payment 21 | attr_reader :amount, :amount_refunded, :charge_date, :created_at, :currency, :description, :faster_ach, :fx, :id, 22 | :metadata, :reference, :retry_if_possible, :status 23 | 24 | # Initialize a payment resource instance 25 | # @param object [Hash] an object returned from the API 26 | def initialize(object, response = nil) 27 | @object = object 28 | 29 | @amount = object['amount'] 30 | @amount_refunded = object['amount_refunded'] 31 | @charge_date = object['charge_date'] 32 | @created_at = object['created_at'] 33 | @currency = object['currency'] 34 | @description = object['description'] 35 | @faster_ach = object['faster_ach'] 36 | @fx = object['fx'] 37 | @id = object['id'] 38 | @links = object['links'] 39 | @metadata = object['metadata'] 40 | @reference = object['reference'] 41 | @retry_if_possible = object['retry_if_possible'] 42 | @status = object['status'] 43 | @response = response 44 | end 45 | 46 | def api_response 47 | ApiResponse.new(@response) 48 | end 49 | 50 | # Return the links that the resource has 51 | def links 52 | @payment_links ||= Links.new(@links) 53 | end 54 | 55 | # Provides the payment resource as a hash of all its readable attributes 56 | def to_h 57 | @object 58 | end 59 | 60 | class Links 61 | def initialize(links) 62 | @links = links || {} 63 | end 64 | 65 | def creditor 66 | @links['creditor'] 67 | end 68 | 69 | def instalment_schedule 70 | @links['instalment_schedule'] 71 | end 72 | 73 | def mandate 74 | @links['mandate'] 75 | end 76 | 77 | def payout 78 | @links['payout'] 79 | end 80 | 81 | def subscription 82 | @links['subscription'] 83 | end 84 | end 85 | end 86 | end 87 | end 88 | -------------------------------------------------------------------------------- /lib/gocardless_pro/resources/customer_notification.rb: -------------------------------------------------------------------------------- 1 | # 2 | # This client is automatically generated from a template and JSON schema definition. 3 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 4 | # 5 | 6 | require 'uri' 7 | 8 | module GoCardlessPro 9 | # A module containing classes for each of the resources in the GC Api 10 | module Resources 11 | # Represents an instance of a customer_notification resource returned from the API 12 | 13 | # Customer Notifications represent the notification which is due to be sent 14 | # to a customer 15 | # after an event has happened. The event, the resource and the customer to 16 | # be notified 17 | # are all identified in the `links` property. 18 | # 19 | # Note that these are ephemeral records - once the notification has been 20 | # actioned in some 21 | # way, it is no longer visible using this API. 22 | # 23 | #

Restricted: This API is 24 | # currently only available for approved integrators - please get in touch if you would like to 26 | # use this API.

27 | class CustomerNotification 28 | attr_reader :action_taken, :action_taken_at, :action_taken_by, :id, :type 29 | 30 | # Initialize a customer_notification resource instance 31 | # @param object [Hash] an object returned from the API 32 | def initialize(object, response = nil) 33 | @object = object 34 | 35 | @action_taken = object['action_taken'] 36 | @action_taken_at = object['action_taken_at'] 37 | @action_taken_by = object['action_taken_by'] 38 | @id = object['id'] 39 | @links = object['links'] 40 | @type = object['type'] 41 | @response = response 42 | end 43 | 44 | def api_response 45 | ApiResponse.new(@response) 46 | end 47 | 48 | # Return the links that the resource has 49 | def links 50 | @customer_notification_links ||= Links.new(@links) 51 | end 52 | 53 | # Provides the customer_notification resource as a hash of all its readable attributes 54 | def to_h 55 | @object 56 | end 57 | 58 | class Links 59 | def initialize(links) 60 | @links = links || {} 61 | end 62 | 63 | def customer 64 | @links['customer'] 65 | end 66 | 67 | def event 68 | @links['event'] 69 | end 70 | 71 | def mandate 72 | @links['mandate'] 73 | end 74 | 75 | def payment 76 | @links['payment'] 77 | end 78 | 79 | def refund 80 | @links['refund'] 81 | end 82 | 83 | def subscription 84 | @links['subscription'] 85 | end 86 | end 87 | end 88 | end 89 | end 90 | -------------------------------------------------------------------------------- /lib/gocardless_pro/services/institutions_service.rb: -------------------------------------------------------------------------------- 1 | require_relative './base_service' 2 | 3 | # encoding: utf-8 4 | # 5 | # This client is automatically generated from a template and JSON schema definition. 6 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 7 | # 8 | 9 | module GoCardlessPro 10 | module Services 11 | # Service for making requests to the Institution endpoints 12 | class InstitutionsService < BaseService 13 | # Returns a list of supported institutions. 14 | # Example URL: /institutions 15 | # @param options [Hash] parameters as a hash, under a params key. 16 | def list(options = {}) 17 | path = '/institutions' 18 | 19 | options[:retry_failures] = true 20 | 21 | response = make_request(:get, path, options) 22 | 23 | ListResponse.new( 24 | response: response, 25 | unenveloped_body: unenvelope_body(response.body), 26 | resource_class: Resources::Institution 27 | ) 28 | end 29 | 30 | # Get a lazily enumerated list of all the items returned. This is similar to the `list` method but will paginate for you automatically. 31 | # 32 | # @param options [Hash] parameters as a hash. If the request is a GET, these will be converted to query parameters. 33 | # Otherwise they will be the body of the request. 34 | def all(options = {}) 35 | Paginator.new( 36 | service: self, 37 | options: options 38 | ).enumerator 39 | end 40 | 41 | # Returns all institutions valid for a Billing Request. 42 | # 43 | # This endpoint is currently supported only for FasterPayments. 44 | # Example URL: /billing_requests/:identity/institutions 45 | # 46 | # @param identity # Unique identifier, beginning with "BRQ". 47 | # @param options [Hash] parameters as a hash, under a params key. 48 | def list_for_billing_request(identity, options = {}) 49 | path = sub_url('/billing_requests/:identity/institutions', { 50 | 'identity' => identity 51 | }) 52 | 53 | options[:retry_failures] = false 54 | 55 | response = make_request(:get, path, options) 56 | 57 | ListResponse.new( 58 | response: response, 59 | unenveloped_body: unenvelope_body(response.body), 60 | resource_class: Resources::Institution 61 | ) 62 | end 63 | 64 | private 65 | 66 | # Unenvelope the response of the body using the service's `envelope_key` 67 | # 68 | # @param body [Hash] 69 | def unenvelope_body(body) 70 | body[envelope_key] || body['data'] 71 | end 72 | 73 | # return the key which API responses will envelope data under 74 | def envelope_key 75 | 'institutions' 76 | end 77 | end 78 | end 79 | end 80 | -------------------------------------------------------------------------------- /lib/gocardless_pro/resources/creditor_bank_account.rb: -------------------------------------------------------------------------------- 1 | # 2 | # This client is automatically generated from a template and JSON schema definition. 3 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 4 | # 5 | 6 | require 'uri' 7 | 8 | module GoCardlessPro 9 | # A module containing classes for each of the resources in the GC Api 10 | module Resources 11 | # Represents an instance of a creditor_bank_account resource returned from the API 12 | 13 | # Creditor Bank Accounts hold the bank details of a 14 | # [creditor](#core-endpoints-creditors). These are the bank accounts which 15 | # your [payouts](#core-endpoints-payouts) will be sent to. 16 | # 17 | # Note that creditor bank accounts must be unique, and so you will encounter 18 | # a `bank_account_exists` error if you try to create a duplicate bank 19 | # account. You may wish to handle this by updating the existing record 20 | # instead, the ID of which will be provided as 21 | # `links[creditor_bank_account]` in the error response. 22 | # 23 | #

Restricted: This API is not 24 | # available for partner integrations.

25 | class CreditorBankAccount 26 | attr_reader :account_holder_name, :account_number_ending, :account_type, :bank_name, :country_code, :created_at, 27 | :currency, :enabled, :id, :metadata, :verification_status 28 | 29 | # Initialize a creditor_bank_account resource instance 30 | # @param object [Hash] an object returned from the API 31 | def initialize(object, response = nil) 32 | @object = object 33 | 34 | @account_holder_name = object['account_holder_name'] 35 | @account_number_ending = object['account_number_ending'] 36 | @account_type = object['account_type'] 37 | @bank_name = object['bank_name'] 38 | @country_code = object['country_code'] 39 | @created_at = object['created_at'] 40 | @currency = object['currency'] 41 | @enabled = object['enabled'] 42 | @id = object['id'] 43 | @links = object['links'] 44 | @metadata = object['metadata'] 45 | @verification_status = object['verification_status'] 46 | @response = response 47 | end 48 | 49 | def api_response 50 | ApiResponse.new(@response) 51 | end 52 | 53 | # Return the links that the resource has 54 | def links 55 | @creditor_bank_account_links ||= Links.new(@links) 56 | end 57 | 58 | # Provides the creditor_bank_account resource as a hash of all its readable attributes 59 | def to_h 60 | @object 61 | end 62 | 63 | class Links 64 | def initialize(links) 65 | @links = links || {} 66 | end 67 | 68 | def creditor 69 | @links['creditor'] 70 | end 71 | end 72 | end 73 | end 74 | end 75 | -------------------------------------------------------------------------------- /lib/gocardless_pro/resources/mandate.rb: -------------------------------------------------------------------------------- 1 | # 2 | # This client is automatically generated from a template and JSON schema definition. 3 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 4 | # 5 | 6 | require 'uri' 7 | 8 | module GoCardlessPro 9 | # A module containing classes for each of the resources in the GC Api 10 | module Resources 11 | # Represents an instance of a mandate resource returned from the API 12 | 13 | # Mandates represent the Direct Debit mandate with a 14 | # [customer](#core-endpoints-customers). 15 | # 16 | # GoCardless will notify you via a [webhook](#appendix-webhooks) whenever 17 | # the status of a mandate changes. 18 | class Mandate 19 | attr_reader :authorisation_source, :consent_parameters, :consent_type, :created_at, :funds_settlement, :id, 20 | :metadata, :next_possible_charge_date, :next_possible_standard_ach_charge_date, :payments_require_approval, :reference, :scheme, :status, :verified_at 21 | 22 | # Initialize a mandate resource instance 23 | # @param object [Hash] an object returned from the API 24 | def initialize(object, response = nil) 25 | @object = object 26 | 27 | @authorisation_source = object['authorisation_source'] 28 | @consent_parameters = object['consent_parameters'] 29 | @consent_type = object['consent_type'] 30 | @created_at = object['created_at'] 31 | @funds_settlement = object['funds_settlement'] 32 | @id = object['id'] 33 | @links = object['links'] 34 | @metadata = object['metadata'] 35 | @next_possible_charge_date = object['next_possible_charge_date'] 36 | @next_possible_standard_ach_charge_date = object['next_possible_standard_ach_charge_date'] 37 | @payments_require_approval = object['payments_require_approval'] 38 | @reference = object['reference'] 39 | @scheme = object['scheme'] 40 | @status = object['status'] 41 | @verified_at = object['verified_at'] 42 | @response = response 43 | end 44 | 45 | def api_response 46 | ApiResponse.new(@response) 47 | end 48 | 49 | # Return the links that the resource has 50 | def links 51 | @mandate_links ||= Links.new(@links) 52 | end 53 | 54 | # Provides the mandate resource as a hash of all its readable attributes 55 | def to_h 56 | @object 57 | end 58 | 59 | class Links 60 | def initialize(links) 61 | @links = links || {} 62 | end 63 | 64 | def creditor 65 | @links['creditor'] 66 | end 67 | 68 | def customer 69 | @links['customer'] 70 | end 71 | 72 | def customer_bank_account 73 | @links['customer_bank_account'] 74 | end 75 | 76 | def new_mandate 77 | @links['new_mandate'] 78 | end 79 | end 80 | end 81 | end 82 | end 83 | -------------------------------------------------------------------------------- /spec/services/transferred_mandates_service_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe GoCardlessPro::Services::TransferredMandatesService do 4 | let(:client) do 5 | GoCardlessPro::Client.new( 6 | access_token: 'SECRET_TOKEN' 7 | ) 8 | end 9 | 10 | let(:response_headers) { { 'Content-Type' => 'application/json' } } 11 | 12 | describe '#transferred_mandates' do 13 | subject(:get_response) { client.transferred_mandates.transferred_mandates(resource_id) } 14 | 15 | let(:resource_id) { 'ABC123' } 16 | 17 | let!(:stub) do 18 | # /transferred_mandates/%v 19 | stub_url = '/transferred_mandates/:identity'.gsub(':identity', resource_id) 20 | stub_request(:get, /.*api.gocardless.com#{stub_url}/).to_return( 21 | body: { 22 | 'transferred_mandates' => { 23 | 24 | 'encrypted_customer_bank_details' => 'encrypted_customer_bank_details-input', 25 | 'encrypted_decryption_key' => 'encrypted_decryption_key-input', 26 | 'links' => 'links-input', 27 | 'public_key_id' => 'public_key_id-input' 28 | } 29 | }.to_json, 30 | 31 | headers: response_headers 32 | ) 33 | end 34 | 35 | it 'wraps the response and calls the right endpoint' do 36 | expect(get_response).to be_a(GoCardlessPro::Resources::TransferredMandate) 37 | 38 | expect(stub).to have_been_requested 39 | end 40 | 41 | describe 'retry behaviour' do 42 | it "doesn't retry errors" do 43 | stub_url = '/transferred_mandates/:identity'.gsub(':identity', resource_id) 44 | stub = stub_request(:get, /.*api.gocardless.com#{stub_url}/) 45 | .to_timeout 46 | 47 | expect { get_response }.to raise_error(Faraday::ConnectionFailed) 48 | expect(stub).to have_been_requested 49 | end 50 | end 51 | 52 | context 'when the request needs a body and custom header' do 53 | let(:body) { { foo: 'bar' } } 54 | let(:headers) { { 'Foo' => 'Bar' } } 55 | subject(:get_response) { client.transferred_mandates.transferred_mandates(resource_id, body, headers) } 56 | 57 | let(:resource_id) { 'ABC123' } 58 | 59 | let!(:stub) do 60 | # /transferred_mandates/%v 61 | stub_url = '/transferred_mandates/:identity'.gsub(':identity', resource_id) 62 | stub_request(:get, /.*api.gocardless.com#{stub_url}/) 63 | .with( 64 | body: { foo: 'bar' }, 65 | headers: { 'Foo' => 'Bar' } 66 | ).to_return( 67 | body: { 68 | 'transferred_mandates' => { 69 | 70 | 'encrypted_customer_bank_details' => 'encrypted_customer_bank_details-input', 71 | 'encrypted_decryption_key' => 'encrypted_decryption_key-input', 72 | 'links' => 'links-input', 73 | 'public_key_id' => 'public_key_id-input' 74 | } 75 | }.to_json, 76 | headers: response_headers 77 | ) 78 | end 79 | end 80 | end 81 | end 82 | -------------------------------------------------------------------------------- /lib/gocardless_pro/resources/billing_request_flow.rb: -------------------------------------------------------------------------------- 1 | # 2 | # This client is automatically generated from a template and JSON schema definition. 3 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 4 | # 5 | 6 | require 'uri' 7 | 8 | module GoCardlessPro 9 | # A module containing classes for each of the resources in the GC Api 10 | module Resources 11 | # Represents an instance of a billing_request_flow resource returned from the API 12 | 13 | # Billing Request Flows can be created to enable a payer to authorise a 14 | # payment created for a scheme with strong payer 15 | # authorisation (such as open banking single payments). 16 | class BillingRequestFlow 17 | attr_reader :authorisation_url, :auto_fulfil, :created_at, :customer_details_captured, :exit_uri, :expires_at, 18 | :id, :language, :lock_bank_account, :lock_currency, :lock_customer_details, :prefilled_bank_account, :prefilled_customer, :redirect_uri, :session_token, :show_redirect_buttons, :show_success_redirect_button, :skip_success_screen 19 | 20 | # Initialize a billing_request_flow resource instance 21 | # @param object [Hash] an object returned from the API 22 | def initialize(object, response = nil) 23 | @object = object 24 | 25 | @authorisation_url = object['authorisation_url'] 26 | @auto_fulfil = object['auto_fulfil'] 27 | @created_at = object['created_at'] 28 | @customer_details_captured = object['customer_details_captured'] 29 | @exit_uri = object['exit_uri'] 30 | @expires_at = object['expires_at'] 31 | @id = object['id'] 32 | @language = object['language'] 33 | @links = object['links'] 34 | @lock_bank_account = object['lock_bank_account'] 35 | @lock_currency = object['lock_currency'] 36 | @lock_customer_details = object['lock_customer_details'] 37 | @prefilled_bank_account = object['prefilled_bank_account'] 38 | @prefilled_customer = object['prefilled_customer'] 39 | @redirect_uri = object['redirect_uri'] 40 | @session_token = object['session_token'] 41 | @show_redirect_buttons = object['show_redirect_buttons'] 42 | @show_success_redirect_button = object['show_success_redirect_button'] 43 | @skip_success_screen = object['skip_success_screen'] 44 | @response = response 45 | end 46 | 47 | def api_response 48 | ApiResponse.new(@response) 49 | end 50 | 51 | # Return the links that the resource has 52 | def links 53 | @billing_request_flow_links ||= Links.new(@links) 54 | end 55 | 56 | # Provides the billing_request_flow resource as a hash of all its readable attributes 57 | def to_h 58 | @object 59 | end 60 | 61 | class Links 62 | def initialize(links) 63 | @links = links || {} 64 | end 65 | 66 | def billing_request 67 | @links['billing_request'] 68 | end 69 | end 70 | end 71 | end 72 | end 73 | -------------------------------------------------------------------------------- /lib/gocardless_pro/resources/outbound_payment.rb: -------------------------------------------------------------------------------- 1 | # 2 | # This client is automatically generated from a template and JSON schema definition. 3 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 4 | # 5 | 6 | require 'uri' 7 | 8 | module GoCardlessPro 9 | # A module containing classes for each of the resources in the GC Api 10 | module Resources 11 | # Represents an instance of a outbound_payment resource returned from the API 12 | 13 | # Outbound Payments represent payments sent from 14 | # [creditors](#core-endpoints-creditors). 15 | # 16 | # GoCardless will notify you via a [webhook](#appendix-webhooks) when the 17 | # status of the outbound payment [changes](#event-actions-outbound-payment). 18 | # 19 | #

Restricted: Outbound 20 | # Payments are currently in Early Access and available only to a limited 21 | # list of organisations. If you are interested in using this feature, please 22 | # stay tuned for our public launch announcement. We are actively testing and 23 | # refining our API to ensure it meets your needs and provides the best 24 | # experience.

25 | class OutboundPayment 26 | attr_reader :amount, :created_at, :currency, :description, :execution_date, :id, :is_withdrawal, :metadata, 27 | :reference, :scheme, :status, :verifications 28 | 29 | # Initialize a outbound_payment resource instance 30 | # @param object [Hash] an object returned from the API 31 | def initialize(object, response = nil) 32 | @object = object 33 | 34 | @amount = object['amount'] 35 | @created_at = object['created_at'] 36 | @currency = object['currency'] 37 | @description = object['description'] 38 | @execution_date = object['execution_date'] 39 | @id = object['id'] 40 | @is_withdrawal = object['is_withdrawal'] 41 | @links = object['links'] 42 | @metadata = object['metadata'] 43 | @reference = object['reference'] 44 | @scheme = object['scheme'] 45 | @status = object['status'] 46 | @verifications = object['verifications'] 47 | @response = response 48 | end 49 | 50 | def api_response 51 | ApiResponse.new(@response) 52 | end 53 | 54 | # Return the links that the resource has 55 | def links 56 | @outbound_payment_links ||= Links.new(@links) 57 | end 58 | 59 | # Provides the outbound_payment resource as a hash of all its readable attributes 60 | def to_h 61 | @object 62 | end 63 | 64 | class Links 65 | def initialize(links) 66 | @links = links || {} 67 | end 68 | 69 | def creditor 70 | @links['creditor'] 71 | end 72 | 73 | def customer 74 | @links['customer'] 75 | end 76 | 77 | def recipient_bank_account 78 | @links['recipient_bank_account'] 79 | end 80 | end 81 | end 82 | end 83 | end 84 | -------------------------------------------------------------------------------- /lib/gocardless_pro/resources/customer_bank_account.rb: -------------------------------------------------------------------------------- 1 | # 2 | # This client is automatically generated from a template and JSON schema definition. 3 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 4 | # 5 | 6 | require 'uri' 7 | 8 | module GoCardlessPro 9 | # A module containing classes for each of the resources in the GC Api 10 | module Resources 11 | # Represents an instance of a customer_bank_account resource returned from the API 12 | 13 | # Customer Bank Accounts hold the bank details of a 14 | # [customer](#core-endpoints-customers). They always belong to a 15 | # [customer](#core-endpoints-customers), and may be linked to several Direct 16 | # Debit [mandates](#core-endpoints-mandates). 17 | # 18 | # Note that customer bank accounts must be unique, and so you will encounter 19 | # a `bank_account_exists` error if you try to create a duplicate bank 20 | # account. You may wish to handle this by updating the existing record 21 | # instead, the ID of which will be provided as 22 | # `links[customer_bank_account]` in the error response. 23 | # 24 | # _Note:_ To ensure the customer's bank accounts are valid, verify them 25 | # first 26 | # using 27 | # 28 | # [bank_details_lookups](#bank-details-lookups-perform-a-bank-details-lookup), 29 | # before proceeding with creating the accounts 30 | class CustomerBankAccount 31 | attr_reader :account_holder_name, :account_number_ending, :account_type, :bank_account_token, :bank_name, 32 | :country_code, :created_at, :currency, :enabled, :id, :metadata 33 | 34 | # Initialize a customer_bank_account resource instance 35 | # @param object [Hash] an object returned from the API 36 | def initialize(object, response = nil) 37 | @object = object 38 | 39 | @account_holder_name = object['account_holder_name'] 40 | @account_number_ending = object['account_number_ending'] 41 | @account_type = object['account_type'] 42 | @bank_account_token = object['bank_account_token'] 43 | @bank_name = object['bank_name'] 44 | @country_code = object['country_code'] 45 | @created_at = object['created_at'] 46 | @currency = object['currency'] 47 | @enabled = object['enabled'] 48 | @id = object['id'] 49 | @links = object['links'] 50 | @metadata = object['metadata'] 51 | @response = response 52 | end 53 | 54 | def api_response 55 | ApiResponse.new(@response) 56 | end 57 | 58 | # Return the links that the resource has 59 | def links 60 | @customer_bank_account_links ||= Links.new(@links) 61 | end 62 | 63 | # Provides the customer_bank_account resource as a hash of all its readable attributes 64 | def to_h 65 | @object 66 | end 67 | 68 | class Links 69 | def initialize(links) 70 | @links = links || {} 71 | end 72 | 73 | def customer 74 | @links['customer'] 75 | end 76 | end 77 | end 78 | end 79 | end 80 | -------------------------------------------------------------------------------- /spec/resources/bank_account_detail_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe GoCardlessPro::Resources::BankAccountDetail do 4 | let(:client) do 5 | GoCardlessPro::Client.new( 6 | access_token: 'SECRET_TOKEN' 7 | ) 8 | end 9 | 10 | let(:response_headers) { { 'Content-Type' => 'application/json' } } 11 | 12 | describe '#get' do 13 | let(:id) { 'ID123' } 14 | 15 | subject(:get_response) { client.bank_account_details.get(id) } 16 | 17 | context 'passing in a custom header' do 18 | let!(:stub) do 19 | stub_url = '/bank_account_details/:identity'.gsub(':identity', id) 20 | stub_request(:get, /.*api.gocardless.com#{stub_url}/) 21 | .with(headers: { 'Foo' => 'Bar' }) 22 | .to_return( 23 | body: { 24 | 'bank_account_details' => { 25 | 26 | 'ciphertext' => 'ciphertext-input', 27 | 'encrypted_key' => 'encrypted_key-input', 28 | 'iv' => 'iv-input', 29 | 'protected' => 'protected-input', 30 | 'tag' => 'tag-input' 31 | } 32 | }.to_json, 33 | headers: response_headers 34 | ) 35 | end 36 | 37 | subject(:get_response) do 38 | client.bank_account_details.get(id, headers: { 39 | 'Foo' => 'Bar' 40 | }) 41 | end 42 | 43 | it 'includes the header' do 44 | get_response 45 | expect(stub).to have_been_requested 46 | end 47 | end 48 | 49 | context 'when there is a bank_account_detail to return' do 50 | before do 51 | stub_url = '/bank_account_details/:identity'.gsub(':identity', id) 52 | stub_request(:get, /.*api.gocardless.com#{stub_url}/).to_return( 53 | body: { 54 | 'bank_account_details' => { 55 | 56 | 'ciphertext' => 'ciphertext-input', 57 | 'encrypted_key' => 'encrypted_key-input', 58 | 'iv' => 'iv-input', 59 | 'protected' => 'protected-input', 60 | 'tag' => 'tag-input' 61 | } 62 | }.to_json, 63 | headers: response_headers 64 | ) 65 | end 66 | 67 | it 'wraps the response in a resource' do 68 | expect(get_response).to be_a(GoCardlessPro::Resources::BankAccountDetail) 69 | end 70 | end 71 | 72 | context 'when nothing is returned' do 73 | before do 74 | stub_url = '/bank_account_details/:identity'.gsub(':identity', id) 75 | stub_request(:get, /.*api.gocardless.com#{stub_url}/).to_return( 76 | body: '', 77 | headers: response_headers 78 | ) 79 | end 80 | 81 | it 'returns nil' do 82 | expect(get_response).to be_nil 83 | end 84 | end 85 | 86 | context "when an ID is specified which can't be included in a valid URI" do 87 | let(:id) { '`' } 88 | 89 | it "doesn't raise an error" do 90 | expect { get_response }.to_not raise_error(/bad URI/) 91 | end 92 | end 93 | end 94 | end 95 | -------------------------------------------------------------------------------- /lib/gocardless_pro/services/bank_details_lookups_service.rb: -------------------------------------------------------------------------------- 1 | require_relative './base_service' 2 | 3 | # encoding: utf-8 4 | # 5 | # This client is automatically generated from a template and JSON schema definition. 6 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 7 | # 8 | 9 | module GoCardlessPro 10 | module Services 11 | # Service for making requests to the BankDetailsLookup endpoints 12 | class BankDetailsLookupsService < BaseService 13 | # Performs a bank details lookup. As part of the lookup, a modulus check and 14 | # reachability check are performed. 15 | # 16 | # For UK-based bank accounts, where an account holder name is provided (and an 17 | # account number, a sort code or an iban 18 | # are already present), we verify that the account holder name and bank account 19 | # number match the details held by 20 | # the relevant bank. 21 | # 22 | # If your request returns an [error](#api-usage-errors) or the 23 | # `available_debit_schemes` 24 | # attribute is an empty array, you will not be able to collect payments from the 25 | # specified bank account. GoCardless may be able to collect payments from an 26 | # account 27 | # even if no `bic` is returned. 28 | # 29 | # Bank account details may be supplied using [local 30 | # details](#appendix-local-bank-details) or an IBAN. 31 | # 32 | # _ACH scheme_ For compliance reasons, an extra validation step is done using 33 | # a third-party provider to make sure the customer's bank account can accept 34 | # Direct Debit. If a bank account is discovered to be closed or invalid, the 35 | # customer is requested to adjust the account number/routing number and 36 | # succeed in this check to continue with the flow. 37 | # 38 | # _Note:_ Usage of this endpoint is monitored. If your organisation relies on 39 | # GoCardless for 40 | # modulus or reachability checking but not for payment collection, please get in 41 | # touch. 42 | # Example URL: /bank_details_lookups 43 | # @param options [Hash] parameters as a hash, under a params key. 44 | def create(options = {}) 45 | path = '/bank_details_lookups' 46 | 47 | params = options.delete(:params) || {} 48 | options[:params] = {} 49 | options[:params][envelope_key] = params 50 | 51 | options[:retry_failures] = true 52 | 53 | response = make_request(:post, path, options) 54 | 55 | return if response.body.nil? 56 | 57 | Resources::BankDetailsLookup.new(unenvelope_body(response.body), response) 58 | end 59 | 60 | private 61 | 62 | # Unenvelope the response of the body using the service's `envelope_key` 63 | # 64 | # @param body [Hash] 65 | def unenvelope_body(body) 66 | body[envelope_key] || body['data'] 67 | end 68 | 69 | # return the key which API responses will envelope data under 70 | def envelope_key 71 | 'bank_details_lookups' 72 | end 73 | end 74 | end 75 | end 76 | -------------------------------------------------------------------------------- /spec/services/customer_notifications_service_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe GoCardlessPro::Services::CustomerNotificationsService do 4 | let(:client) do 5 | GoCardlessPro::Client.new( 6 | access_token: 'SECRET_TOKEN' 7 | ) 8 | end 9 | 10 | let(:response_headers) { { 'Content-Type' => 'application/json' } } 11 | 12 | describe '#handle' do 13 | subject(:post_response) { client.customer_notifications.handle(resource_id) } 14 | 15 | let(:resource_id) { 'ABC123' } 16 | 17 | let!(:stub) do 18 | # /customer_notifications/%v/actions/handle 19 | stub_url = '/customer_notifications/:identity/actions/handle'.gsub(':identity', resource_id) 20 | stub_request(:post, /.*api.gocardless.com#{stub_url}/).to_return( 21 | body: { 22 | 'customer_notifications' => { 23 | 24 | 'action_taken' => 'action_taken-input', 25 | 'action_taken_at' => 'action_taken_at-input', 26 | 'action_taken_by' => 'action_taken_by-input', 27 | 'id' => 'id-input', 28 | 'links' => 'links-input', 29 | 'type' => 'type-input' 30 | } 31 | }.to_json, 32 | 33 | headers: response_headers 34 | ) 35 | end 36 | 37 | it 'wraps the response and calls the right endpoint' do 38 | expect(post_response).to be_a(GoCardlessPro::Resources::CustomerNotification) 39 | 40 | expect(stub).to have_been_requested 41 | end 42 | 43 | describe 'retry behaviour' do 44 | it "doesn't retry errors" do 45 | stub_url = '/customer_notifications/:identity/actions/handle'.gsub(':identity', resource_id) 46 | stub = stub_request(:post, /.*api.gocardless.com#{stub_url}/) 47 | .to_timeout 48 | 49 | expect { post_response }.to raise_error(Faraday::ConnectionFailed) 50 | expect(stub).to have_been_requested 51 | end 52 | end 53 | 54 | context 'when the request needs a body and custom header' do 55 | let(:body) { { foo: 'bar' } } 56 | let(:headers) { { 'Foo' => 'Bar' } } 57 | subject(:post_response) { client.customer_notifications.handle(resource_id, body, headers) } 58 | 59 | let(:resource_id) { 'ABC123' } 60 | 61 | let!(:stub) do 62 | # /customer_notifications/%v/actions/handle 63 | stub_url = '/customer_notifications/:identity/actions/handle'.gsub(':identity', resource_id) 64 | stub_request(:post, /.*api.gocardless.com#{stub_url}/) 65 | .with( 66 | body: { foo: 'bar' }, 67 | headers: { 'Foo' => 'Bar' } 68 | ).to_return( 69 | body: { 70 | 'customer_notifications' => { 71 | 72 | 'action_taken' => 'action_taken-input', 73 | 'action_taken_at' => 'action_taken_at-input', 74 | 'action_taken_by' => 'action_taken_by-input', 75 | 'id' => 'id-input', 76 | 'links' => 'links-input', 77 | 'type' => 'type-input' 78 | } 79 | }.to_json, 80 | headers: response_headers 81 | ) 82 | end 83 | end 84 | end 85 | end 86 | -------------------------------------------------------------------------------- /lib/gocardless_pro/resources/block.rb: -------------------------------------------------------------------------------- 1 | # 2 | # This client is automatically generated from a template and JSON schema definition. 3 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 4 | # 5 | 6 | require 'uri' 7 | 8 | module GoCardlessPro 9 | # A module containing classes for each of the resources in the GC Api 10 | module Resources 11 | # Represents an instance of a block resource returned from the API 12 | 13 | # Blocks are created to prevent certain customer details from being used 14 | # when creating 15 | # mandates. 16 | # 17 | # The details used to create blocks can be exact matches, like a bank 18 | # account or an email, 19 | # or a more generic match such as an email domain or bank name. Please be 20 | # careful when creating 21 | # blocks for more generic matches as this may block legitimate payers from 22 | # using your service. 23 | # 24 | # New block types may be added over time. 25 | # 26 | # A block is in essence a simple rule that is used to match against details 27 | # in a newly 28 | # created mandate. If there is a successful match then the mandate is 29 | # transitioned to a 30 | # "blocked" state. 31 | # 32 | # Please note: 33 | # 34 | # - Payments and subscriptions cannot be created against a mandate in 35 | # blocked state. 36 | # - A mandate can never be transitioned out of the blocked state. 37 | # 38 | # The one exception to this is when blocking a 'bank_name'. This block will 39 | # prevent bank 40 | # accounts from being created for banks that match the given name. To ensure 41 | # we match 42 | # bank names correctly an existing bank account must be used when creating 43 | # this block. Please 44 | # be aware that we cannot always match a bank account to a given bank name. 45 | # 46 | #

47 | # This API is currently only available for GoCardless Protect+ integrators 48 | # - please get in touch if you 49 | # would like to use this API. 50 | #

51 | class Block 52 | attr_reader :active, :block_type, :created_at, :id, :reason_description, :reason_type, :resource_reference, 53 | :updated_at 54 | 55 | # Initialize a block resource instance 56 | # @param object [Hash] an object returned from the API 57 | def initialize(object, response = nil) 58 | @object = object 59 | 60 | @active = object['active'] 61 | @block_type = object['block_type'] 62 | @created_at = object['created_at'] 63 | @id = object['id'] 64 | @reason_description = object['reason_description'] 65 | @reason_type = object['reason_type'] 66 | @resource_reference = object['resource_reference'] 67 | @updated_at = object['updated_at'] 68 | @response = response 69 | end 70 | 71 | def api_response 72 | ApiResponse.new(@response) 73 | end 74 | 75 | # Provides the block resource as a hash of all its readable attributes 76 | def to_h 77 | @object 78 | end 79 | end 80 | end 81 | end 82 | -------------------------------------------------------------------------------- /lib/gocardless_pro/services/mandate_pdfs_service.rb: -------------------------------------------------------------------------------- 1 | require_relative './base_service' 2 | 3 | # encoding: utf-8 4 | # 5 | # This client is automatically generated from a template and JSON schema definition. 6 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 7 | # 8 | 9 | module GoCardlessPro 10 | module Services 11 | # Service for making requests to the MandatePdf endpoints 12 | class MandatePdfsService < BaseService 13 | # Generates a PDF mandate and returns its temporary URL. 14 | # 15 | # Customer and bank account details can be left blank (for a blank mandate), 16 | # provided manually, or inferred from the ID of an existing 17 | # [mandate](#core-endpoints-mandates). 18 | # 19 | # By default, we'll generate PDF mandates in English. 20 | # 21 | # To generate a PDF mandate in another language, set the `Accept-Language` 22 | # header when creating the PDF mandate to the relevant [ISO 23 | # 639-1](http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) language code 24 | # supported for the scheme. 25 | # 26 | # | Scheme | Supported languages 27 | # 28 | # | 29 | # | :--------------- | 30 | # :------------------------------------------------------------------------------------------------------------------------------------------- 31 | # | 32 | # | ACH | English (`en`) 33 | # 34 | # | 35 | # | Autogiro | English (`en`), Swedish (`sv`) 36 | # 37 | # | 38 | # | Bacs | English (`en`) 39 | # 40 | # | 41 | # | BECS | English (`en`) 42 | # 43 | # | 44 | # | BECS NZ | English (`en`) 45 | # 46 | # | 47 | # | Betalingsservice | Danish (`da`), English (`en`) 48 | # 49 | # | 50 | # | PAD | English (`en`) 51 | # 52 | # | 53 | # | SEPA Core | Danish (`da`), Dutch (`nl`), English (`en`), French 54 | # (`fr`), German (`de`), Italian (`it`), Portuguese (`pt`), Spanish (`es`), 55 | # Swedish (`sv`) | 56 | # Example URL: /mandate_pdfs 57 | # @param options [Hash] parameters as a hash, under a params key. 58 | def create(options = {}) 59 | path = '/mandate_pdfs' 60 | 61 | params = options.delete(:params) || {} 62 | options[:params] = {} 63 | options[:params][envelope_key] = params 64 | 65 | options[:retry_failures] = true 66 | 67 | response = make_request(:post, path, options) 68 | 69 | return if response.body.nil? 70 | 71 | Resources::MandatePdf.new(unenvelope_body(response.body), response) 72 | end 73 | 74 | private 75 | 76 | # Unenvelope the response of the body using the service's `envelope_key` 77 | # 78 | # @param body [Hash] 79 | def unenvelope_body(body) 80 | body[envelope_key] || body['data'] 81 | end 82 | 83 | # return the key which API responses will envelope data under 84 | def envelope_key 85 | 'mandate_pdfs' 86 | end 87 | end 88 | end 89 | end 90 | -------------------------------------------------------------------------------- /lib/gocardless_pro/request.rb: -------------------------------------------------------------------------------- 1 | require 'securerandom' 2 | 3 | module GoCardlessPro 4 | # A class that wraps an API request 5 | class Request 6 | MAX_RETRIES = 3 7 | RETRY_DELAY = 0.5 8 | RETRYABLE_EXCEPTIONS = [Faraday::TimeoutError, 9 | Faraday::ConnectionFailed, 10 | GoCardlessPro::ApiError, 11 | GoCardlessPro::GoCardlessError].freeze 12 | 13 | # Initialize a request class, which makes calls to the API 14 | # @param connection 15 | # @param method [Symbol] the method to make the request with 16 | # @param path [String] the path to make the request to 17 | # @param options [hash] options for the request 18 | # @param headers [hash] headers to send with the request 19 | def initialize(connection, method, path, options) 20 | @connection = connection 21 | @method = method 22 | @path = path 23 | @headers = (options.delete(:headers) || {}).each_with_object({}) do |(k, v), hsh| 24 | hsh[k.to_s] = v 25 | end 26 | @envelope_name = options.delete(:envelope_key) 27 | @retry_failures = options.delete(:retry_failures) { true } 28 | @given_options = options 29 | 30 | @request_body = request_body 31 | 32 | if @request_body.is_a?(Hash) 33 | @request_body = @request_body.to_json 34 | @headers['Content-Type'] ||= 'application/json' 35 | end 36 | 37 | @headers['Idempotency-Key'] ||= SecureRandom.uuid if @method == :post 38 | end 39 | 40 | # Make the request and wrap it in a Response object 41 | def request 42 | if @retry_failures 43 | with_retries { Response.new(make_request) } 44 | else 45 | Response.new(make_request) 46 | end 47 | end 48 | 49 | def with_retries 50 | requests_attempted = 0 51 | total_requests_allowed = MAX_RETRIES 52 | 53 | begin 54 | yield 55 | rescue StandardError => e 56 | requests_attempted += 1 57 | 58 | raise e unless requests_attempted < total_requests_allowed && should_retry?(e) 59 | 60 | sleep(RETRY_DELAY) 61 | retry 62 | end 63 | end 64 | 65 | # Make the API request 66 | def make_request 67 | @connection.send(@method) do |request| 68 | request.url @path 69 | request.body = @request_body 70 | request.params = request_query 71 | request.headers.merge!(@headers) 72 | end 73 | end 74 | 75 | # Fetch the body to send with the request 76 | def request_body 77 | if @method == :get 78 | nil 79 | elsif %i[post put delete].include?(@method) 80 | @given_options.fetch(:params, {}) 81 | else 82 | raise "Unknown request method #{@method}" 83 | end 84 | end 85 | 86 | # Get the query params to send with the request 87 | def request_query 88 | if @method == :get 89 | @given_options.fetch(:params, {}) 90 | else 91 | {} 92 | end 93 | end 94 | 95 | private 96 | 97 | def should_retry?(exception) 98 | RETRYABLE_EXCEPTIONS.include?(exception.class) 99 | end 100 | end 101 | end 102 | -------------------------------------------------------------------------------- /lib/gocardless_pro/services/mandate_import_entries_service.rb: -------------------------------------------------------------------------------- 1 | require_relative './base_service' 2 | 3 | # encoding: utf-8 4 | # 5 | # This client is automatically generated from a template and JSON schema definition. 6 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 7 | # 8 | 9 | module GoCardlessPro 10 | module Services 11 | # Service for making requests to the MandateImportEntry endpoints 12 | class MandateImportEntriesService < BaseService 13 | # For an existing [mandate import](#core-endpoints-mandate-imports), this 14 | # endpoint can 15 | # be used to add individual mandates to be imported into GoCardless. 16 | # 17 | # You can add no more than 30,000 rows to a single mandate import. 18 | # If you attempt to go over this limit, the API will return a 19 | # `record_limit_exceeded` error. 20 | # Example URL: /mandate_import_entries 21 | # @param options [Hash] parameters as a hash, under a params key. 22 | def create(options = {}) 23 | path = '/mandate_import_entries' 24 | 25 | params = options.delete(:params) || {} 26 | options[:params] = {} 27 | options[:params][envelope_key] = params 28 | 29 | options[:retry_failures] = true 30 | 31 | response = make_request(:post, path, options) 32 | 33 | return if response.body.nil? 34 | 35 | Resources::MandateImportEntry.new(unenvelope_body(response.body), response) 36 | end 37 | 38 | # For an existing mandate import, this endpoint lists all of the entries 39 | # attached. 40 | # 41 | # After a mandate import has been submitted, you can use this endpoint to 42 | # associate records 43 | # in your system (using the `record_identifier` that you provided when creating 44 | # the 45 | # mandate import). 46 | # 47 | # Example URL: /mandate_import_entries 48 | # @param options [Hash] parameters as a hash, under a params key. 49 | def list(options = {}) 50 | path = '/mandate_import_entries' 51 | 52 | options[:retry_failures] = true 53 | 54 | response = make_request(:get, path, options) 55 | 56 | ListResponse.new( 57 | response: response, 58 | unenveloped_body: unenvelope_body(response.body), 59 | resource_class: Resources::MandateImportEntry 60 | ) 61 | end 62 | 63 | # Get a lazily enumerated list of all the items returned. This is similar to the `list` method but will paginate for you automatically. 64 | # 65 | # @param options [Hash] parameters as a hash. If the request is a GET, these will be converted to query parameters. 66 | # Otherwise they will be the body of the request. 67 | def all(options = {}) 68 | Paginator.new( 69 | service: self, 70 | options: options 71 | ).enumerator 72 | end 73 | 74 | private 75 | 76 | # Unenvelope the response of the body using the service's `envelope_key` 77 | # 78 | # @param body [Hash] 79 | def unenvelope_body(body) 80 | body[envelope_key] || body['data'] 81 | end 82 | 83 | # return the key which API responses will envelope data under 84 | def envelope_key 85 | 'mandate_import_entries' 86 | end 87 | end 88 | end 89 | end 90 | -------------------------------------------------------------------------------- /spec/resources/payout_item_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe GoCardlessPro::Resources::PayoutItem do 4 | let(:client) do 5 | GoCardlessPro::Client.new( 6 | access_token: 'SECRET_TOKEN' 7 | ) 8 | end 9 | 10 | let(:response_headers) { { 'Content-Type' => 'application/json' } } 11 | 12 | describe '#list' do 13 | describe 'with no filters' do 14 | subject(:get_list_response) { client.payout_items.list } 15 | 16 | before do 17 | stub_request(:get, %r{.*api.gocardless.com/payout_items}).to_return( 18 | body: { 19 | 'payout_items' => [{ 20 | 21 | 'amount' => 'amount-input', 22 | 'links' => 'links-input', 23 | 'taxes' => 'taxes-input', 24 | 'type' => 'type-input' 25 | }], 26 | meta: { 27 | cursors: { 28 | before: nil, 29 | after: 'ABC123' 30 | } 31 | } 32 | }.to_json, 33 | headers: response_headers 34 | ) 35 | end 36 | 37 | it 'wraps each item in the resource class' do 38 | expect(get_list_response.records.map { |x| x.class }.uniq.first).to eq(GoCardlessPro::Resources::PayoutItem) 39 | 40 | expect(get_list_response.records.first.amount).to eq('amount-input') 41 | 42 | expect(get_list_response.records.first.taxes).to eq('taxes-input') 43 | 44 | expect(get_list_response.records.first.type).to eq('type-input') 45 | end 46 | 47 | it 'exposes the cursors for before and after' do 48 | expect(get_list_response.before).to eq(nil) 49 | expect(get_list_response.after).to eq('ABC123') 50 | end 51 | 52 | specify { expect(get_list_response.api_response.headers).to eql('content-type' => 'application/json') } 53 | end 54 | end 55 | 56 | describe '#all' do 57 | let!(:first_response_stub) do 58 | stub_request(:get, %r{.*api.gocardless.com/payout_items$}).to_return( 59 | body: { 60 | 'payout_items' => [{ 61 | 62 | 'amount' => 'amount-input', 63 | 'links' => 'links-input', 64 | 'taxes' => 'taxes-input', 65 | 'type' => 'type-input' 66 | }], 67 | meta: { 68 | cursors: { after: 'AB345' }, 69 | limit: 1 70 | } 71 | }.to_json, 72 | headers: response_headers 73 | ) 74 | end 75 | 76 | let!(:second_response_stub) do 77 | stub_request(:get, %r{.*api.gocardless.com/payout_items\?after=AB345}).to_return( 78 | body: { 79 | 'payout_items' => [{ 80 | 81 | 'amount' => 'amount-input', 82 | 'links' => 'links-input', 83 | 'taxes' => 'taxes-input', 84 | 'type' => 'type-input' 85 | }], 86 | meta: { 87 | limit: 2, 88 | cursors: {} 89 | } 90 | }.to_json, 91 | headers: response_headers 92 | ) 93 | end 94 | 95 | it 'automatically makes the extra requests' do 96 | expect(client.payout_items.all.to_a.length).to eq(2) 97 | expect(first_response_stub).to have_been_requested 98 | expect(second_response_stub).to have_been_requested 99 | end 100 | end 101 | end 102 | -------------------------------------------------------------------------------- /lib/gocardless_pro/resources/billing_request_template.rb: -------------------------------------------------------------------------------- 1 | # 2 | # This client is automatically generated from a template and JSON schema definition. 3 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 4 | # 5 | 6 | require 'uri' 7 | 8 | module GoCardlessPro 9 | # A module containing classes for each of the resources in the GC Api 10 | module Resources 11 | # Represents an instance of a billing_request_template resource returned from the API 12 | 13 | # Billing Request Templates are reusable templates that result in 14 | # numerous Billing Requests with similar attributes. They provide 15 | # a no-code solution for generating various types of multi-user payment 16 | # links. 17 | # 18 | # Each template includes a reusable URL that can be embedded in a website 19 | # or shared with customers via email. Every time the URL is opened, 20 | # it generates a new Billing Request. 21 | # 22 | # Billing Request Templates overcome the key limitation of the Billing 23 | # Request: 24 | # a Billing Request cannot be shared among multiple users because it is 25 | # intended 26 | # for single-use and is designed to cater to the unique needs of individual 27 | # customers. 28 | class BillingRequestTemplate 29 | attr_reader :authorisation_url, :created_at, :id, :mandate_request_constraints, :mandate_request_currency, 30 | :mandate_request_description, :mandate_request_metadata, :mandate_request_scheme, :mandate_request_verify, :metadata, :name, :payment_request_amount, :payment_request_currency, :payment_request_description, :payment_request_metadata, :payment_request_scheme, :redirect_uri, :updated_at 31 | 32 | # Initialize a billing_request_template resource instance 33 | # @param object [Hash] an object returned from the API 34 | def initialize(object, response = nil) 35 | @object = object 36 | 37 | @authorisation_url = object['authorisation_url'] 38 | @created_at = object['created_at'] 39 | @id = object['id'] 40 | @mandate_request_constraints = object['mandate_request_constraints'] 41 | @mandate_request_currency = object['mandate_request_currency'] 42 | @mandate_request_description = object['mandate_request_description'] 43 | @mandate_request_metadata = object['mandate_request_metadata'] 44 | @mandate_request_scheme = object['mandate_request_scheme'] 45 | @mandate_request_verify = object['mandate_request_verify'] 46 | @metadata = object['metadata'] 47 | @name = object['name'] 48 | @payment_request_amount = object['payment_request_amount'] 49 | @payment_request_currency = object['payment_request_currency'] 50 | @payment_request_description = object['payment_request_description'] 51 | @payment_request_metadata = object['payment_request_metadata'] 52 | @payment_request_scheme = object['payment_request_scheme'] 53 | @redirect_uri = object['redirect_uri'] 54 | @updated_at = object['updated_at'] 55 | @response = response 56 | end 57 | 58 | def api_response 59 | ApiResponse.new(@response) 60 | end 61 | 62 | # Provides the billing_request_template resource as a hash of all its readable attributes 63 | def to_h 64 | @object 65 | end 66 | end 67 | end 68 | end 69 | -------------------------------------------------------------------------------- /spec/resources/logo_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe GoCardlessPro::Resources::Logo do 4 | let(:client) do 5 | GoCardlessPro::Client.new( 6 | access_token: 'SECRET_TOKEN' 7 | ) 8 | end 9 | 10 | let(:response_headers) { { 'Content-Type' => 'application/json' } } 11 | 12 | describe '#create' do 13 | subject(:post_create_response) { client.logos.create_for_creditor(params: new_resource) } 14 | context 'with a valid request' do 15 | let(:new_resource) do 16 | { 17 | 18 | 'id' => 'id-input' 19 | } 20 | end 21 | 22 | before do 23 | stub_request(:post, %r{.*api.gocardless.com/branding/logos}) 24 | .with( 25 | body: { 26 | 'logos' => { 27 | 28 | 'id' => 'id-input' 29 | } 30 | } 31 | ) 32 | .to_return( 33 | body: { 34 | 'logos' => 35 | 36 | { 37 | 38 | 'id' => 'id-input' 39 | } 40 | 41 | }.to_json, 42 | headers: response_headers 43 | ) 44 | end 45 | 46 | it 'creates and returns the resource' do 47 | expect(post_create_response).to be_a(GoCardlessPro::Resources::Logo) 48 | end 49 | end 50 | 51 | context 'with a request that returns a validation error' do 52 | let(:new_resource) { {} } 53 | 54 | before do 55 | stub_request(:post, %r{.*api.gocardless.com/branding/logos}).to_return( 56 | body: { 57 | error: { 58 | type: 'validation_failed', 59 | code: 422, 60 | errors: [ 61 | { message: 'test error message', field: 'test_field' } 62 | ] 63 | } 64 | }.to_json, 65 | headers: response_headers, 66 | status: 422 67 | ) 68 | end 69 | 70 | it 'throws the correct error' do 71 | expect { post_create_response }.to raise_error(GoCardlessPro::ValidationError) 72 | end 73 | end 74 | 75 | context 'with a request that returns an idempotent creation conflict error' do 76 | let(:id) { 'ID123' } 77 | 78 | let(:new_resource) do 79 | { 80 | 81 | 'id' => 'id-input' 82 | } 83 | end 84 | 85 | let!(:post_stub) do 86 | stub_request(:post, %r{.*api.gocardless.com/branding/logos}).to_return( 87 | body: { 88 | error: { 89 | type: 'invalid_state', 90 | code: 409, 91 | errors: [ 92 | { 93 | message: 'A resource has already been created with this idempotency key', 94 | reason: 'idempotent_creation_conflict', 95 | links: { 96 | conflicting_resource_id: id 97 | } 98 | } 99 | ] 100 | } 101 | }.to_json, 102 | headers: response_headers, 103 | status: 409 104 | ) 105 | end 106 | 107 | it 'raises an InvalidStateError' do 108 | expect { post_create_response }.to raise_error(GoCardlessPro::InvalidStateError) 109 | expect(post_stub).to have_been_requested 110 | end 111 | end 112 | end 113 | end 114 | -------------------------------------------------------------------------------- /lib/gocardless_pro/resources/mandate_import_entry.rb: -------------------------------------------------------------------------------- 1 | # 2 | # This client is automatically generated from a template and JSON schema definition. 3 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 4 | # 5 | 6 | require 'uri' 7 | 8 | module GoCardlessPro 9 | # A module containing classes for each of the resources in the GC Api 10 | module Resources 11 | # Represents an instance of a mandate_import_entry resource returned from the API 12 | 13 | # Mandate Import Entries are added to a [Mandate 14 | # Import](#core-endpoints-mandate-imports). 15 | # Each entry corresponds to one mandate to be imported into GoCardless. 16 | # 17 | # To import a mandate you will need: 18 | #
    19 | #
  1. Identifying information about the customer (name/company and 20 | # address)
  2. 21 | #
  3. Bank account details, consisting of an account holder name and 22 | # either an IBAN or local bank 23 | # details
  4. 24 | #
  5. Amendment details (SEPA only)
  6. 25 | #
26 | # 27 | # We suggest you provide a `record_identifier` (which is unique within the 28 | # context of a 29 | # single mandate import) to help you to identify mandates that have been 30 | # created once the 31 | # import has been processed by GoCardless. You can 32 | # [list the mandate import 33 | # entries](#mandate-import-entries-list-all-mandate-import-entries), 34 | # match them up in your system using the `record_identifier`, and look at 35 | # the `links` 36 | # fields to find the mandate, customer and customer bank account that have 37 | # been imported. 38 | # 39 | #

Restricted: This API is 40 | # currently only available for approved integrators - please get in touch if you would like to 42 | # use this API.

43 | class MandateImportEntry 44 | attr_reader :created_at, :processing_errors, :record_identifier 45 | 46 | # Initialize a mandate_import_entry resource instance 47 | # @param object [Hash] an object returned from the API 48 | def initialize(object, response = nil) 49 | @object = object 50 | 51 | @created_at = object['created_at'] 52 | @links = object['links'] 53 | @processing_errors = object['processing_errors'] 54 | @record_identifier = object['record_identifier'] 55 | @response = response 56 | end 57 | 58 | def api_response 59 | ApiResponse.new(@response) 60 | end 61 | 62 | # Return the links that the resource has 63 | def links 64 | @mandate_import_entry_links ||= Links.new(@links) 65 | end 66 | 67 | # Provides the mandate_import_entry resource as a hash of all its readable attributes 68 | def to_h 69 | @object 70 | end 71 | 72 | class Links 73 | def initialize(links) 74 | @links = links || {} 75 | end 76 | 77 | def customer 78 | @links['customer'] 79 | end 80 | 81 | def customer_bank_account 82 | @links['customer_bank_account'] 83 | end 84 | 85 | def mandate 86 | @links['mandate'] 87 | end 88 | 89 | def mandate_import 90 | @links['mandate_import'] 91 | end 92 | end 93 | end 94 | end 95 | end 96 | -------------------------------------------------------------------------------- /spec/resources/payer_theme_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe GoCardlessPro::Resources::PayerTheme do 4 | let(:client) do 5 | GoCardlessPro::Client.new( 6 | access_token: 'SECRET_TOKEN' 7 | ) 8 | end 9 | 10 | let(:response_headers) { { 'Content-Type' => 'application/json' } } 11 | 12 | describe '#create' do 13 | subject(:post_create_response) { client.payer_themes.create_for_creditor(params: new_resource) } 14 | context 'with a valid request' do 15 | let(:new_resource) do 16 | { 17 | 18 | 'id' => 'id-input' 19 | } 20 | end 21 | 22 | before do 23 | stub_request(:post, %r{.*api.gocardless.com/branding/payer_themes}) 24 | .with( 25 | body: { 26 | 'payer_themes' => { 27 | 28 | 'id' => 'id-input' 29 | } 30 | } 31 | ) 32 | .to_return( 33 | body: { 34 | 'payer_themes' => 35 | 36 | { 37 | 38 | 'id' => 'id-input' 39 | } 40 | 41 | }.to_json, 42 | headers: response_headers 43 | ) 44 | end 45 | 46 | it 'creates and returns the resource' do 47 | expect(post_create_response).to be_a(GoCardlessPro::Resources::PayerTheme) 48 | end 49 | end 50 | 51 | context 'with a request that returns a validation error' do 52 | let(:new_resource) { {} } 53 | 54 | before do 55 | stub_request(:post, %r{.*api.gocardless.com/branding/payer_themes}).to_return( 56 | body: { 57 | error: { 58 | type: 'validation_failed', 59 | code: 422, 60 | errors: [ 61 | { message: 'test error message', field: 'test_field' } 62 | ] 63 | } 64 | }.to_json, 65 | headers: response_headers, 66 | status: 422 67 | ) 68 | end 69 | 70 | it 'throws the correct error' do 71 | expect { post_create_response }.to raise_error(GoCardlessPro::ValidationError) 72 | end 73 | end 74 | 75 | context 'with a request that returns an idempotent creation conflict error' do 76 | let(:id) { 'ID123' } 77 | 78 | let(:new_resource) do 79 | { 80 | 81 | 'id' => 'id-input' 82 | } 83 | end 84 | 85 | let!(:post_stub) do 86 | stub_request(:post, %r{.*api.gocardless.com/branding/payer_themes}).to_return( 87 | body: { 88 | error: { 89 | type: 'invalid_state', 90 | code: 409, 91 | errors: [ 92 | { 93 | message: 'A resource has already been created with this idempotency key', 94 | reason: 'idempotent_creation_conflict', 95 | links: { 96 | conflicting_resource_id: id 97 | } 98 | } 99 | ] 100 | } 101 | }.to_json, 102 | headers: response_headers, 103 | status: 409 104 | ) 105 | end 106 | 107 | it 'raises an InvalidStateError' do 108 | expect { post_create_response }.to raise_error(GoCardlessPro::InvalidStateError) 109 | expect(post_stub).to have_been_requested 110 | end 111 | end 112 | end 113 | end 114 | -------------------------------------------------------------------------------- /spec/resources/currency_exchange_rate_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe GoCardlessPro::Resources::CurrencyExchangeRate do 4 | let(:client) do 5 | GoCardlessPro::Client.new( 6 | access_token: 'SECRET_TOKEN' 7 | ) 8 | end 9 | 10 | let(:response_headers) { { 'Content-Type' => 'application/json' } } 11 | 12 | describe '#list' do 13 | describe 'with no filters' do 14 | subject(:get_list_response) { client.currency_exchange_rates.list } 15 | 16 | before do 17 | stub_request(:get, %r{.*api.gocardless.com/currency_exchange_rates}).to_return( 18 | body: { 19 | 'currency_exchange_rates' => [{ 20 | 21 | 'rate' => 'rate-input', 22 | 'source' => 'source-input', 23 | 'target' => 'target-input', 24 | 'time' => 'time-input' 25 | }], 26 | meta: { 27 | cursors: { 28 | before: nil, 29 | after: 'ABC123' 30 | } 31 | } 32 | }.to_json, 33 | headers: response_headers 34 | ) 35 | end 36 | 37 | it 'wraps each item in the resource class' do 38 | expect(get_list_response.records.map do |x| 39 | x.class 40 | end.uniq.first).to eq(GoCardlessPro::Resources::CurrencyExchangeRate) 41 | 42 | expect(get_list_response.records.first.rate).to eq('rate-input') 43 | 44 | expect(get_list_response.records.first.source).to eq('source-input') 45 | 46 | expect(get_list_response.records.first.target).to eq('target-input') 47 | 48 | expect(get_list_response.records.first.time).to eq('time-input') 49 | end 50 | 51 | it 'exposes the cursors for before and after' do 52 | expect(get_list_response.before).to eq(nil) 53 | expect(get_list_response.after).to eq('ABC123') 54 | end 55 | 56 | specify { expect(get_list_response.api_response.headers).to eql('content-type' => 'application/json') } 57 | end 58 | end 59 | 60 | describe '#all' do 61 | let!(:first_response_stub) do 62 | stub_request(:get, %r{.*api.gocardless.com/currency_exchange_rates$}).to_return( 63 | body: { 64 | 'currency_exchange_rates' => [{ 65 | 66 | 'rate' => 'rate-input', 67 | 'source' => 'source-input', 68 | 'target' => 'target-input', 69 | 'time' => 'time-input' 70 | }], 71 | meta: { 72 | cursors: { after: 'AB345' }, 73 | limit: 1 74 | } 75 | }.to_json, 76 | headers: response_headers 77 | ) 78 | end 79 | 80 | let!(:second_response_stub) do 81 | stub_request(:get, %r{.*api.gocardless.com/currency_exchange_rates\?after=AB345}).to_return( 82 | body: { 83 | 'currency_exchange_rates' => [{ 84 | 85 | 'rate' => 'rate-input', 86 | 'source' => 'source-input', 87 | 'target' => 'target-input', 88 | 'time' => 'time-input' 89 | }], 90 | meta: { 91 | limit: 2, 92 | cursors: {} 93 | } 94 | }.to_json, 95 | headers: response_headers 96 | ) 97 | end 98 | 99 | it 'automatically makes the extra requests' do 100 | expect(client.currency_exchange_rates.all.to_a.length).to eq(2) 101 | expect(first_response_stub).to have_been_requested 102 | expect(second_response_stub).to have_been_requested 103 | end 104 | end 105 | end 106 | -------------------------------------------------------------------------------- /spec/resources/mandate_pdf_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe GoCardlessPro::Resources::MandatePdf do 4 | let(:client) do 5 | GoCardlessPro::Client.new( 6 | access_token: 'SECRET_TOKEN' 7 | ) 8 | end 9 | 10 | let(:response_headers) { { 'Content-Type' => 'application/json' } } 11 | 12 | describe '#create' do 13 | subject(:post_create_response) { client.mandate_pdfs.create(params: new_resource) } 14 | context 'with a valid request' do 15 | let(:new_resource) do 16 | { 17 | 18 | 'expires_at' => 'expires_at-input', 19 | 'url' => 'url-input' 20 | } 21 | end 22 | 23 | before do 24 | stub_request(:post, %r{.*api.gocardless.com/mandate_pdfs}) 25 | .with( 26 | body: { 27 | 'mandate_pdfs' => { 28 | 29 | 'expires_at' => 'expires_at-input', 30 | 'url' => 'url-input' 31 | } 32 | } 33 | ) 34 | .to_return( 35 | body: { 36 | 'mandate_pdfs' => 37 | 38 | { 39 | 40 | 'expires_at' => 'expires_at-input', 41 | 'url' => 'url-input' 42 | } 43 | 44 | }.to_json, 45 | headers: response_headers 46 | ) 47 | end 48 | 49 | it 'creates and returns the resource' do 50 | expect(post_create_response).to be_a(GoCardlessPro::Resources::MandatePdf) 51 | end 52 | end 53 | 54 | context 'with a request that returns a validation error' do 55 | let(:new_resource) { {} } 56 | 57 | before do 58 | stub_request(:post, %r{.*api.gocardless.com/mandate_pdfs}).to_return( 59 | body: { 60 | error: { 61 | type: 'validation_failed', 62 | code: 422, 63 | errors: [ 64 | { message: 'test error message', field: 'test_field' } 65 | ] 66 | } 67 | }.to_json, 68 | headers: response_headers, 69 | status: 422 70 | ) 71 | end 72 | 73 | it 'throws the correct error' do 74 | expect { post_create_response }.to raise_error(GoCardlessPro::ValidationError) 75 | end 76 | end 77 | 78 | context 'with a request that returns an idempotent creation conflict error' do 79 | let(:id) { 'ID123' } 80 | 81 | let(:new_resource) do 82 | { 83 | 84 | 'expires_at' => 'expires_at-input', 85 | 'url' => 'url-input' 86 | } 87 | end 88 | 89 | let!(:post_stub) do 90 | stub_request(:post, %r{.*api.gocardless.com/mandate_pdfs}).to_return( 91 | body: { 92 | error: { 93 | type: 'invalid_state', 94 | code: 409, 95 | errors: [ 96 | { 97 | message: 'A resource has already been created with this idempotency key', 98 | reason: 'idempotent_creation_conflict', 99 | links: { 100 | conflicting_resource_id: id 101 | } 102 | } 103 | ] 104 | } 105 | }.to_json, 106 | headers: response_headers, 107 | status: 409 108 | ) 109 | end 110 | 111 | it 'raises an InvalidStateError' do 112 | expect { post_create_response }.to raise_error(GoCardlessPro::InvalidStateError) 113 | expect(post_stub).to have_been_requested 114 | end 115 | end 116 | end 117 | end 118 | -------------------------------------------------------------------------------- /spec/resources/balance_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe GoCardlessPro::Resources::Balance do 4 | let(:client) do 5 | GoCardlessPro::Client.new( 6 | access_token: 'SECRET_TOKEN' 7 | ) 8 | end 9 | 10 | let(:response_headers) { { 'Content-Type' => 'application/json' } } 11 | 12 | describe '#list' do 13 | describe 'with no filters' do 14 | subject(:get_list_response) { client.balances.list } 15 | 16 | before do 17 | stub_request(:get, %r{.*api.gocardless.com/balances}).to_return( 18 | body: { 19 | 'balances' => [{ 20 | 21 | 'amount' => 'amount-input', 22 | 'balance_type' => 'balance_type-input', 23 | 'currency' => 'currency-input', 24 | 'last_updated_at' => 'last_updated_at-input', 25 | 'links' => 'links-input' 26 | }], 27 | meta: { 28 | cursors: { 29 | before: nil, 30 | after: 'ABC123' 31 | } 32 | } 33 | }.to_json, 34 | headers: response_headers 35 | ) 36 | end 37 | 38 | it 'wraps each item in the resource class' do 39 | expect(get_list_response.records.map { |x| x.class }.uniq.first).to eq(GoCardlessPro::Resources::Balance) 40 | 41 | expect(get_list_response.records.first.amount).to eq('amount-input') 42 | 43 | expect(get_list_response.records.first.balance_type).to eq('balance_type-input') 44 | 45 | expect(get_list_response.records.first.currency).to eq('currency-input') 46 | 47 | expect(get_list_response.records.first.last_updated_at).to eq('last_updated_at-input') 48 | end 49 | 50 | it 'exposes the cursors for before and after' do 51 | expect(get_list_response.before).to eq(nil) 52 | expect(get_list_response.after).to eq('ABC123') 53 | end 54 | 55 | specify { expect(get_list_response.api_response.headers).to eql('content-type' => 'application/json') } 56 | end 57 | end 58 | 59 | describe '#all' do 60 | let!(:first_response_stub) do 61 | stub_request(:get, %r{.*api.gocardless.com/balances$}).to_return( 62 | body: { 63 | 'balances' => [{ 64 | 65 | 'amount' => 'amount-input', 66 | 'balance_type' => 'balance_type-input', 67 | 'currency' => 'currency-input', 68 | 'last_updated_at' => 'last_updated_at-input', 69 | 'links' => 'links-input' 70 | }], 71 | meta: { 72 | cursors: { after: 'AB345' }, 73 | limit: 1 74 | } 75 | }.to_json, 76 | headers: response_headers 77 | ) 78 | end 79 | 80 | let!(:second_response_stub) do 81 | stub_request(:get, %r{.*api.gocardless.com/balances\?after=AB345}).to_return( 82 | body: { 83 | 'balances' => [{ 84 | 85 | 'amount' => 'amount-input', 86 | 'balance_type' => 'balance_type-input', 87 | 'currency' => 'currency-input', 88 | 'last_updated_at' => 'last_updated_at-input', 89 | 'links' => 'links-input' 90 | }], 91 | meta: { 92 | limit: 2, 93 | cursors: {} 94 | } 95 | }.to_json, 96 | headers: response_headers 97 | ) 98 | end 99 | 100 | it 'automatically makes the extra requests' do 101 | expect(client.balances.all.to_a.length).to eq(2) 102 | expect(first_response_stub).to have_been_requested 103 | expect(second_response_stub).to have_been_requested 104 | end 105 | end 106 | end 107 | -------------------------------------------------------------------------------- /lib/gocardless_pro/resources/mandate_import.rb: -------------------------------------------------------------------------------- 1 | # 2 | # This client is automatically generated from a template and JSON schema definition. 3 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 4 | # 5 | 6 | require 'uri' 7 | 8 | module GoCardlessPro 9 | # A module containing classes for each of the resources in the GC Api 10 | module Resources 11 | # Represents an instance of a mandate_import resource returned from the API 12 | 13 | # Mandate Imports allow you to migrate existing mandates from other 14 | # providers into the 15 | # GoCardless platform. 16 | # 17 | # The process is as follows: 18 | # 19 | # 1. [Create a mandate 20 | # import](#mandate-imports-create-a-new-mandate-import) 21 | # 2. [Add entries](#mandate-import-entries-add-a-mandate-import-entry) to 22 | # the import 23 | # 3. [Submit](#mandate-imports-submit-a-mandate-import) the import 24 | # 4. Wait until a member of the GoCardless team approves the import, at 25 | # which point the mandates will be created 26 | # 5. [Link up the 27 | # mandates](#mandate-import-entries-list-all-mandate-import-entries) in your 28 | # system 29 | # 30 | # When you add entries to your mandate import, they are not turned into 31 | # actual mandates 32 | # until the mandate import is submitted by you via the API, and then 33 | # processed by a member 34 | # of the GoCardless team. When that happens, a mandate will be created for 35 | # each entry in the import. 36 | # 37 | # We will issue a `mandate_created` webhook for each entry, which will be 38 | # the same as the webhooks 39 | # triggered when [ creating a mandate ](#mandates-create-a-mandate) using 40 | # the mandates API. Once these 41 | # webhooks start arriving, any reconciliation can now be accomplished by 42 | # [checking the current status](#mandate-imports-get-a-mandate-import) of 43 | # the mandate import and 44 | # [linking up the mandates to your 45 | # system](#mandate-import-entries-list-all-mandate-import-entries). 46 | # 47 | #

Note that all Mandate Imports have an upper limit of 48 | # 30,000 entries, so we recommend you split your import into several smaller 49 | # imports if you're planning to exceed this threshold.

50 | # 51 | #

Restricted: This API is 52 | # currently only available for approved integrators - please get in touch if you would like to 54 | # use this API.

55 | class MandateImport 56 | attr_reader :created_at, :id, :scheme, :status 57 | 58 | # Initialize a mandate_import resource instance 59 | # @param object [Hash] an object returned from the API 60 | def initialize(object, response = nil) 61 | @object = object 62 | 63 | @created_at = object['created_at'] 64 | @id = object['id'] 65 | @links = object['links'] 66 | @scheme = object['scheme'] 67 | @status = object['status'] 68 | @response = response 69 | end 70 | 71 | def api_response 72 | ApiResponse.new(@response) 73 | end 74 | 75 | # Return the links that the resource has 76 | def links 77 | @mandate_import_links ||= Links.new(@links) 78 | end 79 | 80 | # Provides the mandate_import resource as a hash of all its readable attributes 81 | def to_h 82 | @object 83 | end 84 | 85 | class Links 86 | def initialize(links) 87 | @links = links || {} 88 | end 89 | 90 | def creditor 91 | @links['creditor'] 92 | end 93 | end 94 | end 95 | end 96 | end 97 | -------------------------------------------------------------------------------- /lib/gocardless_pro/services/payouts_service.rb: -------------------------------------------------------------------------------- 1 | require_relative './base_service' 2 | 3 | # encoding: utf-8 4 | # 5 | # This client is automatically generated from a template and JSON schema definition. 6 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 7 | # 8 | 9 | module GoCardlessPro 10 | module Services 11 | # Service for making requests to the Payout endpoints 12 | class PayoutsService < BaseService 13 | # Returns a [cursor-paginated](#api-usage-cursor-pagination) list of your 14 | # payouts. 15 | # Example URL: /payouts 16 | # @param options [Hash] parameters as a hash, under a params key. 17 | def list(options = {}) 18 | path = '/payouts' 19 | 20 | options[:retry_failures] = true 21 | 22 | response = make_request(:get, path, options) 23 | 24 | ListResponse.new( 25 | response: response, 26 | unenveloped_body: unenvelope_body(response.body), 27 | resource_class: Resources::Payout 28 | ) 29 | end 30 | 31 | # Get a lazily enumerated list of all the items returned. This is similar to the `list` method but will paginate for you automatically. 32 | # 33 | # @param options [Hash] parameters as a hash. If the request is a GET, these will be converted to query parameters. 34 | # Otherwise they will be the body of the request. 35 | def all(options = {}) 36 | Paginator.new( 37 | service: self, 38 | options: options 39 | ).enumerator 40 | end 41 | 42 | # Retrieves the details of a single payout. For an example of how to reconcile 43 | # the transactions in a payout, see [this 44 | # guide](#events-reconciling-payouts-with-events). 45 | # Example URL: /payouts/:identity 46 | # 47 | # @param identity # Unique identifier, beginning with "PO". 48 | # @param options [Hash] parameters as a hash, under a params key. 49 | def get(identity, options = {}) 50 | path = sub_url('/payouts/:identity', { 51 | 'identity' => identity 52 | }) 53 | 54 | options[:retry_failures] = true 55 | 56 | response = make_request(:get, path, options) 57 | 58 | return if response.body.nil? 59 | 60 | Resources::Payout.new(unenvelope_body(response.body), response) 61 | end 62 | 63 | # Updates a payout object. This accepts only the metadata parameter. 64 | # Example URL: /payouts/:identity 65 | # 66 | # @param identity # Unique identifier, beginning with "PO". 67 | # @param options [Hash] parameters as a hash, under a params key. 68 | def update(identity, options = {}) 69 | path = sub_url('/payouts/:identity', { 70 | 'identity' => identity 71 | }) 72 | 73 | params = options.delete(:params) || {} 74 | options[:params] = {} 75 | options[:params][envelope_key] = params 76 | 77 | options[:retry_failures] = true 78 | 79 | response = make_request(:put, path, options) 80 | 81 | return if response.body.nil? 82 | 83 | Resources::Payout.new(unenvelope_body(response.body), response) 84 | end 85 | 86 | private 87 | 88 | # Unenvelope the response of the body using the service's `envelope_key` 89 | # 90 | # @param body [Hash] 91 | def unenvelope_body(body) 92 | body[envelope_key] || body['data'] 93 | end 94 | 95 | # return the key which API responses will envelope data under 96 | def envelope_key 97 | 'payouts' 98 | end 99 | end 100 | end 101 | end 102 | -------------------------------------------------------------------------------- /spec/resources/negative_balance_limit_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe GoCardlessPro::Resources::NegativeBalanceLimit do 4 | let(:client) do 5 | GoCardlessPro::Client.new( 6 | access_token: 'SECRET_TOKEN' 7 | ) 8 | end 9 | 10 | let(:response_headers) { { 'Content-Type' => 'application/json' } } 11 | 12 | describe '#list' do 13 | describe 'with no filters' do 14 | subject(:get_list_response) { client.negative_balance_limits.list } 15 | 16 | before do 17 | stub_request(:get, %r{.*api.gocardless.com/negative_balance_limits}).to_return( 18 | body: { 19 | 'negative_balance_limits' => [{ 20 | 21 | 'balance_limit' => 'balance_limit-input', 22 | 'created_at' => 'created_at-input', 23 | 'currency' => 'currency-input', 24 | 'id' => 'id-input', 25 | 'links' => 'links-input' 26 | }], 27 | meta: { 28 | cursors: { 29 | before: nil, 30 | after: 'ABC123' 31 | } 32 | } 33 | }.to_json, 34 | headers: response_headers 35 | ) 36 | end 37 | 38 | it 'wraps each item in the resource class' do 39 | expect(get_list_response.records.map do |x| 40 | x.class 41 | end.uniq.first).to eq(GoCardlessPro::Resources::NegativeBalanceLimit) 42 | 43 | expect(get_list_response.records.first.balance_limit).to eq('balance_limit-input') 44 | 45 | expect(get_list_response.records.first.created_at).to eq('created_at-input') 46 | 47 | expect(get_list_response.records.first.currency).to eq('currency-input') 48 | 49 | expect(get_list_response.records.first.id).to eq('id-input') 50 | end 51 | 52 | it 'exposes the cursors for before and after' do 53 | expect(get_list_response.before).to eq(nil) 54 | expect(get_list_response.after).to eq('ABC123') 55 | end 56 | 57 | specify { expect(get_list_response.api_response.headers).to eql('content-type' => 'application/json') } 58 | end 59 | end 60 | 61 | describe '#all' do 62 | let!(:first_response_stub) do 63 | stub_request(:get, %r{.*api.gocardless.com/negative_balance_limits$}).to_return( 64 | body: { 65 | 'negative_balance_limits' => [{ 66 | 67 | 'balance_limit' => 'balance_limit-input', 68 | 'created_at' => 'created_at-input', 69 | 'currency' => 'currency-input', 70 | 'id' => 'id-input', 71 | 'links' => 'links-input' 72 | }], 73 | meta: { 74 | cursors: { after: 'AB345' }, 75 | limit: 1 76 | } 77 | }.to_json, 78 | headers: response_headers 79 | ) 80 | end 81 | 82 | let!(:second_response_stub) do 83 | stub_request(:get, %r{.*api.gocardless.com/negative_balance_limits\?after=AB345}).to_return( 84 | body: { 85 | 'negative_balance_limits' => [{ 86 | 87 | 'balance_limit' => 'balance_limit-input', 88 | 'created_at' => 'created_at-input', 89 | 'currency' => 'currency-input', 90 | 'id' => 'id-input', 91 | 'links' => 'links-input' 92 | }], 93 | meta: { 94 | limit: 2, 95 | cursors: {} 96 | } 97 | }.to_json, 98 | headers: response_headers 99 | ) 100 | end 101 | 102 | it 'automatically makes the extra requests' do 103 | expect(client.negative_balance_limits.all.to_a.length).to eq(2) 104 | expect(first_response_stub).to have_been_requested 105 | expect(second_response_stub).to have_been_requested 106 | end 107 | end 108 | end 109 | -------------------------------------------------------------------------------- /spec/resources/billing_request_with_action_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe GoCardlessPro::Resources::BillingRequestWithAction do 4 | let(:client) do 5 | GoCardlessPro::Client.new( 6 | access_token: 'SECRET_TOKEN' 7 | ) 8 | end 9 | 10 | let(:response_headers) { { 'Content-Type' => 'application/json' } } 11 | 12 | describe '#create' do 13 | subject(:post_create_response) { client.billing_request_with_actions.create_with_actions(params: new_resource) } 14 | context 'with a valid request' do 15 | let(:new_resource) do 16 | { 17 | 18 | 'bank_authorisations' => 'bank_authorisations-input', 19 | 'billing_requests' => 'billing_requests-input' 20 | } 21 | end 22 | 23 | before do 24 | stub_request(:post, %r{.*api.gocardless.com/billing_requests/create_with_actions}) 25 | .with( 26 | body: { 27 | 'billing_request_with_actions' => { 28 | 29 | 'bank_authorisations' => 'bank_authorisations-input', 30 | 'billing_requests' => 'billing_requests-input' 31 | } 32 | } 33 | ) 34 | .to_return( 35 | body: { 36 | 'billing_request_with_actions' => 37 | 38 | { 39 | 40 | 'bank_authorisations' => 'bank_authorisations-input', 41 | 'billing_requests' => 'billing_requests-input' 42 | } 43 | 44 | }.to_json, 45 | headers: response_headers 46 | ) 47 | end 48 | 49 | it 'creates and returns the resource' do 50 | expect(post_create_response).to be_a(GoCardlessPro::Resources::BillingRequestWithAction) 51 | end 52 | end 53 | 54 | context 'with a request that returns a validation error' do 55 | let(:new_resource) { {} } 56 | 57 | before do 58 | stub_request(:post, %r{.*api.gocardless.com/billing_requests/create_with_actions}).to_return( 59 | body: { 60 | error: { 61 | type: 'validation_failed', 62 | code: 422, 63 | errors: [ 64 | { message: 'test error message', field: 'test_field' } 65 | ] 66 | } 67 | }.to_json, 68 | headers: response_headers, 69 | status: 422 70 | ) 71 | end 72 | 73 | it 'throws the correct error' do 74 | expect { post_create_response }.to raise_error(GoCardlessPro::ValidationError) 75 | end 76 | end 77 | 78 | context 'with a request that returns an idempotent creation conflict error' do 79 | let(:id) { 'ID123' } 80 | 81 | let(:new_resource) do 82 | { 83 | 84 | 'bank_authorisations' => 'bank_authorisations-input', 85 | 'billing_requests' => 'billing_requests-input' 86 | } 87 | end 88 | 89 | let!(:post_stub) do 90 | stub_request(:post, %r{.*api.gocardless.com/billing_requests/create_with_actions}).to_return( 91 | body: { 92 | error: { 93 | type: 'invalid_state', 94 | code: 409, 95 | errors: [ 96 | { 97 | message: 'A resource has already been created with this idempotency key', 98 | reason: 'idempotent_creation_conflict', 99 | links: { 100 | conflicting_resource_id: id 101 | } 102 | } 103 | ] 104 | } 105 | }.to_json, 106 | headers: response_headers, 107 | status: 409 108 | ) 109 | end 110 | 111 | it 'raises an InvalidStateError' do 112 | expect { post_create_response }.to raise_error(GoCardlessPro::InvalidStateError) 113 | expect(post_stub).to have_been_requested 114 | end 115 | end 116 | end 117 | end 118 | -------------------------------------------------------------------------------- /spec/resources/bank_details_lookup_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe GoCardlessPro::Resources::BankDetailsLookup do 4 | let(:client) do 5 | GoCardlessPro::Client.new( 6 | access_token: 'SECRET_TOKEN' 7 | ) 8 | end 9 | 10 | let(:response_headers) { { 'Content-Type' => 'application/json' } } 11 | 12 | describe '#create' do 13 | subject(:post_create_response) { client.bank_details_lookups.create(params: new_resource) } 14 | context 'with a valid request' do 15 | let(:new_resource) do 16 | { 17 | 18 | 'available_debit_schemes' => 'available_debit_schemes-input', 19 | 'bank_name' => 'bank_name-input', 20 | 'bic' => 'bic-input' 21 | } 22 | end 23 | 24 | before do 25 | stub_request(:post, %r{.*api.gocardless.com/bank_details_lookups}) 26 | .with( 27 | body: { 28 | 'bank_details_lookups' => { 29 | 30 | 'available_debit_schemes' => 'available_debit_schemes-input', 31 | 'bank_name' => 'bank_name-input', 32 | 'bic' => 'bic-input' 33 | } 34 | } 35 | ) 36 | .to_return( 37 | body: { 38 | 'bank_details_lookups' => 39 | 40 | { 41 | 42 | 'available_debit_schemes' => 'available_debit_schemes-input', 43 | 'bank_name' => 'bank_name-input', 44 | 'bic' => 'bic-input' 45 | } 46 | 47 | }.to_json, 48 | headers: response_headers 49 | ) 50 | end 51 | 52 | it 'creates and returns the resource' do 53 | expect(post_create_response).to be_a(GoCardlessPro::Resources::BankDetailsLookup) 54 | end 55 | end 56 | 57 | context 'with a request that returns a validation error' do 58 | let(:new_resource) { {} } 59 | 60 | before do 61 | stub_request(:post, %r{.*api.gocardless.com/bank_details_lookups}).to_return( 62 | body: { 63 | error: { 64 | type: 'validation_failed', 65 | code: 422, 66 | errors: [ 67 | { message: 'test error message', field: 'test_field' } 68 | ] 69 | } 70 | }.to_json, 71 | headers: response_headers, 72 | status: 422 73 | ) 74 | end 75 | 76 | it 'throws the correct error' do 77 | expect { post_create_response }.to raise_error(GoCardlessPro::ValidationError) 78 | end 79 | end 80 | 81 | context 'with a request that returns an idempotent creation conflict error' do 82 | let(:id) { 'ID123' } 83 | 84 | let(:new_resource) do 85 | { 86 | 87 | 'available_debit_schemes' => 'available_debit_schemes-input', 88 | 'bank_name' => 'bank_name-input', 89 | 'bic' => 'bic-input' 90 | } 91 | end 92 | 93 | let!(:post_stub) do 94 | stub_request(:post, %r{.*api.gocardless.com/bank_details_lookups}).to_return( 95 | body: { 96 | error: { 97 | type: 'invalid_state', 98 | code: 409, 99 | errors: [ 100 | { 101 | message: 'A resource has already been created with this idempotency key', 102 | reason: 'idempotent_creation_conflict', 103 | links: { 104 | conflicting_resource_id: id 105 | } 106 | } 107 | ] 108 | } 109 | }.to_json, 110 | headers: response_headers, 111 | status: 409 112 | ) 113 | end 114 | 115 | it 'raises an InvalidStateError' do 116 | expect { post_create_response }.to raise_error(GoCardlessPro::InvalidStateError) 117 | expect(post_stub).to have_been_requested 118 | end 119 | end 120 | end 121 | end 122 | -------------------------------------------------------------------------------- /lib/gocardless_pro/services/webhooks_service.rb: -------------------------------------------------------------------------------- 1 | require_relative './base_service' 2 | 3 | # encoding: utf-8 4 | # 5 | # This client is automatically generated from a template and JSON schema definition. 6 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 7 | # 8 | 9 | module GoCardlessPro 10 | module Services 11 | # Service for making requests to the Webhook endpoints 12 | class WebhooksService < BaseService 13 | # Returns a [cursor-paginated](#api-usage-cursor-pagination) list of your 14 | # webhooks. 15 | # Example URL: /webhooks 16 | # @param options [Hash] parameters as a hash, under a params key. 17 | def list(options = {}) 18 | path = '/webhooks' 19 | 20 | options[:retry_failures] = true 21 | 22 | response = make_request(:get, path, options) 23 | 24 | ListResponse.new( 25 | response: response, 26 | unenveloped_body: unenvelope_body(response.body), 27 | resource_class: Resources::Webhook 28 | ) 29 | end 30 | 31 | # Get a lazily enumerated list of all the items returned. This is similar to the `list` method but will paginate for you automatically. 32 | # 33 | # @param options [Hash] parameters as a hash. If the request is a GET, these will be converted to query parameters. 34 | # Otherwise they will be the body of the request. 35 | def all(options = {}) 36 | Paginator.new( 37 | service: self, 38 | options: options 39 | ).enumerator 40 | end 41 | 42 | # Retrieves the details of an existing webhook. 43 | # Example URL: /webhooks/:identity 44 | # 45 | # @param identity # Unique identifier, beginning with "WB". 46 | # @param options [Hash] parameters as a hash, under a params key. 47 | def get(identity, options = {}) 48 | path = sub_url('/webhooks/:identity', { 49 | 'identity' => identity 50 | }) 51 | 52 | options[:retry_failures] = true 53 | 54 | response = make_request(:get, path, options) 55 | 56 | return if response.body.nil? 57 | 58 | Resources::Webhook.new(unenvelope_body(response.body), response) 59 | end 60 | 61 | # Requests for a previous webhook to be sent again 62 | # Example URL: /webhooks/:identity/actions/retry 63 | # 64 | # @param identity # Unique identifier, beginning with "WB". 65 | # @param options [Hash] parameters as a hash, under a params key. 66 | def retry(identity, options = {}) 67 | path = sub_url('/webhooks/:identity/actions/retry', { 68 | 'identity' => identity 69 | }) 70 | 71 | params = options.delete(:params) || {} 72 | options[:params] = {} 73 | options[:params]['data'] = params 74 | 75 | options[:retry_failures] = false 76 | 77 | begin 78 | response = make_request(:post, path, options) 79 | 80 | # Response doesn't raise any errors until #body is called 81 | response.tap(&:body) 82 | rescue InvalidStateError => e 83 | if e.idempotent_creation_conflict? 84 | case @api_service.on_idempotency_conflict 85 | when :raise 86 | raise IdempotencyConflict, e.error 87 | when :fetch 88 | return get(e.conflicting_resource_id) 89 | end 90 | end 91 | 92 | raise e 93 | end 94 | 95 | return if response.body.nil? 96 | 97 | Resources::Webhook.new(unenvelope_body(response.body), response) 98 | end 99 | 100 | private 101 | 102 | # Unenvelope the response of the body using the service's `envelope_key` 103 | # 104 | # @param body [Hash] 105 | def unenvelope_body(body) 106 | body[envelope_key] || body['data'] 107 | end 108 | 109 | # return the key which API responses will envelope data under 110 | def envelope_key 111 | 'webhooks' 112 | end 113 | end 114 | end 115 | end 116 | -------------------------------------------------------------------------------- /lib/gocardless_pro/resources/creditor.rb: -------------------------------------------------------------------------------- 1 | # 2 | # This client is automatically generated from a template and JSON schema definition. 3 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 4 | # 5 | 6 | require 'uri' 7 | 8 | module GoCardlessPro 9 | # A module containing classes for each of the resources in the GC Api 10 | module Resources 11 | # Represents an instance of a creditor resource returned from the API 12 | 13 | # Each [payment](#core-endpoints-payments) taken through the API is linked 14 | # to a "creditor", to whom the payment is then paid out. In most cases your 15 | # organisation will have a single "creditor", but the API also supports 16 | # collecting payments on behalf of others. 17 | # 18 | # Currently, for Anti Money Laundering reasons, any creditors you add must 19 | # be directly related to your organisation. 20 | class Creditor 21 | attr_reader :address_line1, :address_line2, :address_line3, :bank_reference_prefix, :can_create_refunds, :city, 22 | :country_code, :created_at, :creditor_type, :custom_payment_pages_enabled, :fx_payout_currency, :id, :logo_url, :mandate_imports_enabled, :merchant_responsible_for_notifications, :name, :postal_code, :region, :scheme_identifiers, :verification_status 23 | 24 | # Initialize a creditor resource instance 25 | # @param object [Hash] an object returned from the API 26 | def initialize(object, response = nil) 27 | @object = object 28 | 29 | @address_line1 = object['address_line1'] 30 | @address_line2 = object['address_line2'] 31 | @address_line3 = object['address_line3'] 32 | @bank_reference_prefix = object['bank_reference_prefix'] 33 | @can_create_refunds = object['can_create_refunds'] 34 | @city = object['city'] 35 | @country_code = object['country_code'] 36 | @created_at = object['created_at'] 37 | @creditor_type = object['creditor_type'] 38 | @custom_payment_pages_enabled = object['custom_payment_pages_enabled'] 39 | @fx_payout_currency = object['fx_payout_currency'] 40 | @id = object['id'] 41 | @links = object['links'] 42 | @logo_url = object['logo_url'] 43 | @mandate_imports_enabled = object['mandate_imports_enabled'] 44 | @merchant_responsible_for_notifications = object['merchant_responsible_for_notifications'] 45 | @name = object['name'] 46 | @postal_code = object['postal_code'] 47 | @region = object['region'] 48 | @scheme_identifiers = object['scheme_identifiers'] 49 | @verification_status = object['verification_status'] 50 | @response = response 51 | end 52 | 53 | def api_response 54 | ApiResponse.new(@response) 55 | end 56 | 57 | # Return the links that the resource has 58 | def links 59 | @creditor_links ||= Links.new(@links) 60 | end 61 | 62 | # Provides the creditor resource as a hash of all its readable attributes 63 | def to_h 64 | @object 65 | end 66 | 67 | class Links 68 | def initialize(links) 69 | @links = links || {} 70 | end 71 | 72 | def default_aud_payout_account 73 | @links['default_aud_payout_account'] 74 | end 75 | 76 | def default_cad_payout_account 77 | @links['default_cad_payout_account'] 78 | end 79 | 80 | def default_dkk_payout_account 81 | @links['default_dkk_payout_account'] 82 | end 83 | 84 | def default_eur_payout_account 85 | @links['default_eur_payout_account'] 86 | end 87 | 88 | def default_gbp_payout_account 89 | @links['default_gbp_payout_account'] 90 | end 91 | 92 | def default_nzd_payout_account 93 | @links['default_nzd_payout_account'] 94 | end 95 | 96 | def default_sek_payout_account 97 | @links['default_sek_payout_account'] 98 | end 99 | 100 | def default_usd_payout_account 101 | @links['default_usd_payout_account'] 102 | end 103 | end 104 | end 105 | end 106 | end 107 | -------------------------------------------------------------------------------- /lib/gocardless_pro/resources/event.rb: -------------------------------------------------------------------------------- 1 | # 2 | # This client is automatically generated from a template and JSON schema definition. 3 | # See https://github.com/gocardless/gocardless-pro-ruby#contributing before editing. 4 | # 5 | 6 | require 'uri' 7 | 8 | module GoCardlessPro 9 | # A module containing classes for each of the resources in the GC Api 10 | module Resources 11 | # Represents an instance of a event resource returned from the API 12 | 13 | # Events are stored for all webhooks. An event refers to a resource which 14 | # has been updated, for example a payment which has been collected, or a 15 | # mandate which has been transferred. Event creation is an asynchronous 16 | # process, so it can take some time between an action occurring and its 17 | # corresponding event getting included in API responses. See 18 | # [here](#event-actions) for a complete list of event types. 19 | class Event 20 | attr_reader :action, :created_at, :customer_notifications, :details, :id, :metadata, :resource_metadata, 21 | :resource_type 22 | 23 | # Initialize a event resource instance 24 | # @param object [Hash] an object returned from the API 25 | def initialize(object, response = nil) 26 | @object = object 27 | 28 | @action = object['action'] 29 | @created_at = object['created_at'] 30 | @customer_notifications = object['customer_notifications'] 31 | @details = object['details'] 32 | @id = object['id'] 33 | @links = object['links'] 34 | @metadata = object['metadata'] 35 | @resource_metadata = object['resource_metadata'] 36 | @resource_type = object['resource_type'] 37 | @response = response 38 | end 39 | 40 | def api_response 41 | ApiResponse.new(@response) 42 | end 43 | 44 | # Return the links that the resource has 45 | def links 46 | @event_links ||= Links.new(@links) 47 | end 48 | 49 | # Provides the event resource as a hash of all its readable attributes 50 | def to_h 51 | @object 52 | end 53 | 54 | class Links 55 | def initialize(links) 56 | @links = links || {} 57 | end 58 | 59 | def bank_authorisation 60 | @links['bank_authorisation'] 61 | end 62 | 63 | def billing_request 64 | @links['billing_request'] 65 | end 66 | 67 | def billing_request_flow 68 | @links['billing_request_flow'] 69 | end 70 | 71 | def creditor 72 | @links['creditor'] 73 | end 74 | 75 | def customer 76 | @links['customer'] 77 | end 78 | 79 | def customer_bank_account 80 | @links['customer_bank_account'] 81 | end 82 | 83 | def instalment_schedule 84 | @links['instalment_schedule'] 85 | end 86 | 87 | def mandate 88 | @links['mandate'] 89 | end 90 | 91 | def mandate_request_mandate 92 | @links['mandate_request_mandate'] 93 | end 94 | 95 | def new_customer_bank_account 96 | @links['new_customer_bank_account'] 97 | end 98 | 99 | def new_mandate 100 | @links['new_mandate'] 101 | end 102 | 103 | def organisation 104 | @links['organisation'] 105 | end 106 | 107 | def parent_event 108 | @links['parent_event'] 109 | end 110 | 111 | def payer_authorisation 112 | @links['payer_authorisation'] 113 | end 114 | 115 | def payment 116 | @links['payment'] 117 | end 118 | 119 | def payment_request_payment 120 | @links['payment_request_payment'] 121 | end 122 | 123 | def payout 124 | @links['payout'] 125 | end 126 | 127 | def previous_customer_bank_account 128 | @links['previous_customer_bank_account'] 129 | end 130 | 131 | def refund 132 | @links['refund'] 133 | end 134 | 135 | def scheme_identifier 136 | @links['scheme_identifier'] 137 | end 138 | 139 | def subscription 140 | @links['subscription'] 141 | end 142 | end 143 | end 144 | end 145 | end 146 | --------------------------------------------------------------------------------