lipwa 0.1.2 → 0.1.4
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 +4 -4
- data/CHANGELOG.md +31 -0
- data/README.md +219 -204
- data/lib/lipwa/auth_strategies/api_key.rb +28 -0
- data/lib/lipwa/auth_strategies/base.rb +4 -0
- data/lib/lipwa/auth_strategies/bearer_token.rb +5 -0
- data/lib/lipwa/auth_strategies/jenga.rb +58 -0
- data/lib/lipwa/auth_strategies.rb +2 -0
- data/lib/lipwa/capabilities/authorize.rb +26 -0
- data/lib/lipwa/capabilities/bank_transfer.rb +66 -0
- data/lib/lipwa/capabilities/c2b.rb +11 -10
- data/lib/lipwa/capabilities/capture.rb +25 -0
- data/lib/lipwa/capabilities/disbursement.rb +16 -17
- data/lib/lipwa/capabilities/lightning_invoice.rb +75 -0
- data/lib/lipwa/capabilities/lightning_payment.rb +71 -0
- data/lib/lipwa/capabilities/purchase.rb +26 -0
- data/lib/lipwa/capabilities/refund.rb +14 -14
- data/lib/lipwa/capabilities/status_query.rb +21 -12
- data/lib/lipwa/capabilities/stk_push.rb +8 -5
- data/lib/lipwa/capabilities/void.rb +25 -0
- data/lib/lipwa/configuration_snapshot.rb +50 -0
- data/lib/lipwa/context.rb +60 -0
- data/lib/lipwa/contracts/bank_transfer_contract.rb +61 -0
- data/lib/lipwa/contracts/card_payment_contract.rb +59 -0
- data/lib/lipwa/contracts/card_transaction_contract.rb +21 -0
- data/lib/lipwa/contracts/lightning_invoice_check_contract.rb +18 -0
- data/lib/lipwa/contracts/lightning_invoice_contract.rb +27 -0
- data/lib/lipwa/contracts/lightning_payment_check_contract.rb +18 -0
- data/lib/lipwa/contracts/lightning_payment_contract.rb +14 -0
- data/lib/lipwa/contracts/status_query_contract.rb +29 -6
- data/lib/lipwa/errors.rb +4 -2
- data/lib/lipwa/gateway.rb +24 -5
- data/lib/lipwa/gateways/coop_bank/auth.rb +68 -0
- data/lib/lipwa/gateways/coop_bank.rb +115 -0
- data/lib/lipwa/gateways/flutterwave.rb +160 -0
- data/lib/lipwa/gateways/jenga/auth.rb +76 -0
- data/lib/lipwa/gateways/jenga.rb +282 -0
- data/lib/lipwa/gateways/lnbits.rb +67 -0
- data/lib/lipwa/gateways/mpesa/auth.rb +18 -2
- data/lib/lipwa/gateways/mpesa.rb +16 -11
- data/lib/lipwa/gateways/paystack.rb +119 -0
- data/lib/lipwa/gateways/pesapal/auth.rb +72 -0
- data/lib/lipwa/gateways/pesapal.rb +123 -0
- data/lib/lipwa/gateways.rb +7 -1
- data/lib/lipwa/http_adapter.rb +56 -17
- data/lib/lipwa/logging.rb +100 -0
- data/lib/lipwa/money.rb +33 -4
- data/lib/lipwa/types.rb +3 -3
- data/lib/lipwa/version.rb +1 -1
- data/lib/lipwa/webhooks/coop_bank.rb +28 -0
- data/lib/lipwa/webhooks/jenga.rb +55 -0
- data/lib/lipwa/webhooks/lnbits.rb +46 -0
- data/lib/lipwa.rb +29 -0
- metadata +32 -4
- data/CODE_OF_CONDUCT.md +0 -10
- data/Rakefile +0 -12
- data/sig/lipwa.rbs +0 -4
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "faraday"
|
|
4
|
+
require "json"
|
|
5
|
+
|
|
6
|
+
module Lipwa
|
|
7
|
+
module Logging
|
|
8
|
+
REDACTED = "[REDACTED]"
|
|
9
|
+
|
|
10
|
+
# Produces sanitized copies of nested payloads without mutating caller data.
|
|
11
|
+
module Redactor
|
|
12
|
+
SECRET_NAMES = "authorization|signature|cookie|api[_-]?key|access[_-]?token|" \
|
|
13
|
+
"refresh[_-]?token|token|consumer[_-]?key|client[_-]?id|" \
|
|
14
|
+
"secret|password|passkey|" \
|
|
15
|
+
"security[_-]?credential|private[_-]?key|admin[_-]?key|invoice[_-]?key|encryption[_-]?key"
|
|
16
|
+
SENSITIVE_KEY = /(?:#{SECRET_NAMES})/i
|
|
17
|
+
STRING_PATTERNS = [
|
|
18
|
+
/((?:authorization|proxy-authorization|signature)\s*:\s*)[^\r\n,]+/i,
|
|
19
|
+
/((?:^|[?&])(?:#{SECRET_NAMES})=)[^&#\s]+/i,
|
|
20
|
+
/(["']?(?:#{SECRET_NAMES})["']?\s*[:=]\s*["'])[^"']*(["'])/i
|
|
21
|
+
].freeze
|
|
22
|
+
|
|
23
|
+
module_function
|
|
24
|
+
|
|
25
|
+
def call(value, key: nil) # rubocop:disable Metrics/CyclomaticComplexity,Metrics/MethodLength
|
|
26
|
+
return REDACTED if sensitive_key?(key)
|
|
27
|
+
|
|
28
|
+
case value
|
|
29
|
+
when Hash
|
|
30
|
+
value.each_with_object({}) do |(child_key, child_value), copy|
|
|
31
|
+
copy[child_key] = call(child_value, key: child_key)
|
|
32
|
+
end
|
|
33
|
+
when Array then value.map { |item| call(item) }
|
|
34
|
+
when String then redact_string(value)
|
|
35
|
+
when Exception then { class: value.class.name, message: redact_string(value.message) }
|
|
36
|
+
else value
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def sensitive_key?(key) = key&.to_s&.match?(SENSITIVE_KEY)
|
|
41
|
+
|
|
42
|
+
def redact_string(value)
|
|
43
|
+
STRING_PATTERNS.reduce(value.dup) do |redacted, pattern|
|
|
44
|
+
redacted.gsub(pattern) { "#{Regexp.last_match(1)}#{REDACTED}#{Regexp.last_match(2)}" }
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Faraday middleware that emits one structured, sanitized event per call.
|
|
50
|
+
class Middleware < Faraday::Middleware
|
|
51
|
+
def initialize(app, logger)
|
|
52
|
+
super(app)
|
|
53
|
+
@logger = logger
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def call(env)
|
|
57
|
+
started_at = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
58
|
+
@app.call(env).on_complete { |completed| log(completed, started_at) }
|
|
59
|
+
rescue StandardError => e
|
|
60
|
+
log(env, started_at, error: e)
|
|
61
|
+
raise
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
private
|
|
65
|
+
|
|
66
|
+
def log(env, started_at, error: nil) # rubocop:disable Metrics/AbcSize
|
|
67
|
+
event = {
|
|
68
|
+
event: "lipwa.http", method: env.method&.to_s&.upcase,
|
|
69
|
+
url: sanitized_url(env.url), status: env.status,
|
|
70
|
+
duration_ms: elapsed_ms(started_at),
|
|
71
|
+
request: { headers: Redactor.call(env.request_headers.to_h), body: redact_body(env.request_body) },
|
|
72
|
+
response: { headers: Redactor.call(env.response_headers.to_h), body: redact_body(env.response_body) }
|
|
73
|
+
}
|
|
74
|
+
event[:error] = Redactor.call(error) if error
|
|
75
|
+
@logger.public_send(error || env.status.to_i >= 400 ? :error : :info, event)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def sanitized_url(url)
|
|
79
|
+
return unless url
|
|
80
|
+
|
|
81
|
+
copy = url.dup
|
|
82
|
+
copy.user = REDACTED if copy.user
|
|
83
|
+
copy.password = REDACTED if copy.password
|
|
84
|
+
copy.query = Redactor.redact_string(copy.query) if copy.query
|
|
85
|
+
copy.to_s
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def redact_body(body)
|
|
89
|
+
parsed = body.is_a?(String) ? JSON.parse(body) : body
|
|
90
|
+
Redactor.call(parsed)
|
|
91
|
+
rescue JSON::ParserError
|
|
92
|
+
Redactor.call(body)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def elapsed_ms(started_at)
|
|
96
|
+
((Process.clock_gettime(Process::CLOCK_MONOTONIC) - started_at) * 1000).round(1)
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
data/lib/lipwa/money.rb
CHANGED
|
@@ -4,10 +4,10 @@ require "dry/struct"
|
|
|
4
4
|
require_relative "types"
|
|
5
5
|
|
|
6
6
|
module Lipwa
|
|
7
|
-
# Immutable representation of an amount in
|
|
8
|
-
# KES has no subunit in practice, but we keep minor units as the
|
|
9
|
-
# storage form so other currencies fit the same shape later.
|
|
7
|
+
# Immutable, decimal representation of an amount in one currency.
|
|
10
8
|
class Money < Dry::Struct
|
|
9
|
+
include Comparable
|
|
10
|
+
|
|
11
11
|
attribute :amount, Types::Amount
|
|
12
12
|
attribute :currency, Types::Currency.default("KES")
|
|
13
13
|
|
|
@@ -21,16 +21,45 @@ module Lipwa
|
|
|
21
21
|
self.class.new(amount: amount - other.amount, currency: currency)
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
+
def *(other)
|
|
25
|
+
self.class.new(amount: amount * decimal_scalar(other), currency: currency)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def /(other)
|
|
29
|
+
divisor = decimal_scalar(other)
|
|
30
|
+
raise ZeroDivisionError, "divided by 0" if divisor.zero?
|
|
31
|
+
|
|
32
|
+
self.class.new(amount: amount / divisor, currency: currency)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def <=>(other)
|
|
36
|
+
return nil unless other.is_a?(self.class)
|
|
37
|
+
|
|
38
|
+
assert_same_currency!(other)
|
|
39
|
+
amount <=> other.amount
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def zero?
|
|
43
|
+
amount.zero?
|
|
44
|
+
end
|
|
45
|
+
|
|
24
46
|
def to_s
|
|
25
|
-
"#{amount} #{currency}"
|
|
47
|
+
"#{amount.to_s("F")} #{currency}"
|
|
26
48
|
end
|
|
27
49
|
|
|
28
50
|
private
|
|
29
51
|
|
|
30
52
|
def assert_same_currency!(other)
|
|
53
|
+
raise TypeError, "expected #{self.class}, got #{other.class}" unless other.is_a?(self.class)
|
|
31
54
|
return if currency == other.currency
|
|
32
55
|
|
|
33
56
|
raise ArgumentError, "currency mismatch: #{currency} vs #{other.currency}"
|
|
34
57
|
end
|
|
58
|
+
|
|
59
|
+
def decimal_scalar(value)
|
|
60
|
+
Types::Coercible::Decimal[value]
|
|
61
|
+
rescue Dry::Types::CoercionError, Dry::Types::ConstraintError
|
|
62
|
+
raise TypeError, "expected a numeric scalar, got #{value.inspect}"
|
|
63
|
+
end
|
|
35
64
|
end
|
|
36
65
|
end
|
data/lib/lipwa/types.rb
CHANGED
|
@@ -7,9 +7,9 @@ module Lipwa
|
|
|
7
7
|
module Types
|
|
8
8
|
include Dry.Types()
|
|
9
9
|
|
|
10
|
-
#
|
|
11
|
-
#
|
|
12
|
-
Amount = Types::
|
|
10
|
+
# BigDecimal-backed amounts avoid binary floating-point errors while
|
|
11
|
+
# accepting the numeric and string inputs commonly received from APIs.
|
|
12
|
+
Amount = Types::Coercible::Decimal.constrained(gteq: 0)
|
|
13
13
|
|
|
14
14
|
Currency = Types::Strict::String.constrained(format: /\A[A-Z]{3}\z/)
|
|
15
15
|
|
data/lib/lipwa/version.rb
CHANGED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../webhook"
|
|
4
|
+
|
|
5
|
+
module Lipwa
|
|
6
|
+
module Webhooks
|
|
7
|
+
# Normalizes Co-op Bank transaction callbacks into WebhookEvent.
|
|
8
|
+
module CoopBank
|
|
9
|
+
module_function
|
|
10
|
+
|
|
11
|
+
def call(body:, headers: {}) # rubocop:disable Lint/UnusedMethodArgument
|
|
12
|
+
payload = body.is_a?(String) ? JSON.parse(body) : body
|
|
13
|
+
code = payload["MessageCode"]
|
|
14
|
+
|
|
15
|
+
Lipwa::WebhookEvent.new(
|
|
16
|
+
provider: :coop_bank,
|
|
17
|
+
event_type: :transaction_status,
|
|
18
|
+
success: code.to_s == "0",
|
|
19
|
+
provider_reference: payload["MessageReference"]&.to_s,
|
|
20
|
+
message: payload["MessageDescription"]&.to_s,
|
|
21
|
+
raw: payload
|
|
22
|
+
)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
Lipwa::Webhook.register(:coop_bank, Lipwa::Webhooks::CoopBank)
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "base64"
|
|
4
|
+
require "openssl"
|
|
5
|
+
require_relative "../webhook"
|
|
6
|
+
|
|
7
|
+
module Lipwa
|
|
8
|
+
module Webhooks
|
|
9
|
+
# Parses Jenga HQ receive-payment Instant Payment Notifications (IPNs).
|
|
10
|
+
module Jenga
|
|
11
|
+
module_function
|
|
12
|
+
|
|
13
|
+
# rubocop:disable Metrics/MethodLength
|
|
14
|
+
def call(body:, headers: {})
|
|
15
|
+
payload = parse(body)
|
|
16
|
+
transaction = payload.fetch("transaction", {})
|
|
17
|
+
authorization = header(headers, "Authorization")
|
|
18
|
+
|
|
19
|
+
Lipwa::WebhookEvent.new(
|
|
20
|
+
provider: :jenga,
|
|
21
|
+
event_type: :receive_payment,
|
|
22
|
+
success: transaction["status"].to_s.casecmp?("SUCCESS"),
|
|
23
|
+
provider_reference: transaction["reference"],
|
|
24
|
+
message: transaction["remarks"],
|
|
25
|
+
raw: payload,
|
|
26
|
+
verifier: lambda do |raw:, username:, password:, **|
|
|
27
|
+
verify_signature(raw: raw, authorization: authorization, username: username, password: password)
|
|
28
|
+
end
|
|
29
|
+
)
|
|
30
|
+
end
|
|
31
|
+
# rubocop:enable Metrics/MethodLength
|
|
32
|
+
|
|
33
|
+
def parse(body)
|
|
34
|
+
body.is_a?(String) ? JSON.parse(body) : body
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def verify_signature(raw:, authorization:, username:, password:) # rubocop:disable Lint/UnusedMethodArgument
|
|
38
|
+
return false unless authorization.is_a?(String) && username.is_a?(String) && password.is_a?(String)
|
|
39
|
+
return false if username.strip.empty? || password.strip.empty?
|
|
40
|
+
|
|
41
|
+
expected = "Basic #{Base64.strict_encode64("#{username}:#{password}")}"
|
|
42
|
+
return false unless authorization.bytesize == expected.bytesize
|
|
43
|
+
|
|
44
|
+
OpenSSL.fixed_length_secure_compare(authorization, expected)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def header(headers, name)
|
|
48
|
+
pair = headers.find { |key, _| key.to_s.casecmp?(name) }
|
|
49
|
+
pair&.last
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
Lipwa::Webhook.register(:jenga, Lipwa::Webhooks::Jenga)
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "openssl"
|
|
4
|
+
require_relative "../webhook"
|
|
5
|
+
|
|
6
|
+
module Lipwa
|
|
7
|
+
module Webhooks
|
|
8
|
+
# Parses LNbits invoice-payment callbacks. LNbits does not sign webhook
|
|
9
|
+
# bodies by default; the verifier compares a per-invoice token supplied in
|
|
10
|
+
# the webhook URL instead. Treat the callback only as a notification and
|
|
11
|
+
# independently confirm payment with #check_invoice before crediting it.
|
|
12
|
+
module Lnbits
|
|
13
|
+
module_function
|
|
14
|
+
|
|
15
|
+
def call(body:, headers: {}) # rubocop:disable Lint/UnusedMethodArgument
|
|
16
|
+
payload = parse(body)
|
|
17
|
+
|
|
18
|
+
Lipwa::WebhookEvent.new(
|
|
19
|
+
provider: :lnbits,
|
|
20
|
+
event_type: :payment,
|
|
21
|
+
success: !payload.key?("paid") || payload["paid"] == true,
|
|
22
|
+
provider_reference: payload.fetch("payment_hash"),
|
|
23
|
+
message: payload["memo"],
|
|
24
|
+
raw: payload,
|
|
25
|
+
verifier: method(:verify_signature)
|
|
26
|
+
)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def parse(body)
|
|
30
|
+
body.is_a?(String) ? JSON.parse(body) : body
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# This verifies knowledge of a shared URL token, not authenticity of the
|
|
34
|
+
# body. The ** passthrough preserves the API for a future HMAC mode.
|
|
35
|
+
def verify_signature(raw: nil, expected_token: nil, provided_token: nil, **) # rubocop:disable Lint/UnusedMethodArgument
|
|
36
|
+
return false unless expected_token.is_a?(String) && provided_token.is_a?(String)
|
|
37
|
+
return false if expected_token.strip.empty?
|
|
38
|
+
return false unless expected_token.bytesize == provided_token.bytesize
|
|
39
|
+
|
|
40
|
+
OpenSSL.fixed_length_secure_compare(expected_token, provided_token)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
Lipwa::Webhook.register(:lnbits, Lipwa::Webhooks::Lnbits)
|
data/lib/lipwa.rb
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require_relative "lipwa/version"
|
|
4
4
|
require_relative "lipwa/errors"
|
|
5
|
+
require_relative "lipwa/logging"
|
|
5
6
|
require_relative "lipwa/types"
|
|
6
7
|
require_relative "lipwa/money"
|
|
7
8
|
require_relative "lipwa/response"
|
|
@@ -11,8 +12,12 @@ require_relative "lipwa/configuration"
|
|
|
11
12
|
require_relative "lipwa/capability"
|
|
12
13
|
require_relative "lipwa/gateway"
|
|
13
14
|
require_relative "lipwa/gateways"
|
|
15
|
+
require_relative "lipwa/context"
|
|
14
16
|
require_relative "lipwa/webhook"
|
|
15
17
|
require_relative "lipwa/webhooks/mpesa"
|
|
18
|
+
require_relative "lipwa/webhooks/jenga"
|
|
19
|
+
require_relative "lipwa/webhooks/coop_bank"
|
|
20
|
+
require_relative "lipwa/webhooks/lnbits"
|
|
16
21
|
require_relative "lipwa/contracts/c2b_register_urls_contract"
|
|
17
22
|
require_relative "lipwa/contracts/c2b_simulate_contract"
|
|
18
23
|
require_relative "lipwa/capabilities/c2b"
|
|
@@ -22,10 +27,34 @@ require_relative "lipwa/contracts/disbursement_contract"
|
|
|
22
27
|
require_relative "lipwa/capabilities/disbursement"
|
|
23
28
|
require_relative "lipwa/contracts/status_query_contract"
|
|
24
29
|
require_relative "lipwa/capabilities/status_query"
|
|
30
|
+
require_relative "lipwa/contracts/lightning_invoice_contract"
|
|
31
|
+
require_relative "lipwa/contracts/lightning_invoice_check_contract"
|
|
32
|
+
require_relative "lipwa/contracts/lightning_payment_contract"
|
|
33
|
+
require_relative "lipwa/contracts/lightning_payment_check_contract"
|
|
34
|
+
require_relative "lipwa/capabilities/lightning_invoice"
|
|
35
|
+
require_relative "lipwa/capabilities/lightning_payment"
|
|
36
|
+
require_relative "lipwa/gateways/lnbits"
|
|
37
|
+
require_relative "lipwa/contracts/bank_transfer_contract"
|
|
38
|
+
require_relative "lipwa/capabilities/bank_transfer"
|
|
39
|
+
require_relative "lipwa/contracts/card_payment_contract"
|
|
40
|
+
require_relative "lipwa/contracts/card_transaction_contract"
|
|
41
|
+
require_relative "lipwa/capabilities/purchase"
|
|
42
|
+
require_relative "lipwa/capabilities/authorize"
|
|
43
|
+
require_relative "lipwa/capabilities/capture"
|
|
44
|
+
require_relative "lipwa/capabilities/void"
|
|
25
45
|
require_relative "lipwa/gateways/mpesa"
|
|
46
|
+
require_relative "lipwa/gateways/coop_bank"
|
|
26
47
|
|
|
48
|
+
require_relative "lipwa/gateways/jenga"
|
|
49
|
+
require_relative "lipwa/gateways/pesapal"
|
|
50
|
+
require_relative "lipwa/gateways/flutterwave"
|
|
51
|
+
require_relative "lipwa/gateways/paystack"
|
|
27
52
|
# Unified payment gateway abstraction for African payment providers.
|
|
28
53
|
module Lipwa
|
|
54
|
+
def self.context(&block)
|
|
55
|
+
Context.new(&block)
|
|
56
|
+
end
|
|
57
|
+
|
|
29
58
|
def self.gateway(name)
|
|
30
59
|
Gateways[name]
|
|
31
60
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: lipwa
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Paul Oguda
|
|
@@ -147,42 +147,70 @@ extensions: []
|
|
|
147
147
|
extra_rdoc_files: []
|
|
148
148
|
files:
|
|
149
149
|
- CHANGELOG.md
|
|
150
|
-
- CODE_OF_CONDUCT.md
|
|
151
150
|
- LICENSE.txt
|
|
152
151
|
- README.md
|
|
153
|
-
- Rakefile
|
|
154
152
|
- lib/lipwa.rb
|
|
155
153
|
- lib/lipwa/auth_strategies.rb
|
|
154
|
+
- lib/lipwa/auth_strategies/api_key.rb
|
|
156
155
|
- lib/lipwa/auth_strategies/base.rb
|
|
157
156
|
- lib/lipwa/auth_strategies/bearer_token.rb
|
|
157
|
+
- lib/lipwa/auth_strategies/jenga.rb
|
|
158
158
|
- lib/lipwa/auth_strategies/none.rb
|
|
159
|
+
- lib/lipwa/capabilities/authorize.rb
|
|
160
|
+
- lib/lipwa/capabilities/bank_transfer.rb
|
|
159
161
|
- lib/lipwa/capabilities/c2b.rb
|
|
162
|
+
- lib/lipwa/capabilities/capture.rb
|
|
160
163
|
- lib/lipwa/capabilities/disbursement.rb
|
|
164
|
+
- lib/lipwa/capabilities/lightning_invoice.rb
|
|
165
|
+
- lib/lipwa/capabilities/lightning_payment.rb
|
|
166
|
+
- lib/lipwa/capabilities/purchase.rb
|
|
161
167
|
- lib/lipwa/capabilities/refund.rb
|
|
162
168
|
- lib/lipwa/capabilities/status_query.rb
|
|
163
169
|
- lib/lipwa/capabilities/stk_push.rb
|
|
170
|
+
- lib/lipwa/capabilities/void.rb
|
|
164
171
|
- lib/lipwa/capability.rb
|
|
165
172
|
- lib/lipwa/configuration.rb
|
|
173
|
+
- lib/lipwa/configuration_snapshot.rb
|
|
174
|
+
- lib/lipwa/context.rb
|
|
175
|
+
- lib/lipwa/contracts/bank_transfer_contract.rb
|
|
166
176
|
- lib/lipwa/contracts/c2b_register_urls_contract.rb
|
|
167
177
|
- lib/lipwa/contracts/c2b_simulate_contract.rb
|
|
178
|
+
- lib/lipwa/contracts/card_payment_contract.rb
|
|
179
|
+
- lib/lipwa/contracts/card_transaction_contract.rb
|
|
168
180
|
- lib/lipwa/contracts/disbursement_contract.rb
|
|
181
|
+
- lib/lipwa/contracts/lightning_invoice_check_contract.rb
|
|
182
|
+
- lib/lipwa/contracts/lightning_invoice_contract.rb
|
|
183
|
+
- lib/lipwa/contracts/lightning_payment_check_contract.rb
|
|
184
|
+
- lib/lipwa/contracts/lightning_payment_contract.rb
|
|
169
185
|
- lib/lipwa/contracts/refund_contract.rb
|
|
170
186
|
- lib/lipwa/contracts/status_query_contract.rb
|
|
171
187
|
- lib/lipwa/contracts/stk_push_contract.rb
|
|
172
188
|
- lib/lipwa/errors.rb
|
|
173
189
|
- lib/lipwa/gateway.rb
|
|
174
190
|
- lib/lipwa/gateways.rb
|
|
191
|
+
- lib/lipwa/gateways/coop_bank.rb
|
|
192
|
+
- lib/lipwa/gateways/coop_bank/auth.rb
|
|
193
|
+
- lib/lipwa/gateways/flutterwave.rb
|
|
194
|
+
- lib/lipwa/gateways/jenga.rb
|
|
195
|
+
- lib/lipwa/gateways/jenga/auth.rb
|
|
196
|
+
- lib/lipwa/gateways/lnbits.rb
|
|
175
197
|
- lib/lipwa/gateways/mpesa.rb
|
|
176
198
|
- lib/lipwa/gateways/mpesa/auth.rb
|
|
177
199
|
- lib/lipwa/gateways/mpesa/security_credential.rb
|
|
200
|
+
- lib/lipwa/gateways/paystack.rb
|
|
201
|
+
- lib/lipwa/gateways/pesapal.rb
|
|
202
|
+
- lib/lipwa/gateways/pesapal/auth.rb
|
|
178
203
|
- lib/lipwa/http_adapter.rb
|
|
204
|
+
- lib/lipwa/logging.rb
|
|
179
205
|
- lib/lipwa/money.rb
|
|
180
206
|
- lib/lipwa/response.rb
|
|
181
207
|
- lib/lipwa/types.rb
|
|
182
208
|
- lib/lipwa/version.rb
|
|
183
209
|
- lib/lipwa/webhook.rb
|
|
210
|
+
- lib/lipwa/webhooks/coop_bank.rb
|
|
211
|
+
- lib/lipwa/webhooks/jenga.rb
|
|
212
|
+
- lib/lipwa/webhooks/lnbits.rb
|
|
184
213
|
- lib/lipwa/webhooks/mpesa.rb
|
|
185
|
-
- sig/lipwa.rbs
|
|
186
214
|
homepage: https://github.com/kamalogudah/lipwa
|
|
187
215
|
licenses:
|
|
188
216
|
- MIT
|
data/CODE_OF_CONDUCT.md
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
# Code of Conduct
|
|
2
|
-
|
|
3
|
-
"lipwa" follows [The Ruby Community Conduct Guideline](https://www.ruby-lang.org/en/conduct) in all "collaborative space", which is defined as community communications channels (such as mailing lists, submitted patches, commit comments, etc.):
|
|
4
|
-
|
|
5
|
-
* Participants will be tolerant of opposing views.
|
|
6
|
-
* Participants must ensure that their language and actions are free of personal attacks and disparaging personal remarks.
|
|
7
|
-
* When interpreting the words and actions of others, participants should always assume good intentions.
|
|
8
|
-
* Behaviour which can be reasonably considered harassment will not be tolerated.
|
|
9
|
-
|
|
10
|
-
If you have any concerns about behaviour within this project, please contact us at ["mcpaul2058@gmail.com"](mailto:"mcpaul2058@gmail.com").
|
data/Rakefile
DELETED
data/sig/lipwa.rbs
DELETED