besepa 0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
}
|