mpesarb 0.3.0 → 0.3.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e9d8b053eedae0cab3d4839a9a618f7b4f520b2deada034c07ab57358d69896b
4
- data.tar.gz: da6f1486a2a3e329dc0999b0cb901791b97c4fe87caf1f85e364fdd864cec069
3
+ metadata.gz: 21c94fd454abe3e4127f6c716ee39c4f574924018af8d6daedafc0c1f1bee5d1
4
+ data.tar.gz: e68131c8d3f8d1531abd3c7419c9dfacc70331a555ecd48b881cf9f290239acf
5
5
  SHA512:
6
- metadata.gz: d05e129b9e523fc31be44cb452283aa83993086b67b7cb540ce0832db3ba787a000c6baee3617f4529e34d6e7668ad31bbf97b78f5aa2e1fb9de73764ea326a5
7
- data.tar.gz: a07ec8dc4b8d383028952722b5785fbba6884d640a0b5333005c6b1905015cba00b6678b30eeebb7cdce5e429cb3b71832a157c7eba149216fae652c5c94577b
6
+ metadata.gz: bf9183f955f48501ab1fbb634145bf2f0116b98cad63613b56bdf832ceedef03eabfa8e5e0cccb55161226af04149208c16afe75eaa986c4971c24e07f053d43
7
+ data.tar.gz: 599eaf780d0efc0e141218ef6848e21454e12a379f66ffe64d1b1bffe8ab6aaccb87f177f418c08848321f097efc3513ab9ee3d71e7d1eefb41dfbebf3a081ff
data/.gitpod.yml ADDED
@@ -0,0 +1,8 @@
1
+ # This configuration file was automatically generated by Gitpod.
2
+ # Please adjust to your needs (see https://www.gitpod.io/docs/config-gitpod-file)
3
+ # and commit this file to your remote git repository to share the goodness with others.
4
+
5
+ tasks:
6
+ - init: bin/setup
7
+
8
+
data/CHANGELOG.md CHANGED
@@ -1,4 +1,6 @@
1
- ### Unreleased
1
+ ### 2022-01-04
2
+ - Support `response` `to_hash` method
3
+ ### 2020-01-20
2
4
  - Update gemspec
3
5
  - Read certificate full path
4
6
  - Return early if get access token fail
data/Gemfile CHANGED
@@ -1,4 +1,6 @@
1
- source "https://rubygems.org"
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
2
4
 
3
5
  # Specify your gem's dependencies in mpesa.gemspec
4
6
  gemspec
data/Gemfile.lock CHANGED
@@ -1,7 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- mpesa (0.2.0)
4
+ mpesarb (0.3.1)
5
+ activesupport (>= 5.0.0)
5
6
  faraday (>= 1.1)
6
7
  faraday_middleware (~> 1.1)
7
8
  openssl (>= 2.1)
@@ -9,12 +10,19 @@ PATH
9
10
  GEM
10
11
  remote: https://rubygems.org/
11
12
  specs:
13
+ activesupport (6.1.4.1)
14
+ concurrent-ruby (~> 1.0, >= 1.0.2)
15
+ i18n (>= 1.6, < 2)
16
+ minitest (>= 5.1)
17
+ tzinfo (~> 2.0)
18
+ zeitwerk (~> 2.3)
12
19
  addressable (2.8.0)
13
20
  public_suffix (>= 2.0.2, < 5.0)
14
21
  ansi (1.5.0)
15
22
  builder (3.2.4)
16
23
  byebug (11.1.3)
17
24
  coderay (1.1.3)
25
+ concurrent-ruby (1.1.9)
18
26
  coveralls (0.8.23)
19
27
  json (>= 1.8, < 3)
20
28
  simplecov (~> 0.16.1)
@@ -24,7 +32,7 @@ GEM
24
32
  crack (0.4.5)
25
33
  rexml
26
34
  docile (1.4.0)
27
- faraday (1.7.1)
35
+ faraday (1.8.0)
28
36
  faraday-em_http (~> 1.0)
29
37
  faraday-em_synchrony (~> 1.0)
30
38
  faraday-excon (~> 1.1)
@@ -43,9 +51,12 @@ GEM
43
51
  faraday-net_http_persistent (1.2.0)
44
52
  faraday-patron (1.0.0)
45
53
  faraday-rack (1.0.0)
46
- faraday_middleware (1.1.0)
54
+ faraday_middleware (1.2.0)
47
55
  faraday (~> 1.0)
48
56
  hashdiff (1.0.1)
57
+ i18n (1.8.10)
58
+ concurrent-ruby (~> 1.0)
59
+ ipaddr (1.2.3)
49
60
  json (2.5.1)
50
61
  method_source (1.0.0)
51
62
  minitest (5.14.4)
@@ -55,7 +66,8 @@ GEM
55
66
  minitest (>= 5.0)
56
67
  ruby-progressbar
57
68
  multipart-post (2.1.1)
58
- openssl (2.2.0)
69
+ openssl (2.2.1)
70
+ ipaddr
59
71
  pry (0.13.1)
60
72
  coderay (~> 1.1)
61
73
  method_source (~> 1.0)
@@ -78,14 +90,18 @@ GEM
78
90
  thor (1.1.0)
79
91
  tins (1.29.1)
80
92
  sync
93
+ tzinfo (2.0.4)
94
+ concurrent-ruby (~> 1.0)
81
95
  vcr (6.0.0)
82
96
  webmock (3.14.0)
83
97
  addressable (>= 2.8.0)
84
98
  crack (>= 0.3.2)
85
99
  hashdiff (>= 0.4.0, < 2.0.0)
100
+ zeitwerk (2.5.1)
86
101
 
87
102
  PLATFORMS
88
103
  x86_64-darwin-19
104
+ x86_64-darwin-20
89
105
 
90
106
  DEPENDENCIES
91
107
  bundler (>= 2.1.4)
@@ -93,11 +109,11 @@ DEPENDENCIES
93
109
  coveralls
94
110
  minitest
95
111
  minitest-reporters
96
- mpesa!
112
+ mpesarb!
97
113
  pry-byebug
98
114
  rake (>= 12.3)
99
115
  vcr
100
116
  webmock (~> 3.7)
101
117
 
102
118
  BUNDLED WITH
103
- 2.2.17
119
+ 2.2.27
data/README.md CHANGED
@@ -12,7 +12,12 @@ This Gem provides an interface that developers can use to convert JSON to `OpenS
12
12
 
13
13
  Install via `Gemfile`
14
14
  ```
15
- gem "mpesa", github: "gathuku/mpesa"
15
+ gem 'mpesarb', '~> 0.3.2'
16
+ ```
17
+
18
+ Or
19
+ ```
20
+ bundle add mpesarb
16
21
  ```
17
22
 
18
23
  ## Usage
@@ -20,12 +25,25 @@ gem "mpesa", github: "gathuku/mpesa"
20
25
  ### Initialization
21
26
 
22
27
  ```ruby
23
- client = Mpesa::Client.new(key: "SKKSS" , secret: "SJSKS", env: "sandbox", adapter: )
28
+ client = Mpesa::Client.new(key: 'ZtkRW6ATbVtFpNml5w5SfG26Adfyagn9', secret: 'dosFI1yQ8bvHEVFw', env: 'sandbox')
24
29
 
25
30
  response = client.auth
26
31
  response.access_token # XiKf3D6UrY0J8S2aeOQ7R7w0BuA5
27
32
  response.expires_in # 3599
28
33
  ```
34
+ __Parameters__
35
+
36
+ Required
37
+ - `key` - API consumer key - Required
38
+ - `secret` - API consumer secret - Required
39
+
40
+ Optional
41
+ - `env` - API environment. Default `production`
42
+ - `adapter` - Faraday HTTP adapter. Default `:net_http`
43
+ - `shortcode` - Mpesa shortcode
44
+ - `pass_key` - LPNMO pass Key( used by STK API)
45
+ - `raise_errors` - `Boolean` raise errors if response status code is not 200. Default: `true`
46
+
29
47
 
30
48
  ### Register Urls
31
49
 
@@ -33,7 +51,8 @@ Register C2B Urls( confirmation and validation url)
33
51
  ```ruby
34
52
  response = client.register(
35
53
  shortcode: "44445",
36
- confirmation_url: 'http://test.com', validation_url: 'http://test.com'
54
+ confirmation_url: 'http://example.com/confirm',
55
+ validation_url: 'http://example.com/validate'
37
56
  )
38
57
  response.OriginatorCoversationID # "807-15591582-1"
39
58
  response.ResponseCode # "0"
@@ -82,6 +101,44 @@ respose.ResponseDescription # "Accept the service request successfully."
82
101
 
83
102
  ```
84
103
 
104
+ ### Transaction Status
105
+ Check Transation Status
106
+
107
+ ```rb
108
+ response = client.status(
109
+ shortcode: '600426',
110
+ transaction_id: 'OEI2AK4Q16',
111
+ identifier_type: 1,
112
+ initiator_username: 'testapi',
113
+ initiator_password: 'Safaricom426!',
114
+ timeout_url: 'https://example.com/result',
115
+ result_url: 'https://example.com/result'
116
+ )
117
+
118
+ response.ConversationID
119
+ response.ResponseCode
120
+ ```
121
+
122
+ ### Reversal
123
+ Initiate a reversal
124
+
125
+ ```
126
+ response = client.reversal(
127
+ initiator_password: 'Safaricom426!',
128
+ initiator_username: 'testapi',
129
+ transaction_id: 'OEI2AK4Q16',
130
+ amount: '100',
131
+ receiver: '600610',
132
+ receiver_type: '4',
133
+ timeout_url: 'https://example.com/result',
134
+ result_url: 'https://example.com/result'
135
+ )
136
+
137
+ response.ConversationID
138
+ response.ResponseCode
139
+
140
+ ```
141
+
85
142
 
86
143
  ## Development
87
144
 
data/Rakefile CHANGED
@@ -1,10 +1,12 @@
1
- require "bundler/gem_tasks"
2
- require "rake/testtask"
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rake/testtask'
3
5
 
4
6
  Rake::TestTask.new(:test) do |t|
5
- t.libs << "test"
6
- t.libs << "lib"
7
- t.test_files = FileList["test/**/*_test.rb"]
7
+ t.libs << 'test'
8
+ t.libs << 'lib'
9
+ t.test_files = FileList['test/**/*_test.rb']
8
10
  end
9
11
 
10
- task :default => :test
12
+ task default: :test
data/bin/console CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'bundler/setup'
4
5
  require 'mpesa'
@@ -10,7 +11,13 @@ require 'mpesa'
10
11
  # require "pry"
11
12
  # Pry.start
12
13
 
13
- client = Mpesa::Client.new(key: 'ZtkRW6ATbVtFpNml5w5SfG26Adfyagn9', secret: 'dosFI1yQ8bvHEVFw', env: 'sandbox')
14
+ client = Mpesa::Client.new(
15
+ key: 'ZtkRW6ATbVtFpNml5w5SfG26Adfyagn9',
16
+ secret: 'dosFI1yQ8bvHEVFw',
17
+ env: 'sandbox',
18
+ shortcode: '174379',
19
+ pass_key: 'bfb279f9aa9bdbcf158e97dd71a467cd2e0c893059b10f78e6b72ada1ed2c919'
20
+ )
14
21
 
15
22
  require 'irb'
16
23
  IRB.start(__FILE__)
data/lib/mpesa/client.rb CHANGED
@@ -1,17 +1,20 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'faraday'
2
4
  require 'faraday_middleware'
3
5
 
4
6
  module Mpesa
5
7
  class Client
6
- attr_reader :key, :secret, :env, :adapter, :shortcode, :pass_key
8
+ attr_reader :key, :secret, :env, :adapter, :shortcode, :pass_key, :raise_errors
7
9
 
8
- def initialize(key:, secret:, shortcode: nil, pass_key: nil, env: 'production', adapter: Faraday.default_adapter)
10
+ def initialize(key:, secret:, shortcode: nil, pass_key: nil, env: 'production', adapter: Faraday.default_adapter, raise_errors: true)
9
11
  @key = key
10
12
  @secret = secret
11
13
  @env = env
12
14
  @adapter = adapter
13
15
  @pass_key = pass_key
14
16
  @shortcode = shortcode
17
+ @raise_errors = raise_errors
15
18
  end
16
19
 
17
20
  def auth
@@ -30,6 +33,18 @@ module Mpesa
30
33
  Payout.new(self, args).call
31
34
  end
32
35
 
36
+ def status(**args)
37
+ Status.new(self, args).call
38
+ end
39
+
40
+ def balance(**args)
41
+ Balance.new(self, args).call
42
+ end
43
+
44
+ def reversal(**args)
45
+ Reversal.new(self, args).call
46
+ end
47
+
33
48
  def connection(basic_auth: false)
34
49
  @connection ||= Faraday.new do |conn|
35
50
  conn.url_prefix = "https://#{subdomain}.safaricom.co.ke"
data/lib/mpesa/error.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Mpesa
2
4
  class Error < StandardError; end
3
5
  end
data/lib/mpesa/object.rb CHANGED
@@ -1,7 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'ostruct'
2
4
 
3
5
  module Mpesa
4
6
  class Object
7
+ attr_reader :attributes
8
+
5
9
  def initialize(attributes)
6
10
  @attributes = OpenStruct.new(attributes)
7
11
  end
@@ -14,5 +18,9 @@ module Mpesa
14
18
  def respond_to_missing?(_method, _include_private = false)
15
19
  true
16
20
  end
21
+
22
+ def to_hash
23
+ attributes.to_h
24
+ end
17
25
  end
18
26
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Mpesa
2
4
  class Intance < Object
3
5
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Mpesa
2
4
  class Resource
3
5
  attr_reader :client, :args
@@ -16,6 +18,8 @@ module Mpesa
16
18
  end
17
19
 
18
20
  def handle_response(response)
21
+ return response unless client.raise_errors
22
+
19
23
  case response.status
20
24
  when 400
21
25
  raise Error, "Your request was malformed. #{response.body['errorMessage']}"
@@ -30,5 +34,12 @@ module Mpesa
30
34
  end
31
35
  response
32
36
  end
37
+
38
+ def format_phone(phone)
39
+ phone = phone.to_s
40
+ return phone if phone.match?(/\A254/)
41
+
42
+ phone.sub(/\A[+0]?(254)?(\d+)/, '254\2')
43
+ end
33
44
  end
34
45
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Mpesa
2
4
  class Status < Resource
3
5
  PATH = 'mpesa/transactionstatus/v1/query'
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Mpesa
2
4
  class Payout < Resource
3
- PATH = 'mpesa/b2c/v1/paymentrequest'.freeze
5
+ PATH = 'mpesa/b2c/v1/paymentrequest'
4
6
 
5
7
  def call
6
8
  Object.new post_request(url: PATH, body: body).body
@@ -13,7 +15,7 @@ module Mpesa
13
15
  'CommandID': args[:command_id],
14
16
  'Amount': args[:amount],
15
17
  'PartyA': client.shortcode || args[:shortcode],
16
- 'PartyB': args[:phone],
18
+ 'PartyB': format_phone(args[:phone]),
17
19
  'Remarks': args[:remarks],
18
20
  'QueueTimeOutURL': args[:timeout_url],
19
21
  'ResultURL': args[:result_url],
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Mpesa
2
4
  class Register < Resource
3
- PATH = 'mpesa/c2b/v1/registerurl'.freeze
5
+ PATH = 'mpesa/c2b/v1/registerurl'
4
6
 
5
7
  def call
6
8
  Object.new post_request(url: PATH, body: body).body
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mpesa
4
+ class Reversal < Resource
5
+ PATH = 'mpesa/reversal/v1/request'
6
+
7
+ def call
8
+ Object.new post_request(url: PATH, body: body).body
9
+ end
10
+
11
+ def body
12
+ {
13
+ "Initiator": args[:initiator_username],
14
+ "SecurityCredential": credentials,
15
+ "CommandID": 'TransactionReversal',
16
+ "TransactionID": args[:transaction_id],
17
+ "Amount": args[:amount],
18
+ "ReceiverParty": args[:receiver],
19
+ "RecieverIdentifierType": args[:receiver_type],
20
+ "Remarks": args[:remarks] || 'check status',
21
+ "QueueTimeOutURL": args[:timeout_url],
22
+ "ResultURL": args[:result_url],
23
+ "Occasion": args[:occasion] || 'check status'
24
+ }
25
+ end
26
+
27
+ def credentials
28
+ SecurityCred.new(args[:initiator_password], client.env).password_credential
29
+ end
30
+ end
31
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Mpesa
2
4
  class Status < Resource
3
5
  PATH = 'mpesa/transactionstatus/v1/query'
@@ -7,8 +9,21 @@ module Mpesa
7
9
 
8
10
  def body
9
11
  {
10
-
12
+ "CommandID": 'TransactionStatusQuery',
13
+ "PartyA": args[:shortcode] || client.shortcode,
14
+ "IdentifierType": args[:identifier_type],
15
+ "Remarks": args[:remarks] || 'check status',
16
+ "Initiator": args[:initiator_username],
17
+ "SecurityCredential": credentials,
18
+ "QueueTimeOutURL": args[:timeout_url],
19
+ "ResultURL": args[:result_url],
20
+ "TransactionID": args[:transaction_id],
21
+ "Occasion": args[:occasion] || 'check status'
11
22
  }
12
23
  end
24
+
25
+ def credentials
26
+ SecurityCred.new(args[:initiator_password], client.env).password_credential
27
+ end
13
28
  end
14
29
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'base64'
2
4
 
3
5
  module Mpesa
@@ -10,14 +12,14 @@ module Mpesa
10
12
 
11
13
  def body
12
14
  {
13
- 'BusinessShortCode': args[:shortcode] || client.shortcode,
15
+ 'BusinessShortCode': shortcode,
14
16
  'Password': password,
15
- 'Timestamp': timestamp.to_s,
17
+ 'Timestamp': timestamp,
16
18
  'TransactionType': 'CustomerPayBillOnline',
17
19
  'Amount': args[:amount],
18
- 'PartyA': args[:phone],
19
- 'PartyB': args[:shortcode] || client.shortcode,
20
- 'PhoneNumber': args[:phone],
20
+ 'PartyA': format_phone(args[:phone]),
21
+ 'PartyB': shortcode,
22
+ 'PhoneNumber': format_phone(args[:phone]),
21
23
  'CallBackURL': args[:callback_url],
22
24
  'AccountReference': args[:reference],
23
25
  'TransactionDesc': args[:trans_desc]
@@ -25,11 +27,15 @@ module Mpesa
25
27
  end
26
28
 
27
29
  def password
28
- Base64.strict_encode64("#{args[:shortcode]}#{client.pass_key || args[:pass_key]}#{timestamp}")
30
+ Base64.strict_encode64("#{shortcode}#{args[:pass_key] || client.pass_key}#{timestamp}")
29
31
  end
30
32
 
31
33
  def timestamp
32
- Time.now.strftime('%Y%m%d%H%M%S').to_i
34
+ Time.now.strftime('%Y%m%d%H%M%S')
35
+ end
36
+
37
+ def shortcode
38
+ args[:shortcode] || client.shortcode
33
39
  end
34
40
  end
35
41
  end
@@ -1,7 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/cache'
4
+ require 'active_support/cache/memory_store'
5
+ require 'active_support/notifications'
6
+
1
7
  module Mpesa
2
8
  class Token < Resource
3
9
  def token
10
+ if cache.exist?('token')
11
+ expires_at = cache.send(:read_entry, 'token')&.expires_at
12
+ Object.new({
13
+ "access_token": cache.fetch('token'),
14
+ "expires_in": expires_at - Time.now.to_f
15
+ })
16
+ else
17
+ cache_token
18
+ end
19
+ end
20
+
21
+ def cache_token
22
+ res = call
23
+ cache.write('token', res.access_token, expires_in: res.expires_in)
24
+ res
25
+ end
26
+
27
+ def call
4
28
  Object.new get_request(url: 'oauth/v1/generate?grant_type=client_credentials', basic_auth: true).body
5
29
  end
30
+
31
+ def cache
32
+ @cache ||= ActiveSupport::Cache::MemoryStore.new
33
+ end
6
34
  end
7
35
  end
data/lib/mpesa/version.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Mpesa
2
- VERSION = '0.3.0'
4
+ VERSION = '0.3.3'
3
5
  end
data/lib/mpesa.rb CHANGED
@@ -16,6 +16,7 @@ module Mpesa
16
16
  autoload :Payout, 'mpesa/resources/payout'
17
17
  autoload :Status, 'mpesa/resources/status'
18
18
  autoload :Balance, 'mpesa/resources/balance'
19
+ autoload :Reversal, 'mpesa/resources/reversal'
19
20
 
20
21
  autoload :Instance, 'mpesa/objects/instace'
21
22
  end
data/mpesa.gemspec CHANGED
@@ -30,6 +30,7 @@ Gem::Specification.new do |spec|
30
30
  spec.add_development_dependency 'bundler', '>= 2.1.4'
31
31
  spec.add_development_dependency 'rake', '>= 12.3'
32
32
  # dependancies
33
+ spec.add_runtime_dependency 'activesupport', '>= 5.0.0'
33
34
  spec.add_runtime_dependency 'faraday', '>= 1.1'
34
35
  spec.add_runtime_dependency 'faraday_middleware', '~> 1.1'
35
36
  spec.add_runtime_dependency 'openssl', '>= 2.1'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mpesarb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Moses Gathuku
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-09-05 00:00:00.000000000 Z
11
+ date: 2022-05-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '12.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: activesupport
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 5.0.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 5.0.0
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: faraday
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -187,6 +201,7 @@ extra_rdoc_files: []
187
201
  files:
188
202
  - ".github/workflows/mpesa.yml"
189
203
  - ".gitignore"
204
+ - ".gitpod.yml"
190
205
  - ".travis.yml"
191
206
  - CHANGELOG.md
192
207
  - CODE_OF_CONDUCT.md
@@ -210,6 +225,7 @@ files:
210
225
  - lib/mpesa/resources/balance.rb
211
226
  - lib/mpesa/resources/payout.rb
212
227
  - lib/mpesa/resources/register.rb
228
+ - lib/mpesa/resources/reversal.rb
213
229
  - lib/mpesa/resources/status.rb
214
230
  - lib/mpesa/resources/stk.rb
215
231
  - lib/mpesa/resources/token.rb
@@ -238,7 +254,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
238
254
  - !ruby/object:Gem::Version
239
255
  version: '0'
240
256
  requirements: []
241
- rubygems_version: 3.2.15
257
+ rubygems_version: 3.3.7
242
258
  signing_key:
243
259
  specification_version: 4
244
260
  summary: a simple gem to integrate ruby with mpesa Apis