besepa 0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +46 -0
- data/LICENSE.txt +22 -0
- data/README.md +132 -0
- data/Rakefile +1 -0
- data/besepa-ruby.gemspec +31 -0
- data/lib/besepa.rb +14 -0
- data/lib/besepa/activity.rb +11 -0
- data/lib/besepa/api_calls/create.rb +26 -0
- data/lib/besepa/api_calls/destroy.rb +15 -0
- data/lib/besepa/api_calls/list.rb +36 -0
- data/lib/besepa/api_calls/update.rb +23 -0
- data/lib/besepa/bank_account.rb +63 -0
- data/lib/besepa/business_account.rb +37 -0
- data/lib/besepa/customer.rb +134 -0
- data/lib/besepa/debit.rb +64 -0
- data/lib/besepa/errors/besepa_error.rb +28 -0
- data/lib/besepa/errors/invalid_resource_error.rb +11 -0
- data/lib/besepa/errors/resource_not_found_error.rb +11 -0
- data/lib/besepa/group.rb +27 -0
- data/lib/besepa/mandate.rb +18 -0
- data/lib/besepa/product.rb +19 -0
- data/lib/besepa/remittance.rb +32 -0
- data/lib/besepa/resource.rb +96 -0
- data/lib/besepa/subscription.rb +50 -0
- data/lib/besepa/utils/config.rb +51 -0
- data/lib/besepa/utils/connection.rb +27 -0
- data/lib/besepa/utils/request.rb +60 -0
- data/lib/besepa/utils/version.rb +6 -0
- data/lib/besepa/webhook.rb +16 -0
- data/spec/besepa/customer_spec.rb +119 -0
- data/spec/fixtures/customer.json +17 -0
- data/spec/fixtures/customer_add_debit.json +54 -0
- data/spec/fixtures/customer_bank_accounts.json +22 -0
- data/spec/fixtures/customer_debits.json +71 -0
- data/spec/fixtures/customer_removed.json +17 -0
- data/spec/fixtures/customers.json +20 -0
- data/spec/helper.rb +46 -0
- metadata +174 -0
@@ -0,0 +1,50 @@
|
|
1
|
+
module Besepa
|
2
|
+
|
3
|
+
class Subscription < Besepa::Resource
|
4
|
+
|
5
|
+
include Besepa::ApiCalls::List
|
6
|
+
include Besepa::ApiCalls::Create
|
7
|
+
include Besepa::ApiCalls::Destroy
|
8
|
+
|
9
|
+
FIELDS = [:id, :last_debit, :next_debit, :status, :metadata, :starts_at, :renew_at]
|
10
|
+
|
11
|
+
|
12
|
+
FIELDS.each do |f|
|
13
|
+
attr_accessor f
|
14
|
+
end
|
15
|
+
|
16
|
+
attr_accessor :debtor_bank_account, :product, :customer
|
17
|
+
|
18
|
+
def to_hash
|
19
|
+
values = {}
|
20
|
+
self.class::FIELDS.each do |key|
|
21
|
+
values[key] = self.send("#{key.to_s}")
|
22
|
+
end
|
23
|
+
values[:debtor_bank_account] = debtor_bank_account.to_hash if debtor_bank_account
|
24
|
+
values[:product] = product.to_hash if product
|
25
|
+
values[:customer] = customer.to_hash if customer
|
26
|
+
values
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.api_path(filters={})
|
30
|
+
"#{Customer.api_path}/#{CGI.escape(filters[:customer_id])}/subscriptions"
|
31
|
+
end
|
32
|
+
|
33
|
+
def api_path(filters={})
|
34
|
+
"#{Customer.api_path}/#{CGI.escape(filters[:customer_id])}/subscriptions/#{CGI.escape(id)}"
|
35
|
+
end
|
36
|
+
|
37
|
+
def process_attributes(attrs)
|
38
|
+
self.class::FIELDS.each do |key|
|
39
|
+
self.send("#{key.to_s}=", attrs[key.to_s] || attrs[key.to_sym])
|
40
|
+
end
|
41
|
+
self.debtor_bank_account = Besepa::BankAccount.new(attrs['debtor_bank_account']) if attrs['debtor_bank_account']
|
42
|
+
self.product = Besepa::Product.new(attrs['product']) if attrs['product']
|
43
|
+
self.customer = Besepa::Customer.new(attrs['customer']) if attrs['customer']
|
44
|
+
process_activities(attrs)
|
45
|
+
self
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Besepa
|
2
|
+
|
3
|
+
module Utils
|
4
|
+
|
5
|
+
# Defines constants and methods related to configuration
|
6
|
+
module ApiConfig
|
7
|
+
|
8
|
+
# The consumer key if none is set
|
9
|
+
DEFAULT_API_KEY = nil
|
10
|
+
|
11
|
+
# The endpoint that will be used to connect if none is set
|
12
|
+
DEFAULT_ENDPOINT = 'https://sandbox.besepa.com'
|
13
|
+
|
14
|
+
# An array of valid keys in the options hash when configuring api objects
|
15
|
+
VALID_OPTIONS_KEYS = [
|
16
|
+
:api_key,
|
17
|
+
:endpoint,
|
18
|
+
:ssl
|
19
|
+
]
|
20
|
+
|
21
|
+
attr_accessor *VALID_OPTIONS_KEYS
|
22
|
+
|
23
|
+
# When this module is extended, set all configuration options to their default values
|
24
|
+
def self.extended(base)
|
25
|
+
base.reset
|
26
|
+
end
|
27
|
+
|
28
|
+
# Convenience method to allow configuration options to be set in a block
|
29
|
+
def configure
|
30
|
+
yield self
|
31
|
+
self
|
32
|
+
end
|
33
|
+
|
34
|
+
# Create a hash of options and their values
|
35
|
+
def options
|
36
|
+
options = {}
|
37
|
+
VALID_OPTIONS_KEYS.each{|k| options[k] = send(k)}
|
38
|
+
options
|
39
|
+
end
|
40
|
+
|
41
|
+
# Reset all configuration options to defaults
|
42
|
+
def reset
|
43
|
+
self.api_key = DEFAULT_API_KEY
|
44
|
+
self.endpoint = DEFAULT_ENDPOINT
|
45
|
+
self
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'faraday_middleware'
|
3
|
+
|
4
|
+
module Besepa
|
5
|
+
|
6
|
+
module Utils
|
7
|
+
|
8
|
+
module Connection
|
9
|
+
|
10
|
+
# Returns a Faraday::Connection object
|
11
|
+
#
|
12
|
+
# @param options [Hash] A hash of options
|
13
|
+
# @return [Faraday::Connection]
|
14
|
+
def connection(options={})
|
15
|
+
options = options.merge(Besepa.options)
|
16
|
+
@connection ||= Faraday.new ( options[:endpoint] ) do |conn|
|
17
|
+
conn.request :json
|
18
|
+
conn.response :json, :content_type => /\bjson$/
|
19
|
+
conn.authorization( 'Bearer', options[:api_key])
|
20
|
+
conn.adapter :net_http
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Besepa
|
2
|
+
|
3
|
+
module Utils
|
4
|
+
|
5
|
+
# Defines HTTP request methods
|
6
|
+
module Request
|
7
|
+
|
8
|
+
END_POINT_URL_PREFIX = "/api/1"
|
9
|
+
|
10
|
+
# Perform an HTTP DELETE request
|
11
|
+
def delete(path, params={}, options={})
|
12
|
+
request(:delete, path, params, options)
|
13
|
+
end
|
14
|
+
|
15
|
+
# Perform an HTTP GET request
|
16
|
+
def get(path, params={}, options={})
|
17
|
+
request(:get, path, params, options)
|
18
|
+
end
|
19
|
+
|
20
|
+
# Perform an HTTP POST request
|
21
|
+
def post(path, params={}, options={})
|
22
|
+
request(:post, path, params, options)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Perform an HTTP PUT request
|
26
|
+
def put(path, params={}, options={})
|
27
|
+
request(:put, path, params, options)
|
28
|
+
end
|
29
|
+
|
30
|
+
protected
|
31
|
+
|
32
|
+
# Perform an HTTP request
|
33
|
+
def request(method, path, params, options)
|
34
|
+
response = connection(options).run_request(method, nil, nil, nil) do |request|
|
35
|
+
request.options[:raw] = true if options[:raw]
|
36
|
+
case method.to_sym
|
37
|
+
when :delete, :get
|
38
|
+
request.url(END_POINT_URL_PREFIX + path, params)
|
39
|
+
when :post, :put
|
40
|
+
request.path = END_POINT_URL_PREFIX + path
|
41
|
+
request.body = params unless params.empty?
|
42
|
+
end
|
43
|
+
end
|
44
|
+
options[:raw] ? response : handle_response(response)
|
45
|
+
end
|
46
|
+
|
47
|
+
def handle_response(response)
|
48
|
+
body = response.body
|
49
|
+
if response.status >= 400 || body['error']
|
50
|
+
handle_errors(response.status, body)
|
51
|
+
else
|
52
|
+
body
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Besepa
|
2
|
+
|
3
|
+
class Webhook < Besepa::Resource
|
4
|
+
|
5
|
+
include Besepa::ApiCalls::List
|
6
|
+
include Besepa::ApiCalls::Create
|
7
|
+
include Besepa::ApiCalls::Destroy
|
8
|
+
|
9
|
+
FIELDS = [:id, :url, :status, :push_count, :ok_count, :success_rate]
|
10
|
+
|
11
|
+
FIELDS.each do |f|
|
12
|
+
attr_accessor f
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
|
2
|
+
require 'helper'
|
3
|
+
|
4
|
+
describe Besepa::Customer do
|
5
|
+
|
6
|
+
describe '#all' do
|
7
|
+
|
8
|
+
before do
|
9
|
+
stub_get('/customers').to_return(body: fixture('customers.json'), headers: {content_type: 'application/json; charset=utf-8'})
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'returns a list of customers' do
|
13
|
+
customers = Besepa::Customer.all
|
14
|
+
expect(customers).to be_an Array
|
15
|
+
expect(customers.first).to be_an Besepa::Customer
|
16
|
+
expect(customers.size).to eq(1)
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '#find' do
|
22
|
+
|
23
|
+
before do
|
24
|
+
stub_get('/customers/cus12345').to_return(body: fixture('customer.json'), headers: {content_type: 'application/json; charset=utf-8'})
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'returns a a customer' do
|
28
|
+
customer = Besepa::Customer.find('cus12345')
|
29
|
+
expect(customer).to be_an Besepa::Customer
|
30
|
+
expect(customer.name).to eq("Pancho Villa SLU")
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '.save' do
|
36
|
+
|
37
|
+
before do
|
38
|
+
stub_get('/customers/cus12345').to_return(body: fixture('customer.json'), headers: {content_type: 'application/json; charset=utf-8'})
|
39
|
+
stub_put('/customers/cus12345').to_return(body: fixture('customer.json'), headers: {content_type: 'application/json; charset=utf-8'})
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'returns a a customer' do
|
43
|
+
customer = Besepa::Customer.find('cus12345')
|
44
|
+
customer.name = customer.name.reverse
|
45
|
+
customer = customer.save
|
46
|
+
expect(customer).to be_an Besepa::Customer
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
describe '.destroy' do
|
52
|
+
|
53
|
+
before do
|
54
|
+
stub_get('/customers/cus12345').to_return(body: fixture('customer.json'), headers: {content_type: 'application/json; charset=utf-8'})
|
55
|
+
stub_delete('/customers/cus12345').to_return(body: fixture('customer_removed.json'), headers: {content_type: 'application/json; charset=utf-8'})
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'returns a a customer' do
|
59
|
+
customer = Besepa::Customer.find('cus12345')
|
60
|
+
customer.name = customer.name.reverse
|
61
|
+
customer = customer.destroy
|
62
|
+
expect(customer).to be_an Besepa::Customer
|
63
|
+
expect(customer.status).to eq('REMOVED')
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
describe "getting customer debits" do
|
70
|
+
|
71
|
+
before do
|
72
|
+
stub_get('/customers/cus12345/debits').to_return(body: fixture('customer_debits.json'), headers: {content_type: 'application/json; charset=utf-8'})
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'returns a list of debits' do
|
76
|
+
debits = Besepa::Customer.new(id: 'cus12345').debits
|
77
|
+
expect(debits).to be_an Array
|
78
|
+
expect(debits.first).to be_an Besepa::Debit
|
79
|
+
expect(debits.size).to eq(1)
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
describe "creating a debit for a customer" do
|
85
|
+
|
86
|
+
describe "with valid data" do
|
87
|
+
|
88
|
+
before do
|
89
|
+
stub_post('/customers/cus12345/debits').to_return(body: fixture('customer_add_debit.json'), headers: {content_type: 'application/json; charset=utf-8'})
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'returns the new created debit' do
|
93
|
+
debit = Besepa::Customer.new(id: 'cus12345').add_debit("man123", "ref123", "desc123", 1000, '2015-11-23')
|
94
|
+
|
95
|
+
expect(debit).to be_an Besepa::Debit
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
|
103
|
+
describe "getting customer bank_accounts" do
|
104
|
+
|
105
|
+
before do
|
106
|
+
stub_get('/customers/cus12345/bank_accounts').to_return(body: fixture('customer_bank_accounts.json'), headers: {content_type: 'application/json; charset=utf-8'})
|
107
|
+
end
|
108
|
+
|
109
|
+
|
110
|
+
it 'returns a list of bank accounts' do
|
111
|
+
bank_accounts = Besepa::Customer.new(id: 'cus12345').bank_accounts
|
112
|
+
expect(bank_accounts).to be_an Array
|
113
|
+
expect(bank_accounts.first).to be_an Besepa::BankAccount
|
114
|
+
expect(bank_accounts.size).to eq(1)
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
{
|
2
|
+
"response": {
|
3
|
+
"name": "Pancho Villa SLU",
|
4
|
+
"taxid": "B98123232",
|
5
|
+
"reference": "11234",
|
6
|
+
"contact_name": null,
|
7
|
+
"contact_email": null,
|
8
|
+
"contact_phone": null,
|
9
|
+
"address_street": null,
|
10
|
+
"address_city": null,
|
11
|
+
"address_postalcode": null,
|
12
|
+
"address_state": null,
|
13
|
+
"address_country": null,
|
14
|
+
"status": "ACTIVE",
|
15
|
+
"id": "cus12345"
|
16
|
+
}
|
17
|
+
}
|
@@ -0,0 +1,54 @@
|
|
1
|
+
{
|
2
|
+
"response": {
|
3
|
+
"amount": 1000,
|
4
|
+
"currency": "EUR",
|
5
|
+
"collect_at": "2014-11-15",
|
6
|
+
"sent_at": null,
|
7
|
+
"status": "READY",
|
8
|
+
"description": "desc",
|
9
|
+
"id": "deb3482f4dc98245ec092581e4f507a",
|
10
|
+
"reference": "REF123",
|
11
|
+
"metadata": {
|
12
|
+
"shipping": "UPS"
|
13
|
+
},
|
14
|
+
"customer": {
|
15
|
+
"name": "Pancho Villa SLU",
|
16
|
+
"taxid": "B98123232",
|
17
|
+
"reference": "11232",
|
18
|
+
"contact_name": "Pancho Villa",
|
19
|
+
"contact_email": "pvilla@panchovilla.com",
|
20
|
+
"contact_phone": "123456789",
|
21
|
+
"address_street": "Avda. de la Revolución 12",
|
22
|
+
"address_city": "Madrid",
|
23
|
+
"address_postalcode": "28001",
|
24
|
+
"address_state": "Madrid",
|
25
|
+
"address_country": "ES",
|
26
|
+
"status": "ACTIVE",
|
27
|
+
"id": "cusa1654ec35f3745481bb0a984d8f8"
|
28
|
+
},
|
29
|
+
"mandate": {
|
30
|
+
"description": "mandate",
|
31
|
+
"status": "SIGNED",
|
32
|
+
"signed_at": "2014-11-10T15:59:45.313Z",
|
33
|
+
"mandate_type": "RECURRENT",
|
34
|
+
"reference": "1415635184",
|
35
|
+
"scheme": "CORE",
|
36
|
+
"id": "manff3c2d4ea5ca29085c5c871ef2d2",
|
37
|
+
"url": "https://test.besepa.com/m/manff3c2d4ea5ca29085c5c871ef2d2"
|
38
|
+
},
|
39
|
+
"debtor_bank_account": {
|
40
|
+
"bank_name": "Banco Santander",
|
41
|
+
"bic": "BSCHESMM",
|
42
|
+
"iban": "ES7620770024003102575766",
|
43
|
+
"status": "ACTIVE",
|
44
|
+
"id": "ban9601a13105a897750917b223418c"
|
45
|
+
},
|
46
|
+
"creditor_bank_account": {
|
47
|
+
"bank_name": "Banco Santander",
|
48
|
+
"bic": "BSCHESMM",
|
49
|
+
"iban": "ES7620770024003102575766",
|
50
|
+
"status": "ACTIVE",
|
51
|
+
"id": "ban60e4704d70add1851b676aa69fbc"
|
52
|
+
}
|
53
|
+
}
|
54
|
+
}
|
@@ -0,0 +1,22 @@
|
|
1
|
+
{
|
2
|
+
"response": [
|
3
|
+
{
|
4
|
+
"id": "banbd5ae7eacf231888edd470ed55144f40",
|
5
|
+
"bank_name": "Banco Santander",
|
6
|
+
"bic": "BSCHESMM",
|
7
|
+
"iban": "ES7620770024003102575766",
|
8
|
+
"status": "PENDING_MANDATE",
|
9
|
+
"customer_id": "cusf11b647d2cc16e503fe8ba36f88c",
|
10
|
+
"mandate": {
|
11
|
+
"status": "PENDING_SIGNATURE",
|
12
|
+
"signed_at": null,
|
13
|
+
"mandate_type": "RECURRENT",
|
14
|
+
"reference": "manf08e870d427040854beca9ad6117",
|
15
|
+
"scheme": "B2B",
|
16
|
+
"id": "manf08d870d327041854beca9ad6117",
|
17
|
+
"url": "http://test.besepa.com/m/manf08e870d427040854beca9ad6117"
|
18
|
+
}
|
19
|
+
}
|
20
|
+
],
|
21
|
+
"count": 1
|
22
|
+
}
|
@@ -0,0 +1,71 @@
|
|
1
|
+
{
|
2
|
+
"response": [
|
3
|
+
{
|
4
|
+
"reference": "1421756142",
|
5
|
+
"amount": 1000,
|
6
|
+
"currency": "EUR",
|
7
|
+
"collect_at": "2015-01-30",
|
8
|
+
"sent_at": null,
|
9
|
+
"status": "READY",
|
10
|
+
"description": "Cargo de 1421756142",
|
11
|
+
"error_code": null,
|
12
|
+
"platform_error_code": null,
|
13
|
+
"metadata": null,
|
14
|
+
"id": "deb4df034666ef17a312b8bbef0bb5d",
|
15
|
+
"customer": {
|
16
|
+
"name": "PATODONALD",
|
17
|
+
"taxid": "PATODONALD",
|
18
|
+
"reference": "PATODONALD",
|
19
|
+
"contact_name": null,
|
20
|
+
"contact_email": null,
|
21
|
+
"contact_phone": null,
|
22
|
+
"address_street": "fsfdsfds",
|
23
|
+
"address_city": "sfsfss",
|
24
|
+
"address_postalcode": "fsf",
|
25
|
+
"address_state": "fsf",
|
26
|
+
"address_country": "ES",
|
27
|
+
"status": "PENDING_MANDATE",
|
28
|
+
"id": "cusf0119f36a683c89e0b041462e23b"
|
29
|
+
},
|
30
|
+
"mandate": {
|
31
|
+
"description": "Firmado fuera de BeSEPA.",
|
32
|
+
"status": "SIGNED",
|
33
|
+
"signed_at": "2015-01-20T12:09:01.000Z",
|
34
|
+
"mandate_type": "RECURRENT",
|
35
|
+
"reference": "man7ca33df2252a2d640175f40f4312",
|
36
|
+
"scheme": "CORE",
|
37
|
+
"signature_type": "checkbox",
|
38
|
+
"id": "man7ca33df225aa2d640175f40f4312",
|
39
|
+
"url": "http://test.besepa.com/m/man7ca33df225aa2d640135f40f4312"
|
40
|
+
},
|
41
|
+
"debtor_bank_account": {
|
42
|
+
"bank_name": "INGDESMMXXX",
|
43
|
+
"bic": "INGDESMMXXX",
|
44
|
+
"iban": "ES7114452100966029467461",
|
45
|
+
"status": "ACTIVE",
|
46
|
+
"id": "ban00fb39d4ab493f34aba3077a3c2e",
|
47
|
+
"customer_id": "cusf0119fe6a683c89e0b041462e23b",
|
48
|
+
"mandate": {
|
49
|
+
"description": "Firmado fuera de BeSEPA.",
|
50
|
+
"status": "SIGNED",
|
51
|
+
"signed_at": "2015-01-20T12:09:01.000Z",
|
52
|
+
"mandate_type": "RECURRENT",
|
53
|
+
"reference": "man7ca33df225aa2d640175f40f4312",
|
54
|
+
"scheme": "CORE",
|
55
|
+
"signature_type": "checkbox",
|
56
|
+
"id": "man7ca3333df5aard640h75f40f4312",
|
57
|
+
"url": "http://test.besepa.com/m/man7ca33df225aa2d640135f40f4312"
|
58
|
+
}
|
59
|
+
},
|
60
|
+
"creditor_bank_account": {
|
61
|
+
"bank_name": "Bankinter",
|
62
|
+
"bic": "BBVAESMMXXX",
|
63
|
+
"iban": "es0820383852396000858559",
|
64
|
+
"status": "PENDING_ACTIVATION",
|
65
|
+
"id": "ban4d38bb61085e2d1e53bff7c1779a",
|
66
|
+
"mandate": null
|
67
|
+
}
|
68
|
+
}
|
69
|
+
],
|
70
|
+
"count": 1
|
71
|
+
}
|