ruby-eupago 0.1.0 → 0.2.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 43a13811487c270301ef4dc2e07cdd5036c11de8981e821ba119017c14ce6a23
4
- data.tar.gz: 72307c343896aa908f4d25757a5764d5aaee1bc08d43c480b8b4a628e0e871fd
3
+ metadata.gz: 8dc8afa36b112dced935208f0172bc416c2f028266463770498c97aa2cf82458
4
+ data.tar.gz: 3bf972bdc874d59c93d732b172509bc477f33fa64139c3385bb2a64a284d0c12
5
5
  SHA512:
6
- metadata.gz: 1393f9d679601c196e3b104fcaf17f27f4830a6b71d849e5a8279561af9d4d5879c7d34c2b3ea3c2142be9b674548b10c294591491e978edbc5cf3d0025568fe
7
- data.tar.gz: 558528c12d48b575a6447c4835f1dccdf6f0f680574b0675bf85e52afb6f5527bb895043c18485855a808a816b79c2a669ce4cfc0834ddac8e1de3d4d688baf9
6
+ metadata.gz: a77c60d2b49067ce1aa5cf1b56f26c9b260a12188e380d5b592796d8fb0263054707d6e4a0185348e8ecab12187739e25657cc2a2de7c245e0fb154137456679
7
+ data.tar.gz: 431dcaee318d4b3d618c72cce44c2409e277d21712f701004fb25d22d034e82b8f9f048612131251e8e3918ddf62f355fbe3ee77eec90c2c202233ecdb764552
data/CHANGELOG.md CHANGED
@@ -0,0 +1,8 @@
1
+ # Changelog
2
+
3
+ ## [v0.1.0] - 2025-09-15
4
+
5
+ ### Added
6
+ - MBWay payment support
7
+ - Credit card recurrent payments
8
+ - Direct debit payments
data/README.md CHANGED
@@ -4,7 +4,53 @@ This is a not official Ruby SDK for the EuPago payment gateway.
4
4
 
5
5
  ## Installation
6
6
 
7
- WIP
7
+ ```ruby
8
+ gem 'ruby-eupago', '~> 0.2.0'
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ First, set your credentials as environment variables:
14
+
15
+ ```bash
16
+ export EUPAGO_CLIENT_ID=your_client_id
17
+ export EUPAGO_CLIENT_SECRET=your_client_secret
18
+ export EUPAGO_API_KEY=your_api_key
19
+ ```
20
+
21
+ Then, in your Ruby code:
22
+
23
+ ```ruby
24
+ require 'ruby-eupago'
25
+
26
+ # Example: Create a direct debit authorization
27
+ response = EuPago::Api::V1::DirectDebit.authorization({
28
+ "debtor" => {
29
+ "name" => "John Doe",
30
+ "iban" => "PT50123443211234567890172",
31
+ "email" => "john@example.com",
32
+ "address" => {
33
+ "zipCode" => "1234-5678",
34
+ "country" => "PT",
35
+ "street" => "Rua das coisas",
36
+ "locality" => "Lisboa"
37
+ },
38
+ "bic" => "CGDIPTPL"
39
+ },
40
+ "payment" => {
41
+ "autoProcess" => "0",
42
+ "type" => EuPago::Constants::PAYMENT_TYPES[:recurring],
43
+ "date" => "2025-09-15",
44
+ "amount" => 20,
45
+ "periodicity" => EuPago::Constants::RECURRENT_PAYMENT_INTERVALS[:monthly]
46
+ },
47
+ "identifier" => "Test Direct Debit Subscription"
48
+ })
49
+
50
+ puts response
51
+ ```
52
+
53
+ For more advanced usage, see the `spec/` directory for real-world examples.
8
54
 
9
55
  ## Testing
10
56
 
@@ -3,12 +3,26 @@ module EuPago
3
3
  module Auth
4
4
  # https://eupago.readme.io/reference/generate-bearer-token
5
5
  def self.token(body)
6
- result = EuPago::Client.new.post("/auth/token", body: body, headers: {
6
+ result = EuPago::Client.new({ prefix_base_url: "/api" }).post("/auth/token", body: body, headers: {
7
7
  "Content-Type" => "application/x-www-form-urlencoded",
8
8
  })
9
9
  EuPago::Current.auth = result
10
10
  result
11
11
  end
12
+
13
+ def self.ensure_valid_token
14
+ if EuPago::Current.access_token.nil? || EuPago::Current.token_expired?
15
+ fetch_client_credentials_token
16
+ end
17
+ end
18
+
19
+ def self.fetch_client_credentials_token
20
+ token(
21
+ grant_type: EuPago::Constants::GRANT_TYPES[:client_credentials],
22
+ client_id: ENV["EUPAGO_CLIENT_ID"],
23
+ client_secret: ENV["EUPAGO_CLIENT_SECRET"],
24
+ )
25
+ end
12
26
  end
13
27
  end
14
28
  end
@@ -3,13 +3,18 @@ module EuPago
3
3
  module V1
4
4
  class CreditCard
5
5
  # https://eupago.readme.io/reference/credit-card-recurrence-authorization
6
- def self.subscription(params)
7
- V1.client.post("/v1.02/creditcard/subscription", body: params)
6
+ def self.subscription(body)
7
+ V1.client.post("/creditcard/subscription", body: body)
8
8
  end
9
9
 
10
10
  # https://eupago.readme.io/reference/credit-card-recurrence-payment
11
- def self.payment(recurrent_id, params)
12
- V1.client.post("/v1.02/creditcard/payment/#{recurrent_id}", body: params)
11
+ def self.payment(recurrent_id, body)
12
+ V1.client.post("/creditcard/payment/#{recurrent_id}", body: body)
13
+ end
14
+
15
+ # https://eupago.readme.io/reference/credit-card
16
+ def self.create(body)
17
+ V1.client.post("/creditcard/create", body: body)
13
18
  end
14
19
  end
15
20
  end
@@ -3,13 +3,13 @@ module EuPago
3
3
  module V1
4
4
  class DirectDebit
5
5
  # https://eupago.readme.io/reference/direct-debit-authorization
6
- def self.authorization(params)
7
- V1.client.post("/v1.02/directdebit/authorization", body: params)
6
+ def self.authorization(body)
7
+ V1.client.post("/directdebit/authorization", body: body)
8
8
  end
9
9
 
10
10
  # https://eupago.readme.io/reference/direct-debit-payment
11
- def self.payment(reference, params)
12
- V1.client.post("/v1.02/directdebit/payment/#{reference}", body: params)
11
+ def self.payment(reference, body)
12
+ V1.client.post("/directdebit/payment/#{reference}", body: body)
13
13
  end
14
14
  end
15
15
  end
@@ -3,8 +3,8 @@ module EuPago
3
3
  module V1
4
4
  class MBWay
5
5
  # https://eupago.readme.io/reference/mbway
6
- def self.payment(params)
7
- V1.client.post("/v1.02/mbway/create", body: params)
6
+ def self.payment(body)
7
+ V1.client.post("/mbway/create", body: body)
8
8
  end
9
9
  end
10
10
  end
@@ -0,0 +1,27 @@
1
+ module EuPago
2
+ module Api
3
+ module V1
4
+ class Payouts
5
+ # Fetches payout transactions with optional parameters.
6
+ #
7
+ # @param params [Hash] Optional parameters for the request.
8
+ # @option params [String] :start_date The first date to filter payouts (YYYY-MM-DD).
9
+ # @option params [String] :end_date The final date to filter payouts (YYYY-MM-DD).
10
+ #
11
+ # @docs https://eupago.readme.io/reference/payouts-transactions
12
+ def self.transactions(params = {})
13
+ V1.oauth_client.get("/management/v1.02/payouts/transactions", query: params)
14
+ end
15
+
16
+ # Fetches payout transactions by transaction ID (trid).
17
+ #
18
+ # @param trid [String] The transaction ID to filter the request.
19
+ #
20
+ # @docs https://eupago.readme.io/reference/trid-information
21
+ def self.transaction_details(trid)
22
+ V1.oauth_client.get("/management/v1.02/payouts/transactions/#{trid}")
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,53 @@
1
+ module EuPago
2
+ module Api
3
+ module V1
4
+ class References
5
+ # Fetches references with optional parameters.
6
+ #
7
+ # @param params [Hash] Optional parameters for the request.
8
+ # @option params [String] :identifier Insert the identifier that you want to find on your search.
9
+ # @option params [String] :reference Insert the reference you want to find in your search.
10
+ # @option params [String] :start_date Specify the first date you want to search (YYYY-MM-DD). We will provide all references since that date.
11
+ #
12
+ # @docs https://eupago.readme.io/reference/advanced-search
13
+ def self.list(params = {})
14
+ V1.oauth_client.get("/management/v1.02/references/info", query: params)
15
+ end
16
+
17
+ # Fetches references by status with optional parameters.
18
+ #
19
+ # @param params [Hash] Optional parameters for the request.
20
+ # @option params [String] :status Choose the status to search (EuPago::Constants::REFERENCE_STATUS)
21
+ # @docs https://eupago.readme.io/reference/references-by-status
22
+ #
23
+ def self.list_by_status(params = {})
24
+ V1.oauth_client.get("/management/v1.02/references", query: params)
25
+ end
26
+
27
+ # Fetches reference information by reference and entity.
28
+ #
29
+ # @param body [Hash] Required parameters for the request.
30
+ # @option body [String] :referencia Reference identifier to search for.
31
+ # @option body [String] :entidade Entity associated with the reference (Not all services have an entity).
32
+ #
33
+ # @return [Hash] Reference information response from the API.
34
+ #
35
+ # @docs https://eupago.readme.io/reference/reference-information
36
+ def self.find(body)
37
+ V1.body_client.post("/clientes/rest_api/multibanco/info", body: body)
38
+ end
39
+
40
+ # =========
41
+ # Alias Methods
42
+ # =========
43
+
44
+ # Fetches reference information by reference.
45
+ # @alias find_by_reference for find method with reference parameter.
46
+ #
47
+ def self.find_by_reference(reference, body = {})
48
+ find(body.merge({ referencia: reference }))
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -4,6 +4,14 @@ module EuPago
4
4
  def self.client
5
5
  @client ||= EuPago::Api.client
6
6
  end
7
+
8
+ def self.oauth_client
9
+ @oauth_client ||= EuPago::Api.oauth_client
10
+ end
11
+
12
+ def self.body_client
13
+ @body_client ||= EuPago::Api.body_client
14
+ end
7
15
  end
8
16
  end
9
17
  end
@@ -11,3 +19,5 @@ end
11
19
  require "ruby-eupago/api/v1/credit_card"
12
20
  require "ruby-eupago/api/v1/mbway"
13
21
  require "ruby-eupago/api/v1/direct_debit"
22
+ require "ruby-eupago/api/v1/payouts"
23
+ require "ruby-eupago/api/v1/references"
@@ -1,7 +1,20 @@
1
1
  module EuPago
2
2
  module Api
3
+ # EuPago current REST API uses three different types of authentication:
4
+ #
5
+ # 1 - ApiKey Auth (API Key sent as an header param)
3
6
  def self.client
4
- @client ||= EuPago::Client.new({ include_api_key: true })
7
+ @client ||= EuPago::Client.new({ include_api_key: true, prefix_base_url: "/api/v1.02" })
8
+ end
9
+
10
+ # 2 -OAuth 2.0 (Bearer Token sent as an header param)
11
+ def self.oauth_client
12
+ @oauth_client ||= EuPago::OAuthClient.new({ prefix_base_url: "/api" })
13
+ end
14
+
15
+ # 3 - API Key sent as a body param
16
+ def self.body_client
17
+ @body_client ||= EuPago::Client.new({ include_api_key: false, include_api_key_in_body: true })
5
18
  end
6
19
  end
7
20
  end
@@ -19,6 +19,17 @@ module EuPago
19
19
  once: "OOFF",
20
20
  recurring: "RCUR",
21
21
  final: "FNAL",
22
- }
22
+ }.freeze
23
+
24
+ REFERENCE_STATUS = {
25
+ paid: "paga",
26
+ pending: "pendente",
27
+ expired: "expirada",
28
+ error: "erro",
29
+ canceled: "cancelada",
30
+ refunded: "reembolsada",
31
+ returned: "devolvida",
32
+ archived: "arquivada",
33
+ }.freeze
23
34
  end
24
35
  end
@@ -1,17 +1,25 @@
1
1
  module EuPago
2
2
  module Current
3
3
  @auth = {}
4
+ @token_expires_at = nil
4
5
 
5
6
  def self.auth=(value)
6
7
  @auth = Hash[value.map { |(k, v)| [k.to_sym, v] }]
8
+ @token_expires_at = Time.now + @auth[:expires_in].to_i if @auth[:expires_in]
7
9
  end
8
10
 
9
11
  def self.access_token
10
12
  @auth[:access_token] if @auth && !@auth.empty?
11
13
  end
12
14
 
15
+ def self.token_expired?
16
+ return true if @token_expires_at.nil?
17
+
18
+ Time.now >= @token_expires_at
19
+ end
20
+
13
21
  def self.logged_in?
14
- !access_token.nil? && !access_token.empty?
22
+ !access_token.nil? && !access_token.empty? && !token_expired?
15
23
  end
16
24
  end
17
25
  end
@@ -5,15 +5,16 @@ module EuPago
5
5
  module Client
6
6
  def initialize(config = {})
7
7
  options = Hash[config.map { |(k, v)| [k.to_sym, v] }]
8
- @base_url = options[:base_url] || build_base_url
8
+ @base_url = build_base_url(options.fetch(:prefix_base_url, ""))
9
9
  @include_api_key = options.fetch(:include_api_key, false)
10
+ @include_api_key_in_body = options.fetch(:include_api_key_in_body, false)
10
11
  end
11
12
 
12
13
  def build_base_url(append_base_url = "")
13
14
  if ENV["EUPAGO_PRODUCTION"].to_s.empty?
14
- "https://sandbox.eupago.pt/api#{append_base_url}"
15
+ "https://sandbox.eupago.pt#{append_base_url}"
15
16
  else
16
- "https://clientes.eupago.pt/api#{append_base_url}"
17
+ "https://clientes.eupago.pt#{append_base_url}"
17
18
  end
18
19
  end
19
20
 
@@ -31,6 +32,7 @@ module EuPago
31
32
 
32
33
  def post(api_url, body: {}, headers: {})
33
34
  kheader = build_headers(headers)
35
+ body[:chave] = ENV.fetch("EUPAGO_API_KEY", "") if @include_api_key_in_body && body[:chave].nil?
34
36
  kbody = kheader["Content-Type"] == "application/json" ? body.to_json : body
35
37
 
36
38
  result = HTTParty.post(
@@ -0,0 +1,29 @@
1
+ require "ruby-eupago/mixins/initializer"
2
+
3
+ module EuPago
4
+ class OAuthClient
5
+ include EuPago::Mixins::Client
6
+
7
+ def get(api_url, query: {}, headers: {})
8
+ EuPago::Api::Auth.ensure_valid_token
9
+ super(api_url, query: query, headers: headers)
10
+ end
11
+
12
+ def post(api_url, body: {}, headers: {})
13
+ EuPago::Api::Auth.ensure_valid_token
14
+ super(api_url, body: body, headers: headers)
15
+ end
16
+
17
+ private
18
+
19
+ def build_headers(additional_headers = {})
20
+ headers = super(additional_headers)
21
+
22
+ if EuPago::Current.access_token
23
+ headers["Authorization"] = "Bearer #{EuPago::Current.access_token}"
24
+ end
25
+
26
+ headers
27
+ end
28
+ end
29
+ end
@@ -1,7 +1,7 @@
1
1
  module EuPago
2
2
  module Version
3
3
  MAJOR = 0
4
- MINOR = 1
4
+ MINOR = 2
5
5
  PATCH = 0
6
6
  STRING = "#{MAJOR}.#{MINOR}.#{PATCH}"
7
7
  end
data/lib/ruby-eupago.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require_relative "ruby-eupago/constants"
2
2
  require_relative "ruby-eupago/current"
3
3
  require_relative "ruby-eupago/client"
4
+ require_relative "ruby-eupago/oauth_client"
4
5
 
5
6
  require_relative "ruby-eupago/api"
6
7
  require_relative "ruby-eupago/api/v1"
data/ruby-eupago.gemspec CHANGED
@@ -4,8 +4,8 @@ Gem::Specification.new do |spec|
4
4
  spec.name = 'ruby-eupago'
5
5
  spec.version = EuPago::Version::STRING
6
6
  spec.date = '2025-09-10'
7
- spec.summary = 'Eupago Ruby SDK'
8
- spec.description = 'Eupago Ruby SDK'
7
+ spec.summary = 'Unofficial Ruby SDK for EuPago payment gateway.'
8
+ spec.description = 'A convenient, unofficial Ruby SDK for integrating with the EuPago payment gateway. Includes authentication helpers, VCR-based test suite, and a structure SDK.'
9
9
  spec.authors = ['Alexandro Castro']
10
10
  spec.email = 'alexoliveira7x@gmail.com'
11
11
  spec.license = 'MIT'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-eupago
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexandro Castro
@@ -136,7 +136,9 @@ dependencies:
136
136
  - - ">="
137
137
  - !ruby/object:Gem::Version
138
138
  version: '0'
139
- description: Eupago Ruby SDK
139
+ description: A convenient, unofficial Ruby SDK for integrating with the EuPago payment
140
+ gateway. Includes authentication helpers, VCR-based test suite, and a structure
141
+ SDK.
140
142
  email: alexoliveira7x@gmail.com
141
143
  executables: []
142
144
  extensions: []
@@ -151,10 +153,13 @@ files:
151
153
  - lib/ruby-eupago/api/v1/credit_card.rb
152
154
  - lib/ruby-eupago/api/v1/direct_debit.rb
153
155
  - lib/ruby-eupago/api/v1/mbway.rb
156
+ - lib/ruby-eupago/api/v1/payouts.rb
157
+ - lib/ruby-eupago/api/v1/references.rb
154
158
  - lib/ruby-eupago/client.rb
155
159
  - lib/ruby-eupago/constants.rb
156
160
  - lib/ruby-eupago/current.rb
157
161
  - lib/ruby-eupago/mixins/initializer.rb
162
+ - lib/ruby-eupago/oauth_client.rb
158
163
  - lib/ruby-eupago/version.rb
159
164
  - ruby-eupago.gemspec
160
165
  homepage:
@@ -179,5 +184,5 @@ requirements: []
179
184
  rubygems_version: 3.5.22
180
185
  signing_key:
181
186
  specification_version: 4
182
- summary: Eupago Ruby SDK
187
+ summary: Unofficial Ruby SDK for EuPago payment gateway.
183
188
  test_files: []