paymentrails-zero 0.2.13

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.
Files changed (34) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +22 -0
  3. data/lib/paymentrails/Balance.rb +4 -0
  4. data/lib/paymentrails/Batch.rb +20 -0
  5. data/lib/paymentrails/BatchSummary.rb +21 -0
  6. data/lib/paymentrails/Client.rb +100 -0
  7. data/lib/paymentrails/Configuration.rb +48 -0
  8. data/lib/paymentrails/Exceptions.rb +19 -0
  9. data/lib/paymentrails/Gateway.rb +43 -0
  10. data/lib/paymentrails/Invoice.rb +22 -0
  11. data/lib/paymentrails/InvoicePayment.rb +13 -0
  12. data/lib/paymentrails/OfflinePayment.rb +23 -0
  13. data/lib/paymentrails/Payment.rb +52 -0
  14. data/lib/paymentrails/Recipient.rb +44 -0
  15. data/lib/paymentrails/RecipientAccount.rb +30 -0
  16. data/lib/paymentrails/gateways/BalanceGateway.rb +15 -0
  17. data/lib/paymentrails/gateways/BatchGateway.rb +88 -0
  18. data/lib/paymentrails/gateways/GatewayHelper.rb +16 -0
  19. data/lib/paymentrails/gateways/InvoiceGateway.rb +77 -0
  20. data/lib/paymentrails/gateways/InvoicePaymentGateway.rb +56 -0
  21. data/lib/paymentrails/gateways/OfflinePaymentGateway.rb +61 -0
  22. data/lib/paymentrails/gateways/PaymentGateway.rb +61 -0
  23. data/lib/paymentrails/gateways/RecipientAccountGateway.rb +61 -0
  24. data/lib/paymentrails/gateways/RecipientGateway.rb +68 -0
  25. data/lib/paymentrails.rb +28 -0
  26. data/paymentrails.gemspec +18 -0
  27. data/spec/integration/BatchTest.rb +121 -0
  28. data/spec/integration/InvoicePaymentTest.rb +99 -0
  29. data/spec/integration/InvoiceTest.rb +124 -0
  30. data/spec/integration/RecipientTest.rb +91 -0
  31. data/spec/integration/helper.rb +4 -0
  32. data/spec/unit/ConfigurationTest.rb +51 -0
  33. data/spec/unit/PaymentRailsTest.rb +15 -0
  34. metadata +131 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 502087c7ed2ea4e06131cff8de78c72bae589bcf42d8ea4f88079c1fbb72e44c
4
+ data.tar.gz: 61aaf4ca7f89590eea3a6e68676b0747cfc56d7610880374621fb31401badb3e
5
+ SHA512:
6
+ metadata.gz: 655f04d7146ad8d723ea75628a410558746a9067433b917c97a7de482a11a96272197e377b74fd63c18657043ca3dec311161be40a9feaef251a23604e950928
7
+ data.tar.gz: 9ad7ae74c3b120ed3bcbdb65921dedb708a3b30e24f74c70253d61822c9a3aeafc4badd24059504c361a916c52edd608b7a282e084a95922231f73f973bb4733
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2017 Trolley, Inc.
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,4 @@
1
+ module PaymentRails
2
+ class Balance
3
+ end
4
+ end
@@ -0,0 +1,20 @@
1
+ module PaymentRails
2
+ class Batch
3
+ attr_accessor(
4
+ :id,
5
+ :amount,
6
+ :completedAt,
7
+ :createdAt,
8
+ :currency,
9
+ :description,
10
+ :sentAt,
11
+ :status,
12
+ :totalPayments,
13
+ :updatedAt,
14
+ :quoteExpiredAt,
15
+ :payments,
16
+ :tags,
17
+ :coverFees
18
+ )
19
+ end
20
+ end
@@ -0,0 +1,21 @@
1
+ module PaymentRails
2
+ class BatchSummary
3
+ attr_accessor(
4
+ :id,
5
+ :amount,
6
+ :completedAt,
7
+ :createdAt,
8
+ :currency,
9
+ :description,
10
+ :sentAt,
11
+ :status,
12
+ :totalPayments,
13
+ :updatedAt,
14
+ :methods,
15
+ :detail,
16
+ :total,
17
+ :balances,
18
+ :accounts
19
+ )
20
+ end
21
+ end
@@ -0,0 +1,100 @@
1
+ # require_relative 'Exceptions.rb'
2
+ require 'digest'
3
+ require 'net/http'
4
+ require 'openssl'
5
+ require 'uri'
6
+ require 'json'
7
+ require "rubygems"
8
+
9
+ module PaymentRails
10
+ class Client
11
+ def initialize(config)
12
+ @config = config
13
+ end
14
+
15
+ def get(endPoint)
16
+ send_request(endPoint, 'GET')
17
+ end
18
+
19
+ def post(endPoint, body)
20
+ body = body.to_json
21
+ send_request(endPoint, 'POST', body)
22
+ end
23
+
24
+ def delete(endPoint)
25
+ send_request(endPoint, 'DELETE')
26
+ end
27
+
28
+ def patch(endPoint, body)
29
+ body = body.to_json
30
+ send_request(endPoint, 'PATCH', body)
31
+ end
32
+
33
+ private
34
+
35
+ def send_request(endPoint, method, body = '')
36
+ uri = URI.parse(@config.apiBase + endPoint)
37
+ http = Net::HTTP.new(
38
+ uri.host, uri.port,
39
+ @config.proxy&.host, @config.proxy&.port, @config.proxy&.user, @config.proxy&.password
40
+ )
41
+ http.use_ssl = @config.useSsl?
42
+
43
+ spec = Gem::Specification.load("paymentrails.gemspec")
44
+
45
+ time = Time.now.to_i
46
+ headers = {'X-PR-Timestamp': time.to_s,
47
+ 'Authorization': generate_authorization(time, endPoint, method, body),
48
+ 'Content-Type': 'application/json',
49
+ 'Trolley-Source': "ruby-sdk_#{spec.version}"}
50
+
51
+ if method === "GET"
52
+ request = Net::HTTP::Get.new(uri.request_uri, headers)
53
+ elsif method === "POST"
54
+ request = Net::HTTP::Post.new(uri.request_uri, headers)
55
+ request.body = body
56
+ elsif method === "PATCH"
57
+ request = Net::HTTP::Patch.new(uri.request_uri, headers)
58
+ request.body = body
59
+ elsif method === "DELETE"
60
+ request = Net::HTTP::Delete.new(uri.request_uri, headers)
61
+ end
62
+
63
+ response = http.request(request)
64
+
65
+ if response.code != '200' && response.code != '204'
66
+ throw_status_code_exception(response.message + ' ' + response.body , response.code)
67
+ end
68
+ response.body
69
+ end
70
+
71
+ private
72
+ def generate_authorization(time, endPoint, method, body)
73
+ message = [time.to_s, method, endPoint, body].join("\n") + "\n"
74
+ signature = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), @config.privateKey, message)
75
+ 'prsign ' + @config.publicKey + ':' + signature
76
+ end
77
+
78
+ private
79
+ def throw_status_code_exception(message, code)
80
+ case code
81
+ when '400'
82
+ raise MalformedException, message
83
+ when '401'
84
+ raise AuthenticationError, message
85
+ when '403'
86
+ raise AuthorizationError, message
87
+ when '404'
88
+ raise NotFoundError, message
89
+ when '429'
90
+ raise TooManyRequestsError, message
91
+ when '500'
92
+ raise ServerError, message
93
+ when '503'
94
+ raise DownForMaintenanceError, message
95
+ else
96
+ raise UnexpectedError, message
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,48 @@
1
+ module PaymentRails
2
+ class Configuration
3
+ class InvalidProxyAddress < StandardError; end
4
+
5
+ def initialize(publicKey, privateKey, environment = 'production', proxy_uri: nil)
6
+ raise ArgumentError, 'Both key/secret must be a nonempty string' if publicKey.to_s&.empty? || privateKey.to_s&.empty?
7
+
8
+ @publicKey = publicKey
9
+ @privateKey = privateKey
10
+ @environment = environment
11
+ # failfast on a bad proxy
12
+ begin
13
+ @proxy = proxy_uri.nil? ? nil : URI.parse(proxy_uri)
14
+ rescue URI::InvalidURIError
15
+ raise InvalidProxyAddress, "Invalid proxy provided to configuration: #{proxy_uri}"
16
+ end
17
+ end
18
+
19
+ def apiBase
20
+ case environment
21
+ when 'production'
22
+ 'https://api.trolley.com'
23
+ when 'development'
24
+ 'https://api.railz.io'
25
+ when 'integration'
26
+ 'http://api.local.dev:3000'
27
+ else
28
+ 'https://api.trolley.com'
29
+ end
30
+ end
31
+
32
+ def useSsl?
33
+ apiBase.start_with? 'https'
34
+ end
35
+
36
+ attr_reader :proxy
37
+
38
+ attr_reader :publicKey
39
+
40
+ attr_writer :publicKey
41
+
42
+ attr_reader :privateKey
43
+
44
+ attr_writer :privateKey
45
+
46
+ attr_reader :environment
47
+ end
48
+ end
@@ -0,0 +1,19 @@
1
+ module PaymentRails
2
+ class PaymentRailsError < ::StandardError; end
3
+
4
+ class AuthenticationError < PaymentRailsError; end
5
+
6
+ class AuthorizationError < PaymentRailsError; end
7
+
8
+ class DownForMaintenanceError < PaymentRailsError; end
9
+
10
+ class NotFoundError < PaymentRailsError; end
11
+
12
+ class ServerError < PaymentRailsError; end
13
+
14
+ class TooManyRequestsError < PaymentRailsError; end
15
+
16
+ class UnexpectedError < PaymentRailsError; end
17
+
18
+ class MalformedException < PaymentRailsError; end
19
+ end
@@ -0,0 +1,43 @@
1
+ module PaymentRails
2
+ class Gateway
3
+ attr_reader :config
4
+ attr_writer :config
5
+
6
+ attr_reader :client
7
+ attr_writer :client
8
+
9
+ attr_reader :recipient
10
+ attr_writer :recipient
11
+
12
+ attr_reader :recipient_account
13
+ attr_writer :recipient_account
14
+
15
+ attr_reader :batch
16
+ attr_writer :batch
17
+
18
+ attr_reader :payment
19
+ attr_writer :payment
20
+
21
+ attr_reader :balance
22
+ attr_writer :balance
23
+
24
+ attr_reader :offline_payment
25
+ attr_writer :offline_payment
26
+
27
+ attr_accessor :invoice
28
+ attr_accessor :invoice_payment
29
+
30
+ def initialize(config)
31
+ @config = config
32
+ @client = Client.new(config)
33
+ @recipient = RecipientGateway.new(client)
34
+ @recipient_account = RecipientAccountGateway.new(client)
35
+ @batch = BatchGateway.new(client)
36
+ @payment = PaymentGateway.new(client)
37
+ @balance = BalanceGateway.new(client)
38
+ @offline_payment = OfflinePaymentGateway.new(client)
39
+ @invoice = InvoiceGateway.new(client)
40
+ @invoice_payment = InvoicePaymentGateway.new(client)
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,22 @@
1
+ module PaymentRails
2
+ class Invoice
3
+ attr_accessor(
4
+ :id,
5
+ :description,
6
+ :externalId,
7
+ :invoiceDate,
8
+ :dueDate,
9
+ :invoiceNumber,
10
+ :status,
11
+ :releaseAfter,
12
+ :createdAt,
13
+ :updatedAt,
14
+ :totalAmount,
15
+ :paidAmount,
16
+ :dueAmount,
17
+ :tags,
18
+ :recipientId,
19
+ :lines
20
+ )
21
+ end
22
+ end
@@ -0,0 +1,13 @@
1
+ module PaymentRails
2
+ class InvoicePayment
3
+ attr_accessor(
4
+ :id,
5
+ :batchId,
6
+ :paymentId,
7
+ :invoiceId,
8
+ :invoiceLineId,
9
+ :amount,
10
+ :invoicePayments
11
+ )
12
+ end
13
+ end
@@ -0,0 +1,23 @@
1
+ module PaymentRails
2
+ class OfflinePayment
3
+ attr_accessor(
4
+ :id,
5
+ :recipientId,
6
+ :externalId,
7
+ :memo,
8
+ :tags,
9
+ :taxReportable,
10
+ :category,
11
+ :amount,
12
+ :currency,
13
+ :withholdingAmount,
14
+ :withholdingCurrency,
15
+ :processedAt,
16
+ :equivalentWithholdingAmount,
17
+ :equivalentWithholdingCurrency,
18
+ :updatedAt,
19
+ :createdAt,
20
+ :deletedAt
21
+ )
22
+ end
23
+ end
@@ -0,0 +1,52 @@
1
+ module PaymentRails
2
+ class Payment
3
+ attr_accessor(
4
+ :id,
5
+ :status,
6
+ :isSupplyPayment,
7
+ :returnedAmount,
8
+ :sourceAmount,
9
+ :sourceCurrency,
10
+ :targetAmount,
11
+ :targetCurrency,
12
+ :exchangeRate,
13
+ :fees,
14
+ :recipientFees,
15
+ :fxRate,
16
+ :memo,
17
+ :externalId,
18
+ :processedAt,
19
+ :createdAt,
20
+ :updatedAt,
21
+ :merchantFees,
22
+ :compliance,
23
+ :payoutMethod,
24
+ :estimatedDeliveryAt,
25
+ :recipient,
26
+ :withholdingAmount,
27
+ :withholdingCurrency,
28
+ :equivalentWithholdingAmount,
29
+ :equivalentWithholdingCurrency,
30
+ :methodDisplay,
31
+ :batch,
32
+ :coverFees,
33
+ :category,
34
+ :amount,
35
+ :currency,
36
+ :taxReportable,
37
+ :taxBasisAmount,
38
+ :taxBasisCurrency,
39
+ :tags,
40
+ :account,
41
+ :initiatedAt,
42
+ :settledAt,
43
+ :returnedAt,
44
+ :returnedNote,
45
+ :returnedReason,
46
+ :failureMessage,
47
+ :merchantId,
48
+ :checkNumber,
49
+ :forceUsTaxActivity
50
+ )
51
+ end
52
+ end
@@ -0,0 +1,44 @@
1
+ module PaymentRails
2
+ class Recipient
3
+ attr_accessor(
4
+ :id,
5
+ :routeMinimum,
6
+ :routeType,
7
+ :estimatedFees,
8
+ :referenceId,
9
+ :email,
10
+ :name,
11
+ :lastName,
12
+ :firstName,
13
+ :type,
14
+ :taxType,
15
+ :status,
16
+ :language,
17
+ :complianceStatus,
18
+ :dob,
19
+ :contactEmails,
20
+ :passport,
21
+ :updatedAt,
22
+ :createdAt,
23
+ :gravatarUrl,
24
+ :governmentId,
25
+ :ssn,
26
+ :primaryCurrency,
27
+ :merchantId,
28
+ :payout,
29
+ :compliance,
30
+ :accounts,
31
+ :address,
32
+ :taxWithholdingPercentage,
33
+ :taxForm,
34
+ :taxFormStatus,
35
+ :inactiveReasons,
36
+ :payoutMethod,
37
+ :placeOfBirth,
38
+ :tags,
39
+ :taxDeliveryType,
40
+ :riskScore,
41
+ :isPortalUser
42
+ )
43
+ end
44
+ end
@@ -0,0 +1,30 @@
1
+ module PaymentRails
2
+ class RecipientAccount
3
+ attr_accessor(
4
+ :id,
5
+ :primary,
6
+ :currency,
7
+ :recipientAccountId,
8
+ :recipientId,
9
+ :recipientReferenceId,
10
+ :routeType,
11
+ :recipientFees,
12
+ :emailAddress,
13
+ :country,
14
+ :type,
15
+ :iban,
16
+ :accountNum,
17
+ :accountHolderName,
18
+ :swiftBic,
19
+ :branchId,
20
+ :bankId,
21
+ :bankName,
22
+ :bankAddress,
23
+ :bankCity,
24
+ :bankRegionCode,
25
+ :bankPostalCode,
26
+ :status,
27
+ :disabledAt
28
+ )
29
+ end
30
+ end
@@ -0,0 +1,15 @@
1
+ require_relative '../Client.rb'
2
+
3
+ module PaymentRails
4
+ class BalanceGateway
5
+ def initialize(client)
6
+ @client = client
7
+ end
8
+
9
+ def find(term = '')
10
+ response = @client.get('/v1/balances/' + term )
11
+ JSON.parse(response, object_class: OpenStruct)
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,88 @@
1
+ require_relative '../Client.rb'
2
+ require_relative 'GatewayHelper'
3
+
4
+ module PaymentRails
5
+ class BatchGateway
6
+ include GatewayHelper
7
+
8
+ def initialize(client)
9
+ @client = client
10
+ end
11
+
12
+ def find(batch_id)
13
+ response = @client.get('/v1/batches/' + batch_id)
14
+ batch_builder(response)
15
+ end
16
+
17
+ def all
18
+ response = @client.get('/v1/batches/')
19
+ batch_list_builder(response)
20
+ end
21
+
22
+ def create(body)
23
+ response = @client.post('/v1/batches/', body)
24
+ batch_builder(response)
25
+ end
26
+
27
+ def update(batch_id, body)
28
+ @client.patch('/v1/batches/' + batch_id, body)
29
+ true
30
+ end
31
+
32
+ def delete(batch_id)
33
+ @client.delete('/v1/batches/' + batch_id)
34
+ true
35
+ end
36
+
37
+ def generate_quote(batch_id)
38
+ response = @client.post('/v1/batches/' + batch_id + '/generate-quote', {})
39
+ batch_builder(response)
40
+ end
41
+
42
+ def start_processing(batch_id)
43
+ response = @client.post('/v1/batches/' + batch_id + '/start-processing', {})
44
+ batch_builder(response)
45
+ end
46
+
47
+ def search(page = 1, page_size = 10, term = '')
48
+ response = @client.get('/v1/batches?page=' + page.to_s + '&pageSize=' + page_size.to_s + '&search=' + term)
49
+ batch_list_builder(response)
50
+ end
51
+
52
+ def batch_builder(response)
53
+ batch = Batch.new
54
+ data = JSON.parse(response)
55
+ data.each do |key, value|
56
+ next unless key === 'batch'
57
+ loosely_hydrate_model(batch, value)
58
+ end
59
+ batch
60
+ end
61
+
62
+ def summary(batch_id)
63
+ response = @client.get('/v1/batches/' + batch_id + '/summary')
64
+ summary = BatchSummary.new
65
+ data = JSON.parse(response)
66
+ data.each do |key, value|
67
+ next unless key === 'batchSummary'
68
+ loosely_hydrate_model(summary, value)
69
+ end
70
+ summary
71
+ end
72
+
73
+ def batch_list_builder(response)
74
+ batches = []
75
+ data = JSON.parse(response)
76
+
77
+ data.each do |key, value|
78
+ next unless key === 'batches'
79
+ value.each do |newKey, _newValue|
80
+ batches.push(
81
+ loosely_hydrate_model(Batch.new, newKey)
82
+ )
83
+ end
84
+ end
85
+ batches
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,16 @@
1
+ module PaymentRails
2
+ module GatewayHelper
3
+ def loosely_hydrate_model(klass_instance, attributes)
4
+ attributes.each do |k, v|
5
+ begin
6
+ klass_instance.send("#{k}=", v)
7
+ rescue NoMethodError
8
+ # TODO: The API is showing non-public attributes, once we remove them from the API response we can re-add this warning.
9
+ # warn "[PaymentRails] Unknown attribute #{k} for class #{klass_instance.class.name}"
10
+ end
11
+ end
12
+
13
+ klass_instance
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,77 @@
1
+ require_relative '../Client.rb'
2
+ require_relative 'GatewayHelper'
3
+
4
+ module PaymentRails
5
+ class InvoiceGateway
6
+ include GatewayHelper
7
+
8
+ def initialize(client)
9
+ @client = client
10
+ end
11
+
12
+ def find(body)
13
+ response = @client.post('/v1/invoices/get', body)
14
+ invoice_builder(response)
15
+ end
16
+
17
+ def create(body)
18
+ response = @client.post('/v1/invoices/create', body)
19
+ invoice_builder(response)
20
+ end
21
+
22
+ def create_line(body)
23
+ response = @client.post('/v1/invoices/create-lines', body)
24
+ invoice_builder(response)
25
+ end
26
+
27
+ def search(body)
28
+ response = @client.post('/v1/invoices/search', body)
29
+ invoice_list_builder(response)
30
+ end
31
+
32
+ def update(body)
33
+ @client.post('/v1/invoices/update', body)
34
+ true
35
+ end
36
+
37
+ def update_line(body)
38
+ @client.post('/v1/invoices/update-lines', body)
39
+ true
40
+ end
41
+
42
+ def delete(body)
43
+ @client.post('/v1/invoices/delete', body)
44
+ true
45
+ end
46
+
47
+ def delete_line(body)
48
+ @client.post('/v1/invoices/delete-lines', body)
49
+ true
50
+ end
51
+
52
+ def invoice_builder(response)
53
+ invoice = Invoice.new
54
+ data = JSON.parse(response)
55
+ data.each do |key, value|
56
+ next unless key === 'invoice'
57
+ loosely_hydrate_model(invoice, value)
58
+ end
59
+ invoice
60
+ end
61
+
62
+ def invoice_list_builder(response)
63
+ invoices = []
64
+ data = JSON.parse(response)
65
+
66
+ data.each do |key, value|
67
+ next unless key === 'invoices'
68
+ value.each do |newKey, _newValue|
69
+ invoices.push(
70
+ loosely_hydrate_model(Invoice.new, newKey)
71
+ )
72
+ end
73
+ end
74
+ invoices
75
+ end
76
+ end
77
+ end