k2-connect-ruby 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +75 -0
  3. data/.gitmodules +6 -0
  4. data/.rspec +3 -0
  5. data/.travis.yml +7 -0
  6. data/CHANGELOG.md +0 -0
  7. data/CODE_OF_CONDUCT.md +74 -0
  8. data/Gemfile +4 -0
  9. data/Gemfile.lock +127 -0
  10. data/Guardfile +80 -0
  11. data/LICENSE +21 -0
  12. data/README.md +542 -0
  13. data/Rakefile +8 -0
  14. data/bin/console +14 -0
  15. data/bin/setup +8 -0
  16. data/k2-connect-ruby.gemspec +51 -0
  17. data/lib/k2-connect-ruby.rb +34 -0
  18. data/lib/k2-connect-ruby/k2_errors.rb +77 -0
  19. data/lib/k2-connect-ruby/k2_financial_entity/entities/k2_pay.rb +100 -0
  20. data/lib/k2-connect-ruby/k2_financial_entity/entities/k2_settlement.rb +49 -0
  21. data/lib/k2-connect-ruby/k2_financial_entity/entities/k2_stk.rb +48 -0
  22. data/lib/k2-connect-ruby/k2_financial_entity/entities/k2_transfer.rb +45 -0
  23. data/lib/k2-connect-ruby/k2_financial_entity/entity.rb +6 -0
  24. data/lib/k2-connect-ruby/k2_financial_entity/k2_entity.rb +34 -0
  25. data/lib/k2-connect-ruby/k2_financial_entity/k2_subscribe.rb +42 -0
  26. data/lib/k2-connect-ruby/k2_financial_entity/k2_token.rb +37 -0
  27. data/lib/k2-connect-ruby/k2_services/client/k2_client.rb +24 -0
  28. data/lib/k2-connect-ruby/k2_services/payload_process.rb +14 -0
  29. data/lib/k2-connect-ruby/k2_services/payloads/k2_transaction.rb +48 -0
  30. data/lib/k2-connect-ruby/k2_services/payloads/k2_webhooks.rb +59 -0
  31. data/lib/k2-connect-ruby/k2_services/payloads/transactions/incoming_payment.rb +46 -0
  32. data/lib/k2-connect-ruby/k2_services/payloads/transactions/outgoing_payment.rb +15 -0
  33. data/lib/k2-connect-ruby/k2_services/payloads/transactions/transfer.rb +12 -0
  34. data/lib/k2-connect-ruby/k2_services/payloads/webhooks/b2b_received.rb +10 -0
  35. data/lib/k2-connect-ruby/k2_services/payloads/webhooks/buygoods_received.rb +5 -0
  36. data/lib/k2-connect-ruby/k2_services/payloads/webhooks/buygoods_reversal.rb +5 -0
  37. data/lib/k2-connect-ruby/k2_services/payloads/webhooks/customer_created.rb +14 -0
  38. data/lib/k2-connect-ruby/k2_services/payloads/webhooks/m2m_transaction.rb +8 -0
  39. data/lib/k2-connect-ruby/k2_services/payloads/webhooks/settlement_webhook.rb +36 -0
  40. data/lib/k2-connect-ruby/k2_utilities/config/k2_config.rb +51 -0
  41. data/lib/k2-connect-ruby/k2_utilities/config/k2_config.yml +14 -0
  42. data/lib/k2-connect-ruby/k2_utilities/k2_authorize.rb +14 -0
  43. data/lib/k2-connect-ruby/k2_utilities/k2_connection.rb +38 -0
  44. data/lib/k2-connect-ruby/k2_utilities/k2_process_result.rb +43 -0
  45. data/lib/k2-connect-ruby/k2_utilities/k2_process_webhook.rb +55 -0
  46. data/lib/k2-connect-ruby/k2_utilities/k2_url_parse.rb +7 -0
  47. data/lib/k2-connect-ruby/k2_utilities/k2_validation.rb +126 -0
  48. data/lib/k2-connect-ruby/k2_utilities/spec_modules/spec_config.rb +41 -0
  49. data/lib/k2-connect-ruby/utilities.rb +19 -0
  50. data/lib/k2-connect-ruby/version.rb +3 -0
  51. metadata +265 -0
@@ -0,0 +1,51 @@
1
+ # TODO: try to see if you can implement Environment variables
2
+ module K2Config
3
+ @config = YAML.load_file(File.join(File.dirname(__FILE__), 'k2_config.yml')).with_indifferent_access
4
+
5
+ class << self
6
+ # Set the Host Url
7
+ def set_base_url(base_url)
8
+ raise ArgumentError, 'Invalid URL Format.' unless base_url =~ /\A#{URI.regexp(%w[http https])}\z/
9
+ @config[:base_url] = base_url
10
+ File.open("lib/k2-connect-ruby/k2_utilities/config/k2_config.yml", 'w') { |f| YAML.dump(@config, f) }
11
+ end
12
+
13
+ # TODO: Versioning
14
+ def set_version(version_number)
15
+ raise ArgumentError, 'Invalid Format: Version Number input should be Numeric' unless version_number.is_a?(Numeric)
16
+ @config[:version] = "v#{version_number}"
17
+ File.open("lib/k2-connect-ruby/k2_utilities/config/k2_config.yml", 'w') { |f| YAML.dump(@config, f) }
18
+ end
19
+
20
+ def version
21
+ @config[:version]
22
+ end
23
+
24
+ def path_endpoint(key)
25
+ unless key.eql?('oauth_token')
26
+ return "api/#{version}/#{@config[:endpoints][:"#{key}"]}"
27
+ end
28
+ @config[:endpoints][:"#{key}"]
29
+ end
30
+
31
+ def path_endpoints
32
+ @config[:endpoints]
33
+ end
34
+
35
+ def path_url(key)
36
+ # TODO: Custom error/exception message
37
+ base_url + path_endpoint(key)
38
+ end
39
+
40
+ def network_operators
41
+ @config[:network_operators]
42
+ end
43
+
44
+ private
45
+
46
+ def base_url
47
+ @config[:base_url]
48
+ end
49
+ end
50
+
51
+ end
@@ -0,0 +1,14 @@
1
+ --- !ruby/hash:ActiveSupport::HashWithIndifferentAccess
2
+ version: v1
3
+ base_url: http://127.0.0.1:3000/
4
+ endpoints: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
5
+ oauth_token: oauth/token
6
+ webhook_subscriptions: webhook_subscriptions
7
+ pay_recipient: pay_recipients
8
+ payments: payments
9
+ incoming_payments: incoming_payments
10
+ settlement_mobile_wallet: merchant_wallets
11
+ settlement_bank_account: merchant_bank_accounts
12
+ transfers: settlement_transfers
13
+ network_operators:
14
+ - SAFARICOM
@@ -0,0 +1,14 @@
1
+ require 'openssl'
2
+ require 'active_support/security_utils'
3
+ # Module for Authenticating the Kopo Kopo Signature via HMAC
4
+ module K2Authenticator
5
+ # Compares HMAC signature with the key.
6
+ def self.authenticate(body, api_secret_key, signature)
7
+ raise ArgumentError, "Nil Authentication Argument!\n Check whether your Input is Empty" if body.blank? || api_secret_key.blank? || signature.blank?
8
+
9
+ digest = OpenSSL::Digest.new('sha256')
10
+ hmac = OpenSSL::HMAC.hexdigest(digest, api_secret_key, body.to_json)
11
+ raise ArgumentError, "Invalid Details Given!\n Ensure that your the Arguments Given are correct, namely:\n\t- The Response Body\n\t- Secret Key\n\t- Signature" unless ActiveSupport::SecurityUtils.secure_compare(hmac, signature)
12
+ true
13
+ end
14
+ end
@@ -0,0 +1,38 @@
1
+ module K2Connect
2
+ # Method for sending the request to K2 sandbox or Mock Server
3
+ def self.make_request(connection_hash)
4
+ access_token = connection_hash[:access_token]
5
+ class_type = connection_hash[:class_type]
6
+ path_url = connection_hash[:path_url]
7
+ request_type = connection_hash[:request_type]
8
+
9
+ unless class_type.eql?('Access Token') || access_token.present?
10
+ raise ArgumentError, 'No Access Token in Arguments!'
11
+ end
12
+
13
+ # Set up Headers
14
+ headers = { 'Content-Type': 'application/json', Accept: 'application/vnd.kopokopo.v1.hal+json', Authorization: "Bearer #{access_token}" }
15
+ if path_url.include?('oauth/token')
16
+ headers = { 'Content-Type': 'application/json' }
17
+ end
18
+
19
+ k2_response = RestClient::Request.execute(method: request_type, url: path_url, headers: headers, payload: connection_hash[:params].to_json)
20
+
21
+ # Response Body
22
+ response_body = Yajl::Parser.parse(k2_response.body)
23
+ response_headers = Yajl::Parser.parse(k2_response.headers.to_json)
24
+ response_code = k2_response.code.to_s
25
+ raise K2ConnectionError.new(response_code) && k2_request.shutdown unless response_code[0].eql?(2.to_s)
26
+
27
+ unless request_type.eql?('get')
28
+ # Returns the access token for authorization
29
+ return response_body['access_token'] if path_url.include?('oauth/token')
30
+
31
+ # Return the location url for post Requests
32
+ return response_headers["location"]
33
+ end
34
+
35
+ # Return the result of the Query
36
+ return response_body
37
+ end
38
+ end
@@ -0,0 +1,43 @@
1
+ # Processes Results
2
+ module K2ProcessResult
3
+ def self.process(payload, secret_key, signature)
4
+ raise ArgumentError, 'Empty/Nil Request Body Argument!' if payload.blank?
5
+ self.check_type(payload) if K2Authenticator.authenticate(payload, secret_key, signature)
6
+ end
7
+
8
+ # Check the Event Type.
9
+ def self.check_type(payload)
10
+ result_type = payload.dig('data', 'type')
11
+ case result_type
12
+ # Incoming Payments
13
+ when 'incoming_payment'
14
+ incoming_payments = IncomingPayments.new(payload)
15
+ return incoming_payments
16
+ # Outgoing Payments
17
+ when 'payment'
18
+ outgoing_payments = OutgoingPayment.new(payload)
19
+ return outgoing_payments
20
+ when 'settlement_transfer'
21
+ transfer = Transfer.new(payload)
22
+ return transfer
23
+ else
24
+ raise ArgumentError, 'No Other Specified Payment Type!'
25
+ end
26
+ end
27
+
28
+ # Returns a Hash Object
29
+ def self.return_obj_hash(instance_hash = HashWithIndifferentAccess.new, obj)
30
+ obj.instance_variables.each do |value|
31
+ instance_hash[:"#{value.to_s.tr('@', '')}"] = obj.instance_variable_get(value)
32
+ end
33
+ instance_hash.each(&:freeze).freeze
34
+ end
35
+
36
+ # Returns an Array Object
37
+ def self.return_obj_array(instance_array = [], obj)
38
+ obj.instance_variables.each do |value|
39
+ instance_array << obj.instance_variable_get(value)
40
+ end
41
+ instance_array.each(&:freeze).freeze
42
+ end
43
+ end
@@ -0,0 +1,55 @@
1
+ # Processes Webhook
2
+ module K2ProcessWebhook
3
+ def self.process(payload, secret_key, signature)
4
+ raise ArgumentError, 'Empty/Nil Request Body Argument!' if payload.blank?
5
+ self.check_topic(payload) if K2Authenticator.authenticate(payload, secret_key, signature)
6
+ end
7
+
8
+ def self.check_topic(payload)
9
+ result_topic = payload.dig('topic')
10
+ case result_topic
11
+ # Buygoods Transaction Received
12
+ when 'buygoods_transaction_received'
13
+ buygoods_received = BuygoodsTransactionReceived.new(payload)
14
+ return buygoods_received
15
+ # Buygoods Transaction Reversed
16
+ when 'buygoods_transaction_reversed'
17
+ buygoods_reversed = BuygoodsTransactionReversed.new(payload)
18
+ return buygoods_reversed
19
+ # B2b Transaction
20
+ when 'b2b_transaction_received'
21
+ b2b_transaction = B2b.new(payload)
22
+ return b2b_transaction
23
+ # Merchant to Merchant
24
+ when 'm2m_transaction_received'
25
+ m2m_transaction_received = MerchantToMerchant.new(payload)
26
+ return m2m_transaction_received
27
+ # Settlement Transfer
28
+ when 'settlement_transfer_completed'
29
+ settlement_transfer = SettlementWebhook.new(payload)
30
+ return settlement_transfer
31
+ # Customer Created
32
+ when 'customer_created'
33
+ customer_created = CustomerCreated.new(payload)
34
+ return customer_created
35
+ else
36
+ raise ArgumentError, 'No Other Specified Event!'
37
+ end
38
+ end
39
+
40
+ # Returns a Hash Object
41
+ def self.return_obj_hash(instance_hash = HashWithIndifferentAccess.new, obj)
42
+ obj.instance_variables.each do |value|
43
+ instance_hash[:"#{value.to_s.tr('@', '')}"] = obj.instance_variable_get(value)
44
+ end
45
+ instance_hash.each(&:freeze).freeze
46
+ end
47
+
48
+ # Returns an Array Object
49
+ def self.return_obj_array(instance_array = [], obj)
50
+ obj.instance_variables.each do |value|
51
+ instance_array << obj.instance_variable_get(value)
52
+ end
53
+ instance_array.each(&:freeze).freeze
54
+ end
55
+ end
@@ -0,0 +1,7 @@
1
+ # Module for dealing with Parsing URLS properly
2
+ module K2UrlParse
3
+ def self.remove_localhost(url)
4
+ url.host = '127.0.0.1' if url.host.eql?('localhost')
5
+ url
6
+ end
7
+ end
@@ -0,0 +1,126 @@
1
+ # Module for Validating Input
2
+ # TODO: Correct validation of url so that it only accepts https
3
+ module K2Validation
4
+ ALL_EVENT_TYPES = %[buygoods_transaction_received b2b_transaction_received buygoods_transaction_reversed customer_created settlement_transfer_completed m2m_transaction_received]
5
+ TILL_SCOPE_EVENT_TYPES = %[buygoods_transaction_received b2b_transaction_received buygoods_transaction_reversed]
6
+
7
+ # Validating Method
8
+ def validate_input(the_input, the_array)
9
+ if the_input.blank?
10
+ raise ArgumentError, "Empty or Nil Input!\n No Input Content has been given."
11
+ else
12
+ unless !!the_input == the_input
13
+ if the_input.is_a?(Hash)
14
+ validate_hash(the_input.with_indifferent_access, the_array)
15
+ else
16
+ begin
17
+ if the_input.is_a?(String)
18
+ raise ArgumentError, "Wrong Input Format.\n The Input is a String."
19
+ elsif the_input.is_a?(Integer)
20
+ raise ArgumentError, "Wrong Input Format.\n The Input is an Integer."
21
+ elsif the_input.key?(:authenticity_token)
22
+ nil_values(the_input.permit(the_array).to_hash.with_indifferent_access)
23
+ else
24
+ raise ArgumentError, "Undefined Input Format.\n The Input is Neither a Hash nor an ActionController::Parameter Object."
25
+ end
26
+ rescue NoMethodError => nme
27
+ if nme.message.include?('has_key?')
28
+ raise ArgumentError, "Undefined Input Format.\n The Input is Neither a Hash nor an ActionController::Parameter Object."
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ to_indifferent_access(the_input)
35
+ end
36
+
37
+ # Validate the Hash Input Parameters
38
+ def validate_hash(the_input, the_array)
39
+ nil_values(the_input)
40
+ incorrect_keys(the_input, the_array)
41
+ end
42
+
43
+ # Return Incorrect Key Symbols for Hashes
44
+ def incorrect_keys(the_input, invalid_hash = [], the_array)
45
+ the_input.each_key do |key|
46
+ validate_network(the_input[:network]) if key.eql?("network")
47
+ validate_settlement_method(the_input[:settlement_method]) if key.eql?("settlement_method")
48
+ invalid_hash << key unless the_array.include?(key.to_s)
49
+ end
50
+ raise K2IncorrectParams, invalid_hash if invalid_hash.present?
51
+ end
52
+
53
+ # Return Key Symbols with Blank Values
54
+ def nil_values(the_input, nil_keys_array = [])
55
+ the_input.select { |_, v| v.blank? }.each_key do |key|
56
+ nil_keys_array << key.to_s
57
+ end
58
+ raise K2EmptyParams, nil_keys_array unless nil_keys_array.blank?
59
+ end
60
+
61
+ # Validate Phone Number
62
+ def validate_phone(phone)
63
+ raise ArgumentError, "No Phone Number given." if phone.blank?
64
+ # Kenyan Phone Numbers
65
+ unless phone.blank?
66
+ if phone[-(number = phone.to_i.to_s.size).to_i, 3].eql?(254.to_s)
67
+ raise ArgumentError, 'Invalid Kenyan Phone Number.' unless phone[-9, 9][0].eql?(7.to_s)
68
+ else
69
+ raise ArgumentError, 'Invalid Phone Number.' unless number.eql?(9)
70
+ end
71
+ phone.tr('+', '')
72
+ end
73
+ end
74
+
75
+ # Validate Email Format
76
+ def validate_email(email)
77
+ unless email.blank?
78
+ raise ArgumentError, 'Invalid Email Address.' unless email.match(URI::MailTo::EMAIL_REGEXP).present?
79
+ end
80
+ email
81
+ end
82
+
83
+ # Validate the Network Operator
84
+ def validate_network(network)
85
+ raise ArgumentError, "Invalid Network Operator." unless K2Config.network_operators.include?(network.to_s.upcase)
86
+ end
87
+
88
+ def validate_settlement_method(settlement_method)
89
+ raise ArgumentError, "Wrong Settlement Method" unless settlement_method.eql?("EFT") || settlement_method.eql?("RTS")
90
+ end
91
+
92
+ # Converts Hash Objects to HashWithIndifferentAccess Objects
93
+ def to_indifferent_access(params)
94
+ params.with_indifferent_access
95
+ end
96
+
97
+ def validate_url(url)
98
+ raise ArgumentError, 'Invalid URL Format.' unless url =~ /\A#{URI.regexp(%w[https http])}\z/
99
+ url
100
+ end
101
+
102
+ def validate_till_number_prefix(till_number)
103
+ raise ArgumentError, "No Till Number given." if till_number.blank?
104
+ raise ArgumentError, "Invalid Till Number format." unless till_number[0, 1].eql?('K')
105
+ till_number
106
+ end
107
+
108
+ def validate_webhook(params)
109
+ raise ArgumentError, 'Subscription Service does not Exist!' unless params[:event_type].in?(ALL_EVENT_TYPES)
110
+ determine_scope_details(params)
111
+ end
112
+
113
+ def validate_webhook_input(params)
114
+ if params[:event_type].in?(TILL_SCOPE_EVENT_TYPES)
115
+ validate_input(params, %w[event_type scope scope_reference url])
116
+ else
117
+ validate_input(params.except(:scope_reference), %w[event_type scope url])
118
+ end
119
+ end
120
+
121
+ def determine_scope_details(params)
122
+ if params[:scope].eql?('till')
123
+ raise ArgumentError, "Invalid scope till for the event type" unless params[:event_type].in?(TILL_SCOPE_EVENT_TYPES)
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,41 @@
1
+ module SpecConfig
2
+ TILL_SCOPE_EVENT_TYPES = %[buygoods_transaction_received b2b_transaction_received buygoods_transaction_reversed]
3
+
4
+ @specs = YAML.load_file(File.join('lib', 'k2-connect-ruby', 'k2_utilities', 'spec_modules', 'test_config.yml')).with_indifferent_access
5
+
6
+ def subscription_stub_request(event_type, url)
7
+ request_body = { event_type: event_type, url: url, secret: 'webhook_secret' }
8
+ SpecConfig.custom_stub_request('post', K2Config.path_url('webhook_subscriptions'), request_body, 200)
9
+ end
10
+
11
+ def webhook_structure(event_type, scope, scope_reference = nil)
12
+ {
13
+ event_type: event_type,
14
+ url: @callback_url,
15
+ scope: scope,
16
+ scope_reference: scope_reference,
17
+ }
18
+ end
19
+
20
+ class << self
21
+ def callback_url(context)
22
+ @specs[:callback_url][:"#{context}"]
23
+ end
24
+
25
+ def custom_stub_request(request_type, path_url, request_body, response_code)
26
+ request_body = request_body.to_s
27
+ request_uri = path_url
28
+ request_headers = { Authorization: "Bearer access_token", Accept: "application/vnd.kopokopo.v1.hal+json" }
29
+
30
+ if request_type.eql?('post')
31
+ request_headers['Content-Type'] = 'application/json'
32
+ end
33
+
34
+ # Stub Request
35
+ WebMock.stub_request(:"#{request_type}", request_uri)
36
+ .with(headers: request_headers, body: request_body)
37
+ .to_return(status: response_code)
38
+ end
39
+ end
40
+
41
+ end
@@ -0,0 +1,19 @@
1
+ require 'k2-connect-ruby/k2_utilities/k2_url_parse'
2
+ require 'k2-connect-ruby/k2_utilities/k2_authorize'
3
+ require 'k2-connect-ruby/k2_utilities/k2_connection'
4
+ require 'k2-connect-ruby/k2_utilities/k2_validation'
5
+ require 'k2-connect-ruby/k2_utilities/config/k2_config'
6
+ require 'k2-connect-ruby/k2_utilities/k2_process_result'
7
+ require 'k2-connect-ruby/k2_utilities/k2_process_webhook'
8
+
9
+ module K2Utilities
10
+ def make_hash(path_url, request, access_token, class_type, body)
11
+ {
12
+ path_url: path_url,
13
+ access_token: access_token,
14
+ request_type: request,
15
+ class_type: class_type,
16
+ params: body
17
+ }.with_indifferent_access
18
+ end
19
+ end
@@ -0,0 +1,3 @@
1
+ module K2ConnectRuby
2
+ VERSION = '0.0.1'
3
+ end
metadata ADDED
@@ -0,0 +1,265 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: k2-connect-ruby
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - DavidKar1uk1
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2021-04-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 6.1.3.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 6.1.3.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: activemodel
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 6.1.3.1
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 6.1.3.1
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: guard
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 2.16.2
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 2.16.2
69
+ - !ruby/object:Gem::Dependency
70
+ name: guard-rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 4.7.3
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 4.7.3
83
+ - !ruby/object:Gem::Dependency
84
+ name: rest-client
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 2.1.0
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 2.1.0
97
+ - !ruby/object:Gem::Dependency
98
+ name: rake
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: 13.0.3
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: 13.0.3
111
+ - !ruby/object:Gem::Dependency
112
+ name: rspec
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: 3.10.0
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: 3.10.0
125
+ - !ruby/object:Gem::Dependency
126
+ name: rspec-nc
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: 0.3.0
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: 0.3.0
139
+ - !ruby/object:Gem::Dependency
140
+ name: vcr
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: 6.0.0
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: 6.0.0
153
+ - !ruby/object:Gem::Dependency
154
+ name: webmock
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - "~>"
158
+ - !ruby/object:Gem::Version
159
+ version: 3.12.2
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - "~>"
165
+ - !ruby/object:Gem::Version
166
+ version: 3.12.2
167
+ - !ruby/object:Gem::Dependency
168
+ name: yajl-ruby
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - "~>"
172
+ - !ruby/object:Gem::Version
173
+ version: 1.4.1
174
+ type: :runtime
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - "~>"
179
+ - !ruby/object:Gem::Version
180
+ version: 1.4.1
181
+ description: Ruby SDK for connection to the Kopo Kopo API, with webhook handling and
182
+ JSON request parsing with the Ruby on Rails framework.
183
+ email:
184
+ - David.mwangi@kopokopo.com
185
+ executables: []
186
+ extensions: []
187
+ extra_rdoc_files: []
188
+ files:
189
+ - ".gitignore"
190
+ - ".gitmodules"
191
+ - ".rspec"
192
+ - ".travis.yml"
193
+ - CHANGELOG.md
194
+ - CODE_OF_CONDUCT.md
195
+ - Gemfile
196
+ - Gemfile.lock
197
+ - Guardfile
198
+ - LICENSE
199
+ - README.md
200
+ - Rakefile
201
+ - bin/console
202
+ - bin/setup
203
+ - k2-connect-ruby.gemspec
204
+ - lib/k2-connect-ruby.rb
205
+ - lib/k2-connect-ruby/k2_errors.rb
206
+ - lib/k2-connect-ruby/k2_financial_entity/entities/k2_pay.rb
207
+ - lib/k2-connect-ruby/k2_financial_entity/entities/k2_settlement.rb
208
+ - lib/k2-connect-ruby/k2_financial_entity/entities/k2_stk.rb
209
+ - lib/k2-connect-ruby/k2_financial_entity/entities/k2_transfer.rb
210
+ - lib/k2-connect-ruby/k2_financial_entity/entity.rb
211
+ - lib/k2-connect-ruby/k2_financial_entity/k2_entity.rb
212
+ - lib/k2-connect-ruby/k2_financial_entity/k2_subscribe.rb
213
+ - lib/k2-connect-ruby/k2_financial_entity/k2_token.rb
214
+ - lib/k2-connect-ruby/k2_services/client/k2_client.rb
215
+ - lib/k2-connect-ruby/k2_services/payload_process.rb
216
+ - lib/k2-connect-ruby/k2_services/payloads/k2_transaction.rb
217
+ - lib/k2-connect-ruby/k2_services/payloads/k2_webhooks.rb
218
+ - lib/k2-connect-ruby/k2_services/payloads/transactions/incoming_payment.rb
219
+ - lib/k2-connect-ruby/k2_services/payloads/transactions/outgoing_payment.rb
220
+ - lib/k2-connect-ruby/k2_services/payloads/transactions/transfer.rb
221
+ - lib/k2-connect-ruby/k2_services/payloads/webhooks/b2b_received.rb
222
+ - lib/k2-connect-ruby/k2_services/payloads/webhooks/buygoods_received.rb
223
+ - lib/k2-connect-ruby/k2_services/payloads/webhooks/buygoods_reversal.rb
224
+ - lib/k2-connect-ruby/k2_services/payloads/webhooks/customer_created.rb
225
+ - lib/k2-connect-ruby/k2_services/payloads/webhooks/m2m_transaction.rb
226
+ - lib/k2-connect-ruby/k2_services/payloads/webhooks/settlement_webhook.rb
227
+ - lib/k2-connect-ruby/k2_utilities/config/k2_config.rb
228
+ - lib/k2-connect-ruby/k2_utilities/config/k2_config.yml
229
+ - lib/k2-connect-ruby/k2_utilities/k2_authorize.rb
230
+ - lib/k2-connect-ruby/k2_utilities/k2_connection.rb
231
+ - lib/k2-connect-ruby/k2_utilities/k2_process_result.rb
232
+ - lib/k2-connect-ruby/k2_utilities/k2_process_webhook.rb
233
+ - lib/k2-connect-ruby/k2_utilities/k2_url_parse.rb
234
+ - lib/k2-connect-ruby/k2_utilities/k2_validation.rb
235
+ - lib/k2-connect-ruby/k2_utilities/spec_modules/spec_config.rb
236
+ - lib/k2-connect-ruby/utilities.rb
237
+ - lib/k2-connect-ruby/version.rb
238
+ homepage: https://github.com/kopokopo/k2-connect-ruby.git
239
+ licenses:
240
+ - MIT
241
+ metadata:
242
+ allowed_push_host: https://rubygems.org
243
+ homepage_uri: https://github.com/kopokopo/k2-connect-ruby.git
244
+ source_code_uri: https://github.com/kopokopo/k2-connect-ruby.git
245
+ changelog_uri: https://github.com/kopokopo/k2-connect-ruby.git/CHANGELOG.MD
246
+ post_install_message:
247
+ rdoc_options: []
248
+ require_paths:
249
+ - lib
250
+ required_ruby_version: !ruby/object:Gem::Requirement
251
+ requirements:
252
+ - - ">="
253
+ - !ruby/object:Gem::Version
254
+ version: '0'
255
+ required_rubygems_version: !ruby/object:Gem::Requirement
256
+ requirements:
257
+ - - ">="
258
+ - !ruby/object:Gem::Version
259
+ version: '0'
260
+ requirements: []
261
+ rubygems_version: 3.0.6
262
+ signing_key:
263
+ specification_version: 4
264
+ summary: Ruby SDK for connection to the Kopo Kopo API.
265
+ test_files: []