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
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: cc1d6afd8cb462672623e84afe97821c5078e62ba5fa29adaa1c8af637afffb0
4
+ data.tar.gz: 1856d71a8889905da81c500f2259449f78e7e119235fd9429923913e4a1ca4ef
5
+ SHA512:
6
+ metadata.gz: '068ee6b4ce7811008df5f432f877820c4e3b79969b09dc78d5bb2fdc80711209a982ff71b96b1d0f67e83964db4addae4a7de2f6ce0c369e5f15aee5a10aa14c'
7
+ data.tar.gz: a015998bc9e4414aa7f753e91eed92cde70cc9cffc762b86341b1fa6b6287edd085db757c5eddda8bc449da96dbbfe784293a7822878274285fddb75e98e2851
data/.gitignore ADDED
@@ -0,0 +1,75 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # rspec failure tracking
11
+ .rspec_status
12
+ *.gem
13
+ *.rbc
14
+ /.config
15
+ /coverage/
16
+ /InstalledFiles
17
+ /pkg/
18
+ /spec/reports/
19
+ /spec/examples.txt
20
+ /test/tmp/
21
+ /test/version_tmp/
22
+ /tmp/
23
+
24
+ # Used by dotenv library to load environment variables.
25
+ # .env
26
+
27
+ ## Specific to RubyMotion:
28
+ .dat*
29
+ .repl_history
30
+ build/
31
+ *.bridgesupport
32
+ build-iPhoneOS/
33
+ build-iPhoneSimulator/
34
+
35
+ ## Specific to RubyMotion (use of CocoaPods):
36
+ #
37
+ # We recommend against adding the Pods directory to your .gitignore. However
38
+ # you should judge for yourself, the pros and cons are mentioned at:
39
+ # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
40
+ #
41
+ # vendor/Pods/
42
+
43
+ ## Documentation cache and generated files:
44
+ /.yardoc/
45
+ /_yardoc/
46
+ /doc/
47
+ /rdoc/
48
+
49
+ ## Environment normalization:
50
+ /.bundle/
51
+ /vendor/bundle
52
+ /lib/bundler/man/
53
+
54
+ # for a library or gem, you might want to ignore these files since the code is
55
+ # intended to run in multiple environments; otherwise, check them in:
56
+ # Gemfile.lock
57
+ # .ruby-version
58
+ # .ruby-gemset
59
+
60
+ # for intellij products
61
+ .idea
62
+
63
+ # rubocop
64
+ rubocop.html
65
+ tmp
66
+
67
+ # rubocop
68
+ rubocop.html
69
+
70
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
71
+ .rvmrc
72
+
73
+ # yml files
74
+ #lib/k2-connect-ruby/k2_utilities/config/k2_config.yml
75
+ lib/k2-connect-ruby/k2_utilities/spec_modules/test_config.yml
data/.gitmodules ADDED
@@ -0,0 +1,6 @@
1
+ [submodule "example_app/rails/kt_tips_rails"]
2
+ path = example_app/rails/kt_tips_rails
3
+ url = git@github.com:DavidKar1uk1/kt_tips_rails.git
4
+ [submodule "example_app/sinatra/kt_tips"]
5
+ path = example_app/sinatra/kt_tips
6
+ url = git@github.com:DavidKar1uk1/kt_tips.git
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ sudo: false
3
+ language: ruby
4
+ cache: bundler
5
+ rvm:
6
+ - 2.5.0
7
+ before_install: gem install bundler -v 2.0.1
data/CHANGELOG.md ADDED
File without changes
@@ -0,0 +1,74 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported by contacting the project team at David.mwangi@kopokop.com. All
59
+ complaints will be reviewed and investigated and will result in a response that
60
+ is deemed necessary and appropriate to the circumstances. The project team is
61
+ obligated to maintain confidentiality with regard to the reporter of an incident.
62
+ Further details of specific enforcement policies may be posted separately.
63
+
64
+ Project maintainers who do not follow or enforce the Code of Conduct in good
65
+ faith may face temporary or permanent repercussions as determined by other
66
+ members of the project's leadership.
67
+
68
+ ## Attribution
69
+
70
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
+ available at [http://contributor-covenant.org/version/1/4][version]
72
+
73
+ [homepage]: http://contributor-covenant.org
74
+ [version]: http://contributor-covenant.org/version/1/4/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in k2-connect-ruby.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,127 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ k2-connect-ruby (0.0.1)
5
+ activemodel (~> 6.1.3.1)
6
+ activesupport (~> 6.1.3.1)
7
+ rest-client (~> 2.1.0)
8
+ yajl-ruby (~> 1.4.1)
9
+
10
+ GEM
11
+ remote: https://rubygems.org/
12
+ specs:
13
+ activemodel (6.1.3.1)
14
+ activesupport (= 6.1.3.1)
15
+ activesupport (6.1.3.1)
16
+ concurrent-ruby (~> 1.0, >= 1.0.2)
17
+ i18n (>= 1.6, < 2)
18
+ minitest (>= 5.1)
19
+ tzinfo (~> 2.0)
20
+ zeitwerk (~> 2.3)
21
+ addressable (2.7.0)
22
+ public_suffix (>= 2.0.2, < 5.0)
23
+ coderay (1.1.3)
24
+ concurrent-ruby (1.1.8)
25
+ crack (0.4.5)
26
+ rexml
27
+ diff-lcs (1.4.4)
28
+ domain_name (0.5.20190701)
29
+ unf (>= 0.0.5, < 1.0.0)
30
+ ffi (1.15.0)
31
+ formatador (0.2.5)
32
+ guard (2.16.2)
33
+ formatador (>= 0.2.4)
34
+ listen (>= 2.7, < 4.0)
35
+ lumberjack (>= 1.0.12, < 2.0)
36
+ nenv (~> 0.1)
37
+ notiffany (~> 0.0)
38
+ pry (>= 0.9.12)
39
+ shellany (~> 0.0)
40
+ thor (>= 0.18.1)
41
+ guard-compat (1.2.1)
42
+ guard-rspec (4.7.3)
43
+ guard (~> 2.1)
44
+ guard-compat (~> 1.1)
45
+ rspec (>= 2.99.0, < 4.0)
46
+ hashdiff (1.0.1)
47
+ http-accept (1.7.0)
48
+ http-cookie (1.0.3)
49
+ domain_name (~> 0.5)
50
+ i18n (1.8.10)
51
+ concurrent-ruby (~> 1.0)
52
+ listen (3.5.1)
53
+ rb-fsevent (~> 0.10, >= 0.10.3)
54
+ rb-inotify (~> 0.9, >= 0.9.10)
55
+ lumberjack (1.2.8)
56
+ method_source (1.0.0)
57
+ mime-types (3.3.1)
58
+ mime-types-data (~> 3.2015)
59
+ mime-types-data (3.2021.0225)
60
+ minitest (5.14.4)
61
+ nenv (0.3.0)
62
+ netrc (0.11.0)
63
+ notiffany (0.1.3)
64
+ nenv (~> 0.1)
65
+ shellany (~> 0.0)
66
+ pry (0.14.0)
67
+ coderay (~> 1.1)
68
+ method_source (~> 1.0)
69
+ public_suffix (4.0.6)
70
+ rake (13.0.3)
71
+ rb-fsevent (0.10.4)
72
+ rb-inotify (0.10.1)
73
+ ffi (~> 1.0)
74
+ rest-client (2.1.0)
75
+ http-accept (>= 1.7.0, < 2.0)
76
+ http-cookie (>= 1.0.2, < 2.0)
77
+ mime-types (>= 1.16, < 4.0)
78
+ netrc (~> 0.8)
79
+ rexml (3.2.5)
80
+ rspec (3.10.0)
81
+ rspec-core (~> 3.10.0)
82
+ rspec-expectations (~> 3.10.0)
83
+ rspec-mocks (~> 3.10.0)
84
+ rspec-core (3.10.1)
85
+ rspec-support (~> 3.10.0)
86
+ rspec-expectations (3.10.1)
87
+ diff-lcs (>= 1.2.0, < 2.0)
88
+ rspec-support (~> 3.10.0)
89
+ rspec-mocks (3.10.2)
90
+ diff-lcs (>= 1.2.0, < 2.0)
91
+ rspec-support (~> 3.10.0)
92
+ rspec-nc (0.3.0)
93
+ rspec (>= 3)
94
+ terminal-notifier (>= 1.4)
95
+ rspec-support (3.10.2)
96
+ shellany (0.0.1)
97
+ terminal-notifier (2.0.0)
98
+ thor (1.1.0)
99
+ tzinfo (2.0.4)
100
+ concurrent-ruby (~> 1.0)
101
+ unf (0.1.4)
102
+ unf_ext
103
+ unf_ext (0.0.7.7)
104
+ vcr (6.0.0)
105
+ webmock (3.12.2)
106
+ addressable (>= 2.3.6)
107
+ crack (>= 0.3.2)
108
+ hashdiff (>= 0.4.0, < 2.0.0)
109
+ yajl-ruby (1.4.1)
110
+ zeitwerk (2.4.2)
111
+
112
+ PLATFORMS
113
+ ruby
114
+
115
+ DEPENDENCIES
116
+ bundler (~> 2.0)
117
+ guard (~> 2.16.2)
118
+ guard-rspec (~> 4.7.3)
119
+ k2-connect-ruby!
120
+ rake (~> 13.0.3)
121
+ rspec (~> 3.10.0)
122
+ rspec-nc (~> 0.3.0)
123
+ vcr (~> 6.0.0)
124
+ webmock (~> 3.12.2)
125
+
126
+ BUNDLED WITH
127
+ 2.2.11
data/Guardfile ADDED
@@ -0,0 +1,80 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ ## Uncomment and set this to only include directories you want to watch
5
+ # directories %w(app lib config test spec features) \
6
+ # .select{|d| Dir.exist?(d) ? d : UI.warning("Directory #{d} does not exist")}
7
+
8
+ ## Note: if you are using the `directories` clause above and you are not
9
+ ## watching the project directory ('.'), then you will want to move
10
+ ## the Guardfile to a watched dir and symlink it back, e.g.
11
+ #
12
+ # $ mkdir config
13
+ # $ mv Guardfile config/
14
+ # $ ln -s config/Guardfile .
15
+ #
16
+ # and, you'll have to watch "config/Guardfile" instead of "Guardfile"
17
+
18
+ # Note: The cmd option is now required due to the increasing number of ways
19
+ # rspec may be run, below are examples of the most common uses.
20
+ # * bundler: 'bundle exec rspec'
21
+ # * bundler binstubs: 'bin/rspec'
22
+ # * spring: 'bin/rspec' (This will use spring if running and you have
23
+ # installed the spring binstubs per the docs)
24
+ # * zeus: 'zeus rspec' (requires the server to be started separately)
25
+ # * 'just' rspec: 'rspec'
26
+
27
+ guard :rspec, cmd: "bundle exec rspec" do
28
+ require "guard/rspec/dsl"
29
+ dsl = Guard::RSpec::Dsl.new(self)
30
+
31
+ # Feel free to open issues for suggestions and improvements
32
+
33
+ # RSpec files
34
+ rspec = dsl.rspec
35
+ watch(rspec.spec_helper) { rspec.spec_dir }
36
+ watch(rspec.spec_support) { rspec.spec_dir }
37
+ watch(rspec.spec_files)
38
+
39
+ # Ruby files
40
+ ruby = dsl.ruby
41
+ dsl.watch_spec_files_for(ruby.lib_files)
42
+
43
+ # Rails files
44
+ rails = dsl.rails(view_extensions: %w(erb haml slim))
45
+ dsl.watch_spec_files_for(rails.app_files)
46
+ dsl.watch_spec_files_for(rails.views)
47
+
48
+ watch(rails.controllers) do |m|
49
+ [
50
+ rspec.spec.call("routing/#{m[1]}_routing"),
51
+ rspec.spec.call("controllers/#{m[1]}_controller"),
52
+ rspec.spec.call("acceptance/#{m[1]}")
53
+ ]
54
+ end
55
+
56
+ # Rails config changes
57
+ watch(rails.spec_helper) { rspec.spec_dir }
58
+ watch(rails.routes) { "#{rspec.spec_dir}/routing" }
59
+ watch(rails.app_controller) { "#{rspec.spec_dir}/controllers" }
60
+
61
+ # Capybara features specs
62
+ watch(rails.view_dirs) { |m| rspec.spec.call("features/#{m[1]}") }
63
+ watch(rails.layouts) { |m| rspec.spec.call("features/#{m[1]}") }
64
+
65
+ # Turnip features and steps
66
+ watch(%r{^spec/acceptance/(.+)\.feature$})
67
+ watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) do |m|
68
+ Dir[File.join("**/#{m[1]}.feature")][0] || "spec/acceptance"
69
+ end
70
+
71
+ # watch /lib/ files
72
+ watch(%r{^lib/(.+).rb$}) do |m|
73
+ "spec/#{m[1]}_spec.rb"
74
+ end
75
+
76
+ # watch /spec/ files
77
+ watch(%r{^spec/(.+).rb$}) do |m|
78
+ "spec/#{m[1]}.rb"
79
+ end
80
+ end
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2019 Kopo Kopo Inc
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,542 @@
1
+ # K2ConnectRuby For Rails
2
+
3
+ Ruby SDK for connection to the Kopo Kopo API.
4
+ This documentation gives you the specifications for connecting your systems to the Kopo Kopo Application.
5
+ Primarily, the library provides functionality to do the following:
6
+
7
+ - Receive Webhook notifications.
8
+ - Receive payments from your users/customers.
9
+ - Initiate payments to third parties.
10
+ - Initiate transfers to your settlement accounts.
11
+
12
+ The library is optimized for **Rails Based Frameworks**.
13
+ Please note, all requests MUST be made over HTTPS.
14
+ Any non-secure requests are met with a redirect (HTTP 302) to the HTTPS equivalent URI.
15
+ All calls made without authentication will also fail.
16
+
17
+ ## LINKS
18
+
19
+ - [Installation](https://github.com/DavidKar1uk1/k2-connect-ruby/tree/development#installation)
20
+ - [Usage](https://github.com/DavidKar1uk1/k2-connect-ruby/tree/development#installation)
21
+ - [Authorization](https://github.com/DavidKar1uk1/k2-connect-ruby/tree/development#authorization)
22
+ - [Webhook Subscription](https://github.com/DavidKar1uk1/k2-connect-ruby/tree/development#webhook-subscription)
23
+ - [STK Push](https://github.com/DavidKar1uk1/k2-connect-ruby/tree/development#stk-push)
24
+ - [PAY](https://github.com/DavidKar1uk1/k2-connect-ruby/tree/development#pay)
25
+ - [Transfers](https://github.com/DavidKar1uk1/k2-connect-ruby/tree/development#transfers)
26
+ - [Parsing the JSON Payload](https://github.com/DavidKar1uk1/k2-connect-ruby/tree/development#parsing-the-json-payload)
27
+ - [Development](https://github.com/DavidKar1uk1/k2-connect-ruby/tree/development#development)
28
+ - [Author](https://github.com/DavidKar1uk1/k2-connect-ruby/tree/development#author)
29
+ - [Contributing](https://github.com/DavidKar1uk1/k2-connect-ruby/tree/development#contributing)
30
+ - [License](https://github.com/DavidKar1uk1/k2-connect-ruby/tree/development#license)
31
+ - [Changelog](https://github.com/DavidKar1uk1/k2-connect-ruby/tree/development#changelog)
32
+ - [Code of Conduct](https://github.com/DavidKar1uk1/k2-connect-ruby/tree/development#code-of-conduct)
33
+
34
+ ## Installation
35
+
36
+ Add this line to your application's Gemfile:
37
+
38
+ gem 'k2-connect-ruby'
39
+
40
+ And then execute:
41
+
42
+ $ bundle install
43
+
44
+ Or install it yourself:
45
+
46
+ $ gem install k2-connect-ruby
47
+
48
+ ## Usage
49
+
50
+ Add the require line to use the gem:
51
+
52
+ require 'k2-connect-ruby'
53
+
54
+ ### Authorization
55
+
56
+ Ensure you first Register your application with the [Kopo Kopo Sandbox](To be added later when launched).
57
+ Once an application is registered you will obtain your `client_id` and `client_secret` (aka client credentials), which will be used to identify your application when calling the Kopo Kopo API.
58
+
59
+ For more Information, visit our [API docs]().
60
+
61
+ In order to request for application authorization and receive an access token, we need to execute the client credentials flow, this is done so by having your application server make a HTTPS request to the Kopo Kopo authorization server, through the K2AccessToken class.
62
+
63
+ ```ruby
64
+ k2_token = K2AccessToken.new('your_client_id', 'your_client_secret').request_token
65
+ ```
66
+
67
+ ### Webhook Subscription
68
+
69
+ ##### Remember to store highly sensitive information like the client credentials, in a config file, while indicating in your .gitignore file.
70
+
71
+ Next, we formally create the webhook subscription by calling on the webhook_subscribe method.
72
+ Ensure the following arguments are passed:
73
+ - event type `REQUIRED`
74
+ - url `REQUIRED`
75
+ - scope `REQUIRED`: is `till` if event_type is a buygoods_transaction_received, buygoods_transaction_reversed or b2b_transaction_received, and `company` if not
76
+ - scope reference: is `REQUIRED` if scope is till
77
+
78
+ Code example;
79
+
80
+ ```ruby
81
+ require 'k2-connect-ruby'
82
+ k2_token = K2AccessToken.new('your_client_id', 'your_client_secret').request_token
83
+ k2subscriber = K2Subscribe.new(k2_token)
84
+
85
+ your_request = {
86
+ event_type: 'buygoods_transaction_received',
87
+ url: callback_url,
88
+ scope: 'till',
89
+ scope_reference: '112233'
90
+ }
91
+ k2subscriber.webhook_subscribe(your_request)
92
+ ```
93
+
94
+
95
+ ### STK-Push
96
+
97
+ #### Receive Payments
98
+
99
+ To receive payments from M-PESA users via STK Push we first create a K2Stk Object, passing the access_token that was created prior.
100
+
101
+ k2_stk = K2Stk.new(your_access_token)
102
+
103
+ Afterwards we send a POST request for receiving Payments by calling the following method and passing the params value received from the POST Form Request:
104
+
105
+ k2_stk.receive_mpesa_payments(your_input)
106
+
107
+ Ensure the following arguments are passed:
108
+ - payment_channel `REQUIRED`
109
+ - till_number `REQUIRED`: from the Online Payments Account created with Kopo Kopo Inc Web App
110
+ - first_name
111
+ - last_name
112
+ - phone_number `REQUIRED`
113
+ - email
114
+ - currency: default is `KES`
115
+ - value `REQUIRED`
116
+ - callback_url `REQUIRED`
117
+
118
+ A Successful Response will be received containing the URL of the Payment Location.
119
+
120
+ #### Query Request Status
121
+
122
+ To Query the STK Payment Request Status pass the Payment location URL response that is returned:
123
+
124
+ k2_stk.query_resource(k2_stk.location_url)
125
+
126
+ To Query the most recent STK Request Status is as follows:
127
+
128
+ k2_stk.query_status
129
+
130
+ As a result a JSON payload will be returned, accessible with the k2_response_body variable.
131
+
132
+ Code example;
133
+
134
+ ```ruby
135
+ k2_stk = K2Stk.new(your_access_token)
136
+
137
+ your_request = {
138
+ payment_channel: 'M-PESA',
139
+ till_number: 'K112233',
140
+ first_name: stk_params[:first_name],
141
+ last_name: stk_params[:last_name],
142
+ phone_number: stk_params[:phone],
143
+ email: stk_params[:email],
144
+ currency: stk_params[:currency],
145
+ value: stk_params[:value],
146
+ callback_url: callback_url
147
+ }
148
+ k2_stk.receive_mpesa_payments(your_request)
149
+ k2_stk.query_resource(k2_stk.location_url)
150
+ ```
151
+
152
+ ### PAY
153
+
154
+ First Create the K2Pay Object passing the access token
155
+
156
+
157
+ k2_pay = K2Pay.new(access_token)
158
+
159
+ #### Add PAY Recipients
160
+
161
+ Add a PAY Recipient, with the following arguments:
162
+
163
+ **Mobile** PAY Recipient
164
+ - type: 'mobile_wallet' `REQUIRED`
165
+ - first_name `REQUIRED`
166
+ - last_name `REQUIRED`
167
+ - phone_number `REQUIRED`
168
+ - email `REQUIRED`
169
+ - network `REQUIRED`
170
+
171
+ **Bank** PAY Recipient
172
+ - type: 'bank_account' `REQUIRED`
173
+ - account_name `REQUIRED`
174
+ - account_number `REQUIRED`
175
+ - bank_branch_ref `REQUIRED`
176
+ - settlement_method: 'EFT' or 'RTS' `REQUIRED`
177
+
178
+
179
+ k2_pay.add_recipients(your_input)
180
+
181
+ The type value can either be `mobile_wallet` or `bank_account`
182
+
183
+ A Successful Response is returned with the URL of the recipient resource.
184
+
185
+ #### Create Outgoing Payment
186
+
187
+ Creating an Outgoing Payment to a third party.
188
+
189
+ k2_pay.create_payment(your_input)
190
+
191
+ The following arguments should be passed within a hash:
192
+
193
+ - destination_reference `REQUIRED`
194
+ - destination_type `REQUIRED`
195
+ - currency default is `KES`
196
+ - value `REQUIRED`
197
+ - callback_url `REQUIRED`
198
+
199
+ A Successful Response is returned with the URL of the Payment resource in the HTTP Location Header.
200
+
201
+ #### Query PAY Request Status
202
+
203
+ To Query the status of the Add Recipient or Outgoing Payment request:
204
+
205
+ // add recipient
206
+ k2_pay.query_resource(k2_pay.recipients_location_url)
207
+ // create outgoing payment
208
+ k2_pay.query_resource(k2_pay.payments_location_url)
209
+
210
+ To Query the most recent status of either the Add Recipient or Outgoing Payment request:
211
+
212
+ // add recipient
213
+ k2_pay.query_status('recipients')
214
+ // create outgoing payment
215
+ k2_pay.query_status('payments')
216
+
217
+ As a result a JSON payload will be returned, accessible with the k2_response_body variable.
218
+
219
+ Code example;
220
+
221
+ ```ruby
222
+ k2_pay = K2Pay.new(your_access_token)
223
+ k2_pay.add_recipient(your_recipient_input)
224
+ k2_pay.query_resource(k2_pay.recipients_location_url)
225
+ k2_pay.create_payment(your_payment_input)
226
+ k2_pay.query_resource(k2_pay.payments_location_url)
227
+ ```
228
+
229
+ ### Settlement Accounts
230
+
231
+ Add pre-approved settlement accounts, to which one can transfer funds to. Can be either a bank or mobile wallet account,
232
+ with the following details:
233
+
234
+ **Mobile** Settlement Account
235
+ - type: 'merchant_wallet' `REQUIRED`
236
+ - first_name `REQUIRED`
237
+ - last_name `REQUIRED`
238
+ - phone_number `REQUIRED`
239
+ - network: 'Safaricom' `REQUIRED`
240
+
241
+ **Bank** Settlement Account
242
+ - type: 'merchant_bank_account' `REQUIRED`
243
+ - account_name `REQUIRED`
244
+ - account_number `REQUIRED`
245
+ - bank_branch_ref `REQUIRED`
246
+ - settlement_method: 'EFT' or 'RTS' `REQUIRED`
247
+
248
+ ```ruby
249
+ k2_settlement = K2Settlement.new(your_access_token)
250
+ # Add a mobile merchant wallet
251
+ k2_settlement.add_settlement_account(merchant_wallet)
252
+ # Add a merchant bank account
253
+ k2_settlement.add_settlement_account(merchant_bank_account)
254
+ ```
255
+
256
+ ### Transfers
257
+
258
+ This will Enable one to transfer funds to your settlement accounts.
259
+
260
+ First Create the K2Transfer Object
261
+
262
+ k2_transfers = K2Transfer.new(access_token)
263
+
264
+ #### Create Transfer Request
265
+
266
+ One can either have it `blind`, meaning that it has no specified destination with the default/specified settlement account being selected,
267
+ or one can have a `targeted` transfer with a specified settlement account in mind. Either can be done through:
268
+
269
+ ##### Blind Transfer
270
+
271
+ k2_transfers.transfer_funds(nil, params)
272
+
273
+ With `nil` representing that there are no specified destinations.
274
+
275
+ ##### Target Transfer
276
+
277
+ k2_transfers.transfer_funds(params)
278
+
279
+ The Following Details should be passed for either **Blind** or **Targeted** Transfer:
280
+
281
+ **Blind** Transfer to your default settlement account
282
+ - currency default is `KES`
283
+ - value `REQUIRED`
284
+ - callback_url `REQUIRED`
285
+
286
+ **Targeted** Transfer
287
+ - destination_reference `REQUIRED`
288
+ - destination_type: `merchant_wallet` or `merchant_bank_account` `REQUIRED`
289
+ - currency default is `KES`
290
+ - value `REQUIRED`
291
+ - callback_url `REQUIRED`
292
+
293
+ The Params are passed as the argument containing all the form data sent. A Successful Response is returned with the URL of the Transfer in the HTTP Location Header.
294
+
295
+ Sample code example:
296
+
297
+ ```ruby
298
+ k2_transfer = K2Transfer.new(your_access_token)
299
+ # Blind or Targeted Transfer
300
+ k2_transfer.transfer_funds(your_input)
301
+ ```
302
+
303
+ #### Query Prior Transfer
304
+
305
+ To Query the status of the prior initiated Transfer Request pass the location_url response as shown:
306
+
307
+ k2_transfers.query_resource(k2_transfers.location_url)
308
+
309
+ To Query the most recent initiated Transfer Request:
310
+
311
+ k2_transfers.query_status
312
+
313
+ A HTTP Response will be returned in a JSON Payload, accessible with the k2_response_body variable.
314
+
315
+ ### Parsing the JSON Payload
316
+
317
+ The K2Client class will be use to parse the Payload received from Kopo Kopo, and to further consume the webhooks and split the responses into components, the K2Authenticator and
318
+ K2ProcessResult Classes will be used.
319
+
320
+ ###### K2Client Object
321
+
322
+ First Create an Object of the K2Client class to Parse the response, passing the client_secret_key received from Kopo Kopo:
323
+
324
+ k2_parse = K2Client.new(client_secret)
325
+
326
+ ###### Parse the request
327
+
328
+ k2_parse.parse_request(request)
329
+
330
+ ###### Create an Object
331
+
332
+ Create an Object to receive the components resulting from processing the parsed request results which will be returned by the following method:
333
+
334
+ k2_components = K2ProcessResult.process(k2_parse.hash_body)
335
+
336
+ Code example:
337
+
338
+ ```ruby
339
+ k2_parse = K2Client.new(client_secret)
340
+ k2_parse.parse_request(request)
341
+ k2_components = K2ProcessResult.process(k2_parse.hash_body)
342
+ ```
343
+
344
+ Below is a list of key symbols accessible for each of the Results retrieved after processing it into an Object.
345
+
346
+ 1. Buy Goods Transaction Received:
347
+ - `id`
348
+ - `resource_id`
349
+ - `topic`
350
+ - `created_at`
351
+ - `event_type`
352
+ - `reference`
353
+ - `origination_time`
354
+ - `sender_phone_number`
355
+ - `amount`
356
+ - `currency`
357
+ - `till_number`
358
+ - `system`
359
+ - `status`
360
+ - `sender_first_name`
361
+ - `sender_last_name`
362
+ - `links_self`
363
+ - `links_resource`
364
+
365
+ 2. Buy Goods Transaction Reversed:
366
+ - `id`
367
+ - `resource_id`
368
+ - `topic`
369
+ - `created_at`
370
+ - `event_type`
371
+ - `reference`
372
+ - `origination_time`
373
+ - `sender_phone_number`
374
+ - `amount`
375
+ - `currency`
376
+ - `till_number`
377
+ - `system`
378
+ - `status`
379
+ - `sender_first_name`
380
+ - `sender_last_name`
381
+ - `links_self`
382
+ - `links_resource`
383
+
384
+ 3. Settlement Transfer:
385
+ - `id`
386
+ - `resource_id`
387
+ - `topic`
388
+ - `created_at`
389
+ - `event_type`
390
+ - `origination_time`
391
+ - `amount`
392
+ - `currency`
393
+ - `resource_status`
394
+ - `links_self`
395
+ - `links_resource`
396
+ - `destination_reference`
397
+ - `destination_type`
398
+ **Bank Account** Destination Type
399
+ - `destination_account_name`
400
+ - `destination_account_number`
401
+ - `destination_bank_branch_ref`
402
+ - `destination_settlement_method`
403
+ **Merchant Wallet** Destination Type
404
+ - `destination_first_name`
405
+ - `destination_last_name`
406
+ - `destination_phone_number`
407
+ - `destination_network`
408
+
409
+ 4. Customer Created:
410
+ - `id`
411
+ - `resource_id`
412
+ - `topic`
413
+ - `created_at`
414
+ - `event_type`
415
+ - `resource_first_name`
416
+ - `resource_middle_name`
417
+ - `resource_last_name`
418
+ - `resource_phone_number`
419
+ - `links_self`
420
+ - `links_resource`
421
+
422
+ 5. B2b Transaction Transaction (External Till to Till):
423
+ - `id`
424
+ - `resource_id`
425
+ - `topic`
426
+ - `created_at`
427
+ - `event_type`
428
+ - `reference`
429
+ - `origination_time`
430
+ - `amount`
431
+ - `currency`
432
+ - `till_number`
433
+ - `status`
434
+ - `links_self`
435
+ - `links_resource`
436
+ - `sending_till`
437
+
438
+ 6. Merchant to Merchant Transaction:
439
+ - `id`
440
+ - `resource_id`
441
+ - `topic`
442
+ - `created_at`
443
+ - `event_type`
444
+ - `reference`
445
+ - `origination_time`
446
+ - `amount`
447
+ - `currency`
448
+ - `status`
449
+ - `links_self`
450
+ - `links_resource`
451
+ - `resource_sending_merchant`
452
+
453
+ 7. Process STK Push Payment Request Result
454
+ - `id`
455
+ - `type`
456
+ - `initiation_time`
457
+ - `status`
458
+ - `event_type`
459
+ - `resource_id`
460
+ - `resource_status`
461
+ - `transaction_reference`
462
+ - `origination_time`
463
+ - `sender_phone_number`
464
+ - `amount`
465
+ - `currency`
466
+ - `till_number`
467
+ - `system`
468
+ - `sender_first_name`
469
+ - `sender_middle_name`
470
+ - `sender_last_name`
471
+ - `errors`
472
+ - `metadata`
473
+ - `links_self`
474
+ - `callback_url`
475
+
476
+ 8. Process PAY Result
477
+ - `id`
478
+ - `type`
479
+ - `created_at`
480
+ - `status`
481
+ - `transfer_batch`
482
+ - `currency`
483
+ - `value`
484
+ - `metadata`
485
+ - `links_self`
486
+ - `callback_url`
487
+
488
+ 9. Process Settlement Transfer Result
489
+ - `id`
490
+ - `type`
491
+ - `created_at`
492
+ - `status`
493
+ - `transfer_batch`
494
+ - `currency`
495
+ - `value`
496
+ - `links_self`
497
+ - `callback_url`
498
+
499
+ If you want to convert the Object into a Hash or Array, the following methods can be used.
500
+ - Hash:
501
+
502
+
503
+ k2_hash_components = K2ProcessResult.return_obj_hash(k2_components)
504
+
505
+
506
+ - Array:
507
+
508
+
509
+ k2_array_components = K2ProcessResult.return_obj_array(k2_components)
510
+
511
+
512
+ Sample Web Application examples written in Rails and Sinatra frameworks that utilize this library are available in the example_app folder or in the following GitHub hyperlinks:
513
+
514
+ - [Rails example application](https://github.com/DavidKar1uk1/kt_tips_rails)
515
+
516
+ - [Sinatra example application](https://github.com/DavidKar1uk1/kt_tips)
517
+
518
+ ##### Take Note; the Library is optimized for Rails frameworks version 5.
519
+
520
+ ## Development
521
+
522
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
523
+
524
+ ## Author
525
+
526
+ **Name**: [David Kariuki Mwangi](https://github.com/DavidJonKariz)
527
+
528
+ ## Contributing
529
+
530
+ Bug reports and pull requests are welcome on GitHub at https://github.com/kopokopo/k2-connect-ruby. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
531
+
532
+ ## License
533
+
534
+ The gem is available as open source under the terms of the [MIT License].
535
+
536
+ ## Changelog
537
+
538
+
539
+
540
+ ## Code of Conduct
541
+
542
+ Everyone interacting in the K2ConnectRuby project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/kopokopo/k2-connect-ruby/blob/master/CODE_OF_CONDUCT.md).