k2-connect-ruby 3.0.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/.github/pull_request_template.md +31 -0
  3. data/.gitignore +2 -0
  4. data/Gemfile.lock +38 -5
  5. data/README.md +499 -198
  6. data/k2-connect-ruby.gemspec +39 -35
  7. data/lib/k2-connect-ruby/entity.rb +39 -9
  8. data/lib/k2-connect-ruby/http_client.rb +43 -0
  9. data/lib/k2-connect-ruby/k2_entity/k2_entity.rb +12 -11
  10. data/lib/k2-connect-ruby/k2_entity/k2_financial_entities/destination/destination_request.rb +27 -0
  11. data/lib/k2-connect-ruby/k2_entity/k2_financial_entities/destination/external_bank_account.rb +32 -0
  12. data/lib/k2-connect-ruby/k2_entity/k2_financial_entities/destination/external_mpesa_wallet.rb +38 -0
  13. data/lib/k2-connect-ruby/k2_entity/k2_financial_entities/destination/external_paybill.rb +31 -0
  14. data/lib/k2-connect-ruby/k2_entity/k2_financial_entities/destination/external_till.rb +30 -0
  15. data/lib/k2-connect-ruby/k2_entity/k2_financial_entities/destination/merchant_bank_account.rb +27 -0
  16. data/lib/k2-connect-ruby/k2_entity/k2_financial_entities/destination/merchant_mpesa_wallet.rb +27 -0
  17. data/lib/k2-connect-ruby/k2_entity/k2_financial_entities/external_recipient/bank_account.rb +17 -0
  18. data/lib/k2-connect-ruby/k2_entity/k2_financial_entities/external_recipient/mobile_wallet.rb +24 -0
  19. data/lib/k2-connect-ruby/k2_entity/k2_financial_entities/external_recipient/paybill.rb +17 -0
  20. data/lib/k2-connect-ruby/k2_entity/k2_financial_entities/external_recipient/recipient_request.rb +32 -0
  21. data/lib/k2-connect-ruby/k2_entity/k2_financial_entities/external_recipient/till.rb +17 -0
  22. data/lib/k2-connect-ruby/k2_entity/k2_financial_entities/external_recipient.rb +54 -0
  23. data/lib/k2-connect-ruby/k2_entity/k2_financial_entities/k2_stk.rb +14 -31
  24. data/lib/k2-connect-ruby/k2_entity/k2_financial_entities/payment_link.rb +53 -0
  25. data/lib/k2-connect-ruby/k2_entity/k2_financial_entities/payment_links/payment_link_request.rb +43 -0
  26. data/lib/k2-connect-ruby/k2_entity/k2_financial_entities/reversal.rb +39 -0
  27. data/lib/k2-connect-ruby/k2_entity/k2_financial_entities/reversals/reversal_request.rb +39 -0
  28. data/lib/k2-connect-ruby/k2_entity/k2_financial_entities/send_money/send_money_request.rb +53 -0
  29. data/lib/k2-connect-ruby/k2_entity/k2_financial_entities/send_money.rb +73 -0
  30. data/lib/k2-connect-ruby/k2_entity/k2_financial_entities/stk_push/stk_push_request.rb +51 -0
  31. data/lib/k2-connect-ruby/k2_entity/k2_financial_entities/transfer_account/merchant_bank_account.rb +35 -0
  32. data/lib/k2-connect-ruby/k2_entity/k2_financial_entities/transfer_account/merchant_mpesa_wallet.rb +38 -0
  33. data/lib/k2-connect-ruby/k2_entity/k2_financial_entities/transfer_account/transfer_account_request.rb +25 -0
  34. data/lib/k2-connect-ruby/k2_entity/k2_financial_entities/transfer_account.rb +49 -0
  35. data/lib/k2-connect-ruby/k2_entity/k2_polling.rb +16 -13
  36. data/lib/k2-connect-ruby/k2_entity/k2_subscribe.rb +16 -14
  37. data/lib/k2-connect-ruby/k2_entity/k2_token.rb +14 -39
  38. data/lib/k2-connect-ruby/k2_entity/polling/polling_request.rb +48 -0
  39. data/lib/k2-connect-ruby/k2_entity/webhook/webhook_subscription_request.rb +66 -0
  40. data/lib/k2-connect-ruby/k2_errors.rb +15 -71
  41. data/lib/k2-connect-ruby/k2_services/base_service.rb +25 -0
  42. data/lib/k2-connect-ruby/k2_services/k2_client.rb +7 -6
  43. data/lib/k2-connect-ruby/k2_services/payloads/daraja_webhooks.rb +43 -0
  44. data/lib/k2-connect-ruby/k2_services/payloads/k2_transaction.rb +20 -18
  45. data/lib/k2-connect-ruby/k2_services/payloads/k2_webhooks.rb +36 -32
  46. data/lib/k2-connect-ruby/k2_services/payloads/transactions/incoming_payment.rb +31 -29
  47. data/lib/k2-connect-ruby/k2_services/payloads/transactions/outgoing_payment.rb +3 -1
  48. data/lib/k2-connect-ruby/k2_services/payloads/transactions/payment_link.rb +38 -0
  49. data/lib/k2-connect-ruby/k2_services/payloads/transactions/reversal.rb +35 -0
  50. data/lib/k2-connect-ruby/k2_services/payloads/transactions/send_money_payment.rb +25 -0
  51. data/lib/k2-connect-ruby/k2_services/payloads/transactions/transfer.rb +2 -0
  52. data/lib/k2-connect-ruby/k2_services/payloads/webhooks/b2b_transaction_received.rb +9 -3
  53. data/lib/k2-connect-ruby/k2_services/payloads/webhooks/b2b_transaction_reversed.rb +22 -0
  54. data/lib/k2-connect-ruby/k2_services/payloads/webhooks/buygoods_transaction_received.rb +6 -0
  55. data/lib/k2-connect-ruby/k2_services/payloads/webhooks/buygoods_transaction_reversed.rb +4 -0
  56. data/lib/k2-connect-ruby/k2_services/payloads/webhooks/card_transaction_received.rb +18 -0
  57. data/lib/k2-connect-ruby/k2_services/payloads/webhooks/card_transaction_reversed.rb +17 -0
  58. data/lib/k2-connect-ruby/k2_services/payloads/webhooks/card_transaction_voided.rb +17 -0
  59. data/lib/k2-connect-ruby/k2_services/payloads/webhooks/customer_created.rb +11 -7
  60. data/lib/k2-connect-ruby/k2_services/payloads/webhooks/transfer_webhook.rb +50 -0
  61. data/lib/k2-connect-ruby/k2_services/send_introspect_token_request_service.rb +56 -0
  62. data/lib/k2-connect-ruby/k2_services/send_k2_connect_get_request_service.rb +42 -0
  63. data/lib/k2-connect-ruby/k2_services/send_k2_connect_post_request_service.rb +44 -0
  64. data/lib/k2-connect-ruby/k2_services/send_request_token_request_service.rb +55 -0
  65. data/lib/k2-connect-ruby/k2_services/send_revoke_token_request_service.rb +56 -0
  66. data/lib/k2-connect-ruby/k2_services/send_token_info_request_service.rb +44 -0
  67. data/lib/k2-connect-ruby/k2_services.rb +29 -0
  68. data/lib/k2-connect-ruby/k2_utilities/config/k2_config.rb +18 -26
  69. data/lib/k2-connect-ruby/k2_utilities/config/k2_config.yml +9 -10
  70. data/lib/k2-connect-ruby/k2_utilities/k2_authenticator.rb +12 -5
  71. data/lib/k2-connect-ruby/k2_utilities/k2_connection.rb +0 -48
  72. data/lib/k2-connect-ruby/k2_utilities/k2_connection_helper.rb +21 -0
  73. data/lib/k2-connect-ruby/k2_utilities/k2_process_result.rb +16 -15
  74. data/lib/k2-connect-ruby/k2_utilities/k2_process_webhook.rb +34 -21
  75. data/lib/k2-connect-ruby/k2_utilities/k2_url_parse.rb +3 -1
  76. data/lib/k2-connect-ruby/k2_utilities/phone_number_validator.rb +15 -0
  77. data/lib/k2-connect-ruby/k2_utilities.rb +9 -20
  78. data/lib/k2-connect-ruby/version.rb +1 -1
  79. data/lib/k2-connect-ruby.rb +14 -13
  80. metadata +119 -36
  81. data/lib/k2-connect-ruby/k2_entity/k2_financial_entities/k2_pay.rb +0 -98
  82. data/lib/k2-connect-ruby/k2_entity/k2_financial_entities/k2_settlement.rb +0 -48
  83. data/lib/k2-connect-ruby/k2_entity/k2_financial_entities/k2_transfer.rb +0 -44
  84. data/lib/k2-connect-ruby/k2_entity/k2_notification.rb +0 -40
  85. data/lib/k2-connect-ruby/k2_services/payload_process.rb +0 -19
  86. data/lib/k2-connect-ruby/k2_services/payloads/webhooks/settlement_webhook.rb +0 -44
  87. data/lib/k2-connect-ruby/k2_utilities/k2_validation.rb +0 -128
data/README.md CHANGED
@@ -8,8 +8,10 @@ Primarily, the library provides functionality to do the following:
8
8
 
9
9
  - Receive Webhook notifications.
10
10
  - Receive payments from your users/customers.
11
+ - Initiate reversals for payments from your users/customers
11
12
  - Initiate payments to third parties.
12
- - Initiate transfers to your settlement accounts.
13
+ - Initiate transfers to your preferred accounts.
14
+ - Create payment links
13
15
 
14
16
  The library is optimized for **Rails Based Frameworks**.
15
17
  Please note, all requests MUST be made over HTTPS.
@@ -22,12 +24,13 @@ All calls made without authentication will also fail.
22
24
  - [Usage](#installation)
23
25
  - [Authorization](#authorization)
24
26
  - [Webhook Subscription](#webhook-subscription)
25
- - [SMS Notifications](#sms-notifications)
26
27
  - [STK Push](#stk-push)
27
- - [PAY](#pay)
28
- - [Settlemennt accounts](#settlement-accounts)
29
- - [Transfers](#transfers)
28
+ - [Add External recipients](#add-external-recipients)
29
+ - [Add Transfer accounts](#add-transfer-accounts)
30
+ - [Send money](#send-money)
30
31
  - [Polling](#polling)
32
+ - [Reversals](#reversals)
33
+ - [Payment links](#payment-links)
31
34
  - [Parsing the JSON Payload](#parsing-the-json-payload)
32
35
  - [Development](#development)
33
36
  - [Author](#author)
@@ -59,14 +62,17 @@ Add the require line to use the gem:
59
62
  To set the base_url:
60
63
 
61
64
  ```ruby
62
- K2ConnectRuby::K2Utilities::Config::K2Config.set_base_url("https://sandbox.kopokopo.com/")
65
+ K2ConnectRuby::K2Utilities::Config::K2Config.base_url = "https://sandbox.kopokopo.com/"
63
66
  ```
64
67
 
65
- To set the api version:
68
+ > [!NOTE]
69
+ > The API version in use is K2 Connect v2. To use K2 Connect v2, make use of versions 3.0.0 of the SDK.
66
70
 
67
- ```ruby
68
- K2ConnectRuby::K2Utilities::Config::K2Config.set_version(1)
69
- ```
71
+ > [!WARNING]
72
+ > The following APIs are deprecated on version 2 (v2).
73
+ > - Pay (Replaced with Send money)
74
+ > - Transfers (Replaced with Send money)
75
+ > - SMS Notifications
70
76
 
71
77
  ### Authorization
72
78
 
@@ -78,7 +84,7 @@ For more Information, visit our [API docs]().
78
84
  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.
79
85
 
80
86
  ```ruby
81
- k2_token = K2ConnectRuby::K2Entity::K2Token.new('your_client_id', 'your_client_secret').request_token
87
+ access_token = K2ConnectRuby::K2Entity::K2Token.new('your_client_id', 'your_client_secret').request_token
82
88
  ```
83
89
 
84
90
  ### Webhook Subscription
@@ -89,58 +95,49 @@ Next, we formally create the webhook subscription by calling on the webhook_subs
89
95
  Ensure the following arguments are passed:
90
96
  - event type `REQUIRED`
91
97
  - url `REQUIRED`
92
- - scope `REQUIRED`: is `till` if event_type is a buygoods_transaction_received, buygoods_transaction_reversed or b2b_transaction_received, and `company` if not
93
- - scope reference: is `REQUIRED` if scope is till
98
+ - scope `REQUIRED`: is `till` if event_type is a buygoods_transaction_received, buygoods_transaction_reversed, b2b_transaction_received, card_transaction_received, card_transaction_voided or card_transaction_reversed and `company` if not
99
+ - scope_reference: is `REQUIRED` if scope is till
100
+ - enable_daraja_payload: `OPTIONAL`. By default, it is set to `false`
101
+
102
+ Supported event types:
103
+ - buygoods_transaction_received
104
+ - buygoods_transaction_reversed
105
+ - b2b_transaction_received
106
+ - b2b_transaction_reversed
107
+ - card_transaction_received
108
+ - card_transaction_voided
109
+ - card_transaction_reversed
110
+ - customer_created
111
+ - settlement_transfer_completed
94
112
 
95
113
  Code example;
96
114
 
97
115
  ```ruby
98
116
  require 'k2-connect-ruby'
99
- k2_token = K2ConnectRuby::K2Entity::K2Token.new('your_client_id', 'your_client_secret').request_token
100
- k2subscriber = K2ConnectRuby::K2Entity::K2Subscribe.new(k2_token)
117
+ access_token = K2ConnectRuby::K2Entity::K2Token.new('your_client_id', 'your_client_secret').request_token
118
+ k2subscriber = K2ConnectRuby::K2Entity::K2Subscribe.new(access_token)
101
119
  your_request = {
102
120
  event_type: 'buygoods_transaction_received',
103
121
  url: callback_url,
104
122
  scope: 'till',
105
- scope_reference: '112233'
123
+ scope_reference: '112233',
124
+ enable_daraja_payload: true
106
125
  }
107
126
  k2subscriber.webhook_subscribe(your_request)
108
127
  ```
109
128
 
110
- ### SMS Notifications
111
-
112
- To create an SMS notification request by calling on the send_sms_transaction_notification method.
113
- Ensure the following arguments are passed:
114
- - webhook_event_reference `REQUIRED`
115
- - message `REQUIRED`
116
- - callback_url `REQUIRED`
117
-
118
- Code example;
119
-
120
- ```ruby
121
- require 'k2-connect-ruby'
122
- k2_token = K2ConnectRuby::K2Entity::K2Token.new('your_client_id', 'your_client_secret').request_token
123
- k2_notification = K2ConnectRuby::K2Entity::K2Notification.new(k2_token)
124
- request_payload = {
125
- webhook_event_reference: 'c271535c-687f-4a40-a589-8b66b894792e',
126
- message: 'message',
127
- callback_url: 'callback_url'
128
- }
129
- k2_notification.send_sms_transaction_notification(request_payload)
130
- ```
131
-
132
129
 
133
130
  ### STK-Push
134
131
 
135
- #### Receive Payments
132
+ #### Receive Payments
136
133
 
137
134
  To receive payments from M-PESA users via STK Push we first create a K2Stk Object, passing the access_token that was created prior.
138
135
 
139
- k2_stk = K2ConnectRuby::K2Entity::K2Stk.new(your_access_token)
136
+ k2_stk = K2ConnectRuby::K2Entity::K2Stk.new(access_token)
140
137
 
141
138
  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:
142
139
 
143
- k2_stk.receive_mpesa_payments(your_input)
140
+ k2_stk.send_stk_request(your_input)
144
141
 
145
142
  Ensure the following arguments are passed:
146
143
  - payment_channel `REQUIRED`
@@ -149,7 +146,7 @@ Ensure the following arguments are passed:
149
146
  - last_name
150
147
  - phone_number `REQUIRED`
151
148
  - email
152
- - currency: default is `KES`
149
+ - currency: `KES` expected
153
150
  - value `REQUIRED`
154
151
  - callback_url `REQUIRED`
155
152
 
@@ -170,35 +167,38 @@ As a result a JSON payload will be returned, accessible with the k2_response_bod
170
167
  Code example;
171
168
 
172
169
  ```ruby
173
- k2_stk = K2ConnectRuby::K2Entity::K2Stk.new(your_access_token)
170
+ k2_stk = K2ConnectRuby::K2Entity::K2Stk.new(access_token)
174
171
 
175
172
  your_request = {
176
- payment_channel: 'M-PESA',
177
- till_number: 'K112233',
178
- first_name: stk_params[:first_name],
179
- last_name: stk_params[:last_name],
180
- phone_number: stk_params[:phone],
181
- email: stk_params[:email],
182
- currency: stk_params[:currency],
183
- value: stk_params[:value],
184
- callback_url: callback_url
173
+ payment_channel: "M-PESA STK Push",
174
+ till_number: "K112233",
175
+ first_name: "First",
176
+ middle_name: "Middle",
177
+ last_name: "Last",
178
+ phone_number: "phone_number",
179
+ email: "test_email@email.com",
180
+ currency: "KES",
181
+ amount: "100",
182
+ metadata: {
183
+ customer_id: "123_456_789",
184
+ reference: "123_456",
185
+ notes: "Placeholder text",
186
+ },
187
+ callback_url: callback_url,
185
188
  }
186
- k2_stk.receive_mpesa_payments(your_request)
189
+ k2_stk.send_stk_request(your_request)
187
190
  k2_stk.query_resource(k2_stk.location_url)
188
191
  ```
189
192
 
190
- ### PAY
191
-
192
- First Create the K2Pay Object passing the access token
193
+ ### Add External Recipients
193
194
 
195
+ First Create the `ExternalRecipient` Object passing the access token
194
196
 
195
- k2_pay = K2ConnectRuby::K2Entity::K2Pay.new(access_token)
197
+ external_recipient = K2ConnectRuby::K2Entity::ExternalRecipient.new(access_token)
196
198
 
197
- #### Add PAY Recipients
199
+ Add a external recipient, with the following arguments:
198
200
 
199
- Add a PAY Recipient, with the following arguments:
200
-
201
- **Mobile** PAY Recipient
201
+ **Mobile** External Recipient
202
202
  - type: 'mobile_wallet' `REQUIRED`
203
203
  - first_name `REQUIRED`
204
204
  - last_name `REQUIRED`
@@ -206,182 +206,271 @@ Add a PAY Recipient, with the following arguments:
206
206
  - email `REQUIRED`
207
207
  - network `REQUIRED`
208
208
 
209
- **Bank** PAY Recipient
209
+ **Bank** External Recipient
210
210
  - type: 'bank_account' `REQUIRED`
211
211
  - account_name `REQUIRED`
212
212
  - account_number `REQUIRED`
213
213
  - bank_branch_ref `REQUIRED`
214
- - settlement_method: 'EFT' or 'RTS' `REQUIRED`
215
214
 
216
- **Paybill** PAY Recipient
215
+ **Paybill** External Recipient
217
216
  - type: 'paybill' `REQUIRED`
218
217
  - paybill_name `REQUIRED`
219
218
  - paybill_number `REQUIRED`
220
219
  - paybill_account_number `REQUIRED`
221
220
 
222
- **Till** PAY Recipient
221
+ **Till** External Recipient
223
222
  - type: 'till' `REQUIRED`
224
223
  - till_name `REQUIRED`
225
224
  - till_number `REQUIRED`
226
225
 
227
226
  ```ruby
228
- k2_pay.add_recipients(your_input)
227
+ external_recipient = K2ConnectRuby::K2Entity::ExternalRecipient.new(access_token)
228
+ your_input = {
229
+ type: "mobile_wallet",
230
+ first_name: "First",
231
+ last_name: "Last",
232
+ email: "test_email@email.com",
233
+ phone_number: "phone_number",
234
+ }
235
+ external_recipient.add_external_recipient(your_input)
229
236
  ```
230
-
231
- The type value can either be `mobile_wallet` or `bank_account`
232
237
 
233
- A Successful Response is returned with the URL of the recipient resource.
234
-
235
- #### Create Outgoing Payment
238
+ The type value can be `mobile_wallet`, `bank_account`, `till` or `paybill`
236
239
 
237
- Creating an Outgoing Payment to a third party.
238
-
239
- k2_pay.create_payment(your_input)
240
-
241
- The following arguments should be passed within a hash:
242
-
243
- - destination_reference `REQUIRED`
244
- - destination_type `REQUIRED`
245
- - currency default is `KES`
246
- - value `REQUIRED`
247
- - description `REQUIRED`
248
- - category
249
- - tags
250
- - callback_url `REQUIRED`
240
+ A Successful Response is returned with the URL of the recipient resource.
251
241
 
252
- A Successful Response is returned with the URL of the Payment resource in the HTTP Location Header.
242
+ #### Query add ExternalRecipient Request Status
253
243
 
254
- #### Query PAY Request Status
244
+ To Query the status of the Add Recipient:
255
245
 
256
- To Query the status of the Add Recipient or Outgoing Payment request:
246
+ external_recipient.query_resource(external_recipient.recipients_location_url)
257
247
 
258
- // add recipient
259
- k2_pay.query_resource(k2_pay.recipients_location_url)
260
- // create outgoing payment
261
- k2_pay.query_resource(k2_pay.payments_location_url)
248
+ To Query the most recent status of the Add Recipient:
262
249
 
263
- To Query the most recent status of either the Add Recipient or Outgoing Payment request:
250
+ external_recipient.query_status
264
251
 
265
- // add recipient
266
- k2_pay.query_status('recipients')
267
- // create outgoing payment
268
- k2_pay.query_status('payments')
252
+ A HTTP Response will be returned in a JSON Payload, accessible with the k2_response_body variable.
269
253
 
270
- As a result a JSON payload will be returned, accessible with the k2_response_body variable.
271
-
272
254
  Code example;
273
-
274
- ```ruby
275
- k2_pay = K2ConnectRuby::K2Entity::K2Pay.new(your_access_token)
276
- k2_pay.add_recipient(your_recipient_input)
277
- k2_pay.query_resource(k2_pay.recipients_location_url)
278
255
 
279
- your_request = {
280
- destination_type: "mobile_wallet",
281
- destination_reference: "example_reference",
282
- amount: {
283
- "currency": "KES",
284
- "value": "500"
285
- },
286
- description: "k2-connect",
287
- category: "general",
288
- tags: ["tag_1", "tag_2"],
289
- metadata: {
290
- "something": "",
291
- "something_else": "Something else"
292
- },
293
- _links: { "callback_url": "https://example.site/example" }
294
- }
295
-
296
- k2_pay.create_payment(your_request)
297
- k2_pay.query_resource(k2_pay.payments_location_url)
256
+ ```ruby
257
+ external_recipient = K2ConnectRuby::K2Entity::ExternalRecipient.new(access_token)
258
+ external_recipient.add_external_recipient(your_input)
259
+ external_recipient.query_resource(external_recipient.recipients_location_url)
298
260
  ```
299
261
 
300
- ### Settlement Accounts
262
+ ### Add Transfer Accounts
301
263
 
302
- Add pre-approved settlement accounts, to which one can transfer funds to. Can be either a bank or mobile wallet account,
303
- with the following details:
264
+ Add pre-approved transfer accounts, to which one can transfer funds to. Can be either a bank or mobile wallet account,
265
+ with the following details:
304
266
 
305
- **Mobile** Settlement Account
267
+ **Mobile** Transfer Account
306
268
  - type: 'merchant_wallet' `REQUIRED`
307
269
  - first_name `REQUIRED`
308
270
  - last_name `REQUIRED`
309
271
  - phone_number `REQUIRED`
310
272
  - network: 'Safaricom' `REQUIRED`
273
+ - nickname
274
+ - email
311
275
 
312
- **Bank** Settlement Account
276
+ **Bank** Transfer Account
313
277
  - type: 'merchant_bank_account' `REQUIRED`
314
278
  - account_name `REQUIRED`
315
279
  - account_number `REQUIRED`
316
280
  - bank_branch_ref `REQUIRED`
317
281
  - settlement_method: 'EFT' or 'RTS' `REQUIRED`
282
+ - nickname
318
283
 
319
284
  ```ruby
320
- k2_settlement = K2ConnectRuby::K2Entity::K2Settlement.new(your_access_token)
285
+ transfer_account = K2ConnectRuby::K2Entity::TransferAccount.new(access_token)
321
286
  # Add a mobile merchant wallet
322
- k2_settlement.add_settlement_account(merchant_wallet)
287
+ merchant_wallet_params = {
288
+ type: "merchant_wallet",
289
+ first_name: "first_name",
290
+ last_name: "last_name",
291
+ email: "email@email.com",
292
+ phone_number: "phone_number",
293
+ nickname: "nickname",
294
+ }
295
+ transfer_account.add_transfer_account(merchant_wallet_params)
323
296
  # Add a merchant bank account
324
- k2_settlement.add_settlement_account(merchant_bank_account)
297
+ merchant_bank_account_params = {
298
+ type: "merchant_bank_account",
299
+ account_name: Faker::Name.name_with_middle,
300
+ account_number: Faker::Number.number(digits: 10),
301
+ bank_branch_ref: "reference to bank branch", # View https://developers.kopokopo.com/ on how to retrieve the bank branch reference
302
+ settlement_method: "EFT",
303
+ nickname: Faker::Name.name_with_middle,
304
+ }
305
+ transfer_account.add_transfer_account(merchant_bank_account_params)
325
306
  ```
326
307
 
327
- ### Transfers
308
+ A Successful Response is returned with the URL of the resource.
328
309
 
329
- This will Enable one to transfer funds to your settlement accounts.
310
+ #### Query add transfer account Request Status
330
311
 
331
- First Create the K2Transfer Object
312
+ To Query the status of the Add Transfer account:
332
313
 
333
- k2_transfers = K2ConnectRuby::K2Entity::K2Transfer.new(access_token)
314
+ transfer_account.query_resource(transfer_account.transfer_account_location_url)
334
315
 
335
- #### Create Transfer Request
316
+ To Query the most recent status of the Add Transfer account:
336
317
 
337
- One can either have it `blind`, meaning that it has no specified destination with the default/specified settlement account being selected,
338
- or one can have a `targeted` transfer with a specified settlement account in mind. Either can be done through:
318
+ transfer_account.query_status
339
319
 
340
- ##### Blind Transfer
320
+ A HTTP Response will be returned in a JSON Payload, accessible with the k2_response_body variable.
341
321
 
342
- k2_transfers.transfer_funds(params)
322
+ Code example;
343
323
 
344
- With `nil` representing that there are no specified destinations.
324
+ ```ruby
325
+ transfer_account = K2ConnectRuby::K2Entity::TransferAccount.new(access_token)
326
+ transfer_account.add_transfer_account(your_input)
327
+ transfer_account.query_resource(transfer_account.transfer_account_location_url)
328
+ ```
345
329
 
346
- ##### Target Transfer
330
+ ### Send money
347
331
 
348
- k2_transfers.transfer_funds(params)
349
-
350
- The Following Details should be passed for either **Blind** or **Targeted** Transfer:
332
+ First Create the `SendMoney` Object passing the access token
351
333
 
352
- **Blind** Transfer to your default settlement account
353
- - currency default is `KES`
354
- - value `REQUIRED`
355
- - callback_url `REQUIRED`
334
+ send_money = K2ConnectRuby::K2Entity::SendMoney.new(access_token)
335
+
336
+ Creating an Outgoing Payment to a third party.
356
337
 
357
- **Targeted** Transfer
358
- - destination_reference `REQUIRED`
359
- - destination_type: `merchant_wallet` or `merchant_bank_account` `REQUIRED`
360
- - currency default is `KES`
361
- - value `REQUIRED`
338
+ send_money.create_payment(your_input)
339
+
340
+ The following arguments should be passed within a hash:
341
+
342
+ - destinations (array of hashes). `REQUIRED` unless doing send money sweep of available funds
343
+ - currency `KES` expected
344
+ - source_identifier
362
345
  - callback_url `REQUIRED`
363
346
 
364
- The Params are passed as the argument containing all the form data sent. A Successful Response is returned with the URL of the transfer request in the HTTP Location Header.
347
+ The hash structure within the destinations array:
365
348
 
366
- Sample code example:
349
+ Send to **External Mobile Recipient**
350
+ - type: 'mobile_wallet' `REQUIRED`
351
+ - phone_number `REQUIRED`
352
+ - amount `REQUIRED`
353
+ - description `REQUIRED`
354
+ - network `REQUIRED`
355
+ - first_name
356
+ - last_name
357
+ - nickname
358
+ - favourite
367
359
 
368
- ```ruby
369
- k2_transfer = K2ConnectRuby::K2Entity::K2Transfer.new(your_access_token)
370
- # Blind or Targeted Transfer
371
- k2_transfer.transfer_funds(your_input)
372
- ```
360
+ Send to **External Bank account Recipient**
361
+ - type: 'bank_account' `REQUIRED`
362
+ - account_name `REQUIRED`
363
+ - account_number `REQUIRED`
364
+ - amount `REQUIRED`
365
+ - description `REQUIRED`
366
+ - bank_branch_ref `REQUIRED`
367
+ - nickname
368
+ - favourite
369
+
370
+ Send to **External Paybill Recipient**
371
+ - type: 'paybill' `REQUIRED`
372
+ - paybill_number `REQUIRED`
373
+ - paybill_account_number `REQUIRED`
374
+ - paybill_name
375
+ - description `REQUIRED`
376
+ - nickname
377
+ - favourite
373
378
 
374
- #### Query Prior Transfer
379
+ Send to **External Till Recipient**
380
+ - type: 'till' `REQUIRED`
381
+ - till_number `REQUIRED`
382
+ - till_name
383
+ - description `REQUIRED`
384
+ - nickname
385
+ - favourite
375
386
 
376
- To Query the status of the prior initiated Transfer Request pass the location_url response as shown:
387
+ Send to **My Mobile Phone**
388
+ - type: 'merchant_wallet' `REQUIRED`
389
+ - reference `REQUIRED`
390
+ - amount `REQUIRED`
377
391
 
378
- k2_transfers.query_resource(k2_transfers.location_url)
392
+ Send to **My Bank account**
393
+ - type: 'merchant_bank_account' `REQUIRED`
394
+ - reference `REQUIRED`
395
+ - amount `REQUIRED`
379
396
 
380
- To Query the most recent initiated Transfer Request:
397
+ A Successful Response is returned with the URL of the Payment resource in the HTTP Location Header.
381
398
 
382
- k2_transfers.query_status
399
+ #### Query SendMoney Request Status
400
+
401
+ To Query the status of the Outgoing Payment request:
402
+
403
+ send_money.query_resource(send_money.payments_location_url)
404
+
405
+ To Query the most recent status of Outgoing Payment request:
406
+
407
+ send_money.query_status
383
408
 
384
409
  A HTTP Response will be returned in a JSON Payload, accessible with the k2_response_body variable.
410
+
411
+ Code example of send money to an external recipient;
412
+
413
+ ```ruby
414
+ # Send money to external recipient
415
+ params = {
416
+ destinations: [
417
+ {
418
+ type: "bank_account",
419
+ bank_branch_ref: "reference to bank branch", # View https://developers.kopokopo.com/ on how to retrieve the bank branch reference
420
+ account_name: Faker::Name.name,
421
+ account_number: "bank account number",
422
+ nickname: Faker::Name.name,
423
+ amount: "1000",
424
+ description: "send money via K2 Connect",
425
+ },
426
+ ],
427
+ currency: "KES",
428
+ source_identifier: nil,
429
+ metadata: {
430
+ order_no: "ORD192832",
431
+ },
432
+ callback_url: Faker::Internet.url,
433
+ }
434
+ access_token = K2ConnectRuby::K2Entity::K2Token.new("client_id", "client_secret").request_token
435
+ send_money = K2ConnectRuby::K2Entity::SendMoney.new(access_token)
436
+ send_money.create_payment(params)
437
+ ```
438
+
439
+ Code example of send money to a transfer account;
440
+
441
+ ```ruby
442
+ # Send money to a transfer account
443
+ params = {
444
+ destinations: [
445
+ {
446
+ type: "merchant_wallet",
447
+ reference: destination_reference, # Retrieved from logging into the merchant app https://app.kopokopo.com
448
+ amount: "1000",
449
+ },
450
+ ],
451
+ currency: "KES",
452
+ source_identifier: nil,
453
+ callback_url: callback_url,
454
+ }
455
+ access_token = K2ConnectRuby::K2Entity::K2Token.new("client_id", "client_secret").request_token
456
+ send_money = K2ConnectRuby::K2Entity::SendMoney.new(access_token)
457
+ send_money.create_payment(params)
458
+ ```
459
+
460
+ Code example of send money to my accounts (Sweep all available funds);
461
+
462
+ ```ruby
463
+ # Send money to my accounts
464
+ params = {
465
+ destinations: [],
466
+ currency: "KES",
467
+ source_identifier: nil,
468
+ callback_url: callback_url,
469
+ }
470
+ access_token = K2ConnectRuby::K2Entity::K2Token.new("client_id", "client_secret").request_token
471
+ send_money = K2ConnectRuby::K2Entity::SendMoney.new(access_token)
472
+ send_money.create_payment(params)
473
+ ```
385
474
 
386
475
  ### Polling
387
476
 
@@ -394,7 +483,7 @@ First Create the K2Polling Object
394
483
  The following details should be passed:
395
484
 
396
485
  - scope `REQUIRED`
397
- - scope_reference
486
+ - scope_reference is `REQUIRED` if scope is till
398
487
  - from_time `REQUIRED`
399
488
  - to_time `REQUIRED`
400
489
  - callback_url `REQUIRED`
@@ -402,32 +491,159 @@ The following details should be passed:
402
491
  Sample code example:
403
492
 
404
493
  ```ruby
405
- your_input =
406
- {
407
- scope: "company",
408
- scope_reference: "",
409
- from_time: "2021-04-12T08:50:22+03:00",
410
- to_time: "2021-04-19T08:50:22+03:00",
411
- callback_url: 'https://call_back_to_your_app.your_application.com'
412
- }
413
-
414
- k2_polling = K2ConnectRuby::K2Entity::K2Polling.new("your_access_token")
494
+ your_input = {
495
+ scope: "company",
496
+ scope_reference: "",
497
+ from_time: "2025-04-12T08:50:22+03:00",
498
+ to_time: "2025-04-19T08:50:22+03:00",
499
+ callback_url: 'http://placeholder_url_com'
500
+ }
501
+
502
+ k2_polling = K2ConnectRuby::K2Entity::K2Polling.new("access_token")
415
503
  k2_polling.poll(your_input)
416
504
  k2_polling.location_url # => "https://sandbox.kopokopo.com/api/v1/polling/247b1bd8-f5a0-4b71-a898-f62f67b8ae1c"
417
505
  ```
418
506
 
419
507
  #### Query Request
420
508
 
421
- To Query the status of the prior initiated Notification Request pass the location_url response as shown:
509
+ To Query the status of the prior initiated Polling Request pass the location_url response as shown:
422
510
 
423
- k2_notification.query_resource_url(k2_notification.location_url)
511
+ k2_polling.query_resource_url(k2_polling.location_url)
424
512
 
425
- To Query the most recent initiated Transfer Request:
513
+ To Query the most recent initiated Polling Request:
426
514
 
427
- k2_notification.query_resource
515
+ k2_polling.query_resource
428
516
 
429
517
  A HTTP Response will be returned in a JSON Payload, accessible with the k2_response_body variable.
430
518
 
519
+ ### Reversals
520
+
521
+ Initiate a reversal for a C2B or B2B transaction to your till and get the reversal request's status.
522
+
523
+ #### Initiate a reversal
524
+ Create an instance of `K2ConnectRuby::K2Entity::Reversal` object and call `initiate_reversal` method with the following reversal parameters:
525
+ - `transaction_reference`: Reference of the transaction to be reversed. `REQUIRED`
526
+ - `reason`: Reason for the reversal. `REQUIRED`
527
+ - `metadata`: A hash with a maximum of 5 key-value pairs.
528
+ - `callback_url`: URL that the result will be posted to. `REQUIRED`
529
+
530
+ ```ruby
531
+ reversal_params = {
532
+ transaction_reference: "Y7T2990R11",
533
+ reason: "Erroneous payment",
534
+ metadata: {
535
+ order_no: "ORD192832",
536
+ },
537
+ callback_url: "https://example.com/callback",
538
+ }
539
+
540
+ access_token = K2ConnectRuby::K2Entity::K2Token.new("client_id", "client_secret").request_token
541
+ k2_reversal = K2ConnectRuby::K2Entity::Reversal.new(access_token)
542
+ k2_reversal.initiate_reversal(reversal_params)
543
+ ```
544
+
545
+
546
+ #### Get status of reversal request
547
+ ```ruby
548
+ reversal_params = {
549
+ transaction_reference: "Y7T2990R11",
550
+ reason: "Erroneous payment",
551
+ metadata: {
552
+ order_no: "ORD192832",
553
+ },
554
+ callback_url: "https://example.com/callback",
555
+ }
556
+
557
+ access_token = K2ConnectRuby::K2Entity::K2Token.new("client_id", "client_secret").request_token
558
+ k2_reversal = K2ConnectRuby::K2Entity::Reversal.new(access_token)
559
+ location_url = k2_reversal.initiate_reversal(reversal_params)
560
+
561
+ # Get status of current reversal request
562
+ k2_reversal.query_status
563
+
564
+ # Get status of specific reversal request
565
+ k2_reversal.query_resource(location_url)
566
+ ```
567
+
568
+ ### Payment Links
569
+
570
+ Generate a payment link that you can share with a customer to collect a payment
571
+
572
+ #### Create a payment link
573
+ Create an instance of `K2ConnectRuby::K2Entity::PaymentLink` object and call `create_payment_link` method with the following payment link parameters:
574
+ - `till_number`: Till number for the **M-PESA** or **Online Payments Account** that will receive the payment. `REQUIRED`
575
+ - `currency`: 3-digit ISO format currency code. `REQUIRED`
576
+ - `amount`: The amount the customer will pay. `REQUIRED`
577
+ - `payment_reference`: The merchant internal reference for the payment.
578
+ - `note`: Note for the customer as they make the payment.
579
+ - `metadata`: A hash with a maximum of 5 key pairs.
580
+ - `callback_url`: URL that the payment link result will be posted to once a customer makes a payment. `REQUIRED`
581
+
582
+ ```ruby
583
+ payment_link_params = {
584
+ till_number: "4321",
585
+ currency: "KES",
586
+ amount: 1000,
587
+ payment_reference: "INV02932922",
588
+ note: "Payment for monthly internet subscription",
589
+ metadata: {
590
+ account_number: "1234567",
591
+ },
592
+ callback_url: "https://example.com/callback",
593
+ }
594
+
595
+ access_token = K2ConnectRuby::K2Entity::K2Token.new("client_id", "client_secret").request_token
596
+ k2_payment_links = K2ConnectRuby::K2Entity::PaymentLink.new(access_token)
597
+ k2_payment_links.create_payment_link(payment_link_params)
598
+ ```
599
+
600
+ ### Cancel payment link
601
+ ```ruby
602
+ payment_link_params = {
603
+ till_number: "4321",
604
+ currency: "KES",
605
+ amount: 1000,
606
+ payment_reference: "INV02932922",
607
+ note: "Payment for monthly internet subscription",
608
+ metadata: {
609
+ account_number: "1234567",
610
+ },
611
+ callback_url: "https://example.com/callback",
612
+ }
613
+
614
+ access_token = K2ConnectRuby::K2Entity::K2Token.new("client_id", "client_secret").request_token
615
+ k2_payment_links = K2ConnectRuby::K2Entity::PaymentLink.new(access_token)
616
+ location_url = k2_payment_links.create_payment_link(payment_link_params)
617
+
618
+ # Cancel payment link
619
+ k2_payment_links.cancel_payment_link(location_url)
620
+ ```
621
+
622
+ #### Get status of payment link
623
+ ```ruby
624
+ payment_link_params = {
625
+ till_number: "4321",
626
+ currency: "KES",
627
+ amount: 1000,
628
+ payment_reference: "INV02932922",
629
+ note: "Payment for monthly internet subscription",
630
+ metadata: {
631
+ account_number: "1234567",
632
+ },
633
+ callback_url: "https://example.com/callback",
634
+ }
635
+
636
+ access_token = K2ConnectRuby::K2Entity::K2Token.new("client_id", "client_secret").request_token
637
+ k2_payment_links = K2ConnectRuby::K2Entity::PaymentLink.new(access_token)
638
+ location_url = k2_payment_links.create_payment_link(payment_link_params)
639
+
640
+ # Get status of current payment link
641
+ k2_payment_links.query_status
642
+
643
+ # Get status of specific payment link
644
+ k2_payment_links.query_resource(location_url)
645
+ ```
646
+
431
647
  ### Parsing the JSON Payload
432
648
 
433
649
  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
@@ -472,6 +688,7 @@ k2_components = K2ConnectRuby::K2Utilities::K2ProcessResult.process(k2_parse.has
472
688
  - `reference`
473
689
  - `origination_time`
474
690
  - `sender_phone_number`
691
+ - `hashed_sender_phone`
475
692
  - `amount`
476
693
  - `currency`
477
694
  - `till_number`
@@ -499,8 +716,8 @@ k2_components = K2ConnectRuby::K2Utilities::K2ProcessResult.process(k2_parse.has
499
716
  - `sender_first_name`
500
717
  - `sender_last_name`
501
718
  - `links_self`
502
- - `links_resource`
503
-
719
+ - `links_resource`
720
+
504
721
  3. Settlement Transfer:
505
722
  - `id`
506
723
  - `resource_id`
@@ -539,7 +756,23 @@ k2_components = K2ConnectRuby::K2Utilities::K2ProcessResult.process(k2_parse.has
539
756
  - `links_self`
540
757
  - `links_resource`
541
758
 
542
- 5. B2b Transaction Transaction (External Till to Till):
759
+ 5. B2b Transaction Received (External Till to Till):
760
+ - `id`
761
+ - `resource_id`
762
+ - `topic`
763
+ - `created_at`
764
+ - `event_type`
765
+ - `reference`
766
+ - `origination_time`
767
+ - `amount`
768
+ - `currency`
769
+ - `till_number`
770
+ - `status`
771
+ - `links_self`
772
+ - `links_resource`
773
+ - `sending_till`
774
+
775
+ 6. B2B Transaction Reversed:
543
776
  - `id`
544
777
  - `resource_id`
545
778
  - `topic`
@@ -554,8 +787,57 @@ k2_components = K2ConnectRuby::K2Utilities::K2ProcessResult.process(k2_parse.has
554
787
  - `links_self`
555
788
  - `links_resource`
556
789
  - `sending_till`
790
+
791
+ 7. Card Transaction Received
792
+ - `id`
793
+ - `resource_id`
794
+ - `topic`
795
+ - `created_at`
796
+ - `event`
797
+ - `reference`
798
+ - `origination_time`
799
+ - `amount`
800
+ - `currency`
801
+ - `till_number`
802
+ - `customer_cc_number`
803
+ - `status`
804
+ - `links_self`
805
+ - `links_resource`
806
+ - `settled`
807
+
808
+ 8. Card Transaction Reversed:
809
+ - `id`
810
+ - `resource_id`
811
+ - `topic`
812
+ - `created_at`
813
+ - `event`
814
+ - `reference`
815
+ - `origination_time`
816
+ - `amount`
817
+ - `currency`
818
+ - `till_number`
819
+ - `customer_cc_number`
820
+ - `status`
821
+ - `links_self`
822
+ - `links_resource`
823
+
824
+ 9. Card Transaction Voided:
825
+ - `id`
826
+ - `resource_id`
827
+ - `topic`
828
+ - `created_at`
829
+ - `event_type`
830
+ - `reference`
831
+ - `origination_time`
832
+ - `amount`
833
+ - `currency`
834
+ - `till_number`
835
+ - `customer_cc_number`
836
+ - `status`
837
+ - `links_self`
838
+ - `links_resource`
557
839
 
558
- 6. Process STK Push Payment Request Result
840
+ 10. Process STK Push Payment Request Result
559
841
  - `id`
560
842
  - `type`
561
843
  - `initiation_time`
@@ -578,7 +860,7 @@ k2_components = K2ConnectRuby::K2Utilities::K2ProcessResult.process(k2_parse.has
578
860
  - `links_self`
579
861
  - `callback_url`
580
862
 
581
- 7. Process PAY Result
863
+ 11. Process Send money Result
582
864
  - `id`
583
865
  - `type`
584
866
  - `created_at`
@@ -590,17 +872,36 @@ k2_components = K2ConnectRuby::K2Utilities::K2ProcessResult.process(k2_parse.has
590
872
  - `links_self`
591
873
  - `callback_url`
592
874
 
593
- 8. Process Settlement Transfer Result
594
- - `id`
595
- - `type`
596
- - `created_at`
597
- - `status`
598
- - `transfer_batch`
599
- - `currency`
600
- - `value`
601
- - `links_self`
602
- - `callback_url`
603
-
875
+ 12. Reversal Result
876
+ - `id`
877
+ - `type`
878
+ - `transaction_reference`
879
+ - `status`
880
+ - `created_at`
881
+ - `reason`
882
+ - `reversal_bulk_payment`
883
+ - `errors`
884
+ - `metadata`
885
+ - `callback_url`
886
+ - `links_self`
887
+
888
+ 13. Payment Link Result
889
+ - `id`
890
+ - `type`
891
+ - `status`
892
+ - `created_at`
893
+ - `till_name`
894
+ - `till_number`
895
+ - `payment_reference`
896
+ - `currency`
897
+ - `amount`
898
+ - `note`
899
+ - `payment_link`
900
+ - `errors`
901
+ - `metadata`
902
+ - `callback_url`
903
+ - `links_self`
904
+
604
905
  If you want to convert the Object into a Hash or Array, the following methods can be used.
605
906
  - Hash:
606
907
 
@@ -620,7 +921,7 @@ Sample Web Application examples written in Rails and Sinatra frameworks that uti
620
921
 
621
922
  - [Sinatra example application](https://github.com/DavidKar1uk1/kt_tips)
622
923
 
623
- ##### Take Note; the Library is optimized for Rails frameworks version 5.
924
+ ##### Take Note; the Library is optimized for Rails frameworks version 8.
624
925
 
625
926
  ## Development
626
927