fawry 0.1.0 → 0.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 35a9a9bd2b1674d4f6df24e1b7a8fb187585906fed608c41991613f25f459214
4
- data.tar.gz: f1c205a1f9d92c758df8fe13f0a4bcd0bc70ea22106ab380984db00bc1303f6a
3
+ metadata.gz: 801fa2ec9cada4bf14b44b1733ff0010eae8c26ccc72ed23c500ae0b55ff6e30
4
+ data.tar.gz: c48087c1e6f133664be53c2e2d28d6a6b228379367eb4817a88e9d2ef9b5a669
5
5
  SHA512:
6
- metadata.gz: 7d3f2b4b9f111b8f967cbe2a67da12ed9c4683fd99a70e784d14963642b609594f4a2592782e5cfa0d92b8c16cbbe024d70fa99c150a74a0600656bab61057ed
7
- data.tar.gz: f65d775062f6a683b855b7d3deb10d8fa99b4f05a4f365bcb6b86312f2375d506f6e7e50f87f91ce517c5878e6b707a1dafc6b873ff0a729f6a101193709e4d1
6
+ metadata.gz: b721a5d9d20bf0a7c4faccc2d6db668b9c3aae73fbffec5c3a917b9463ac6753b3e28189674d749239f6065f659e938b44c9bd3cb8588d57af83d8cfd114808a
7
+ data.tar.gz: 97a8f8acf8eb6c41531a8b1ef8d72a26f650d95b0cb9ad5a41deb306f152b0d8d70ece22f4c6284e218de04311d2ba187d434fe3ba07844948428cded4a7feda
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- fawry (0.1.0)
4
+ fawry (0.2.0)
5
5
  dry-validation (~> 1.3, >= 1.3.1)
6
6
  faraday (~> 0.17.0)
7
7
 
data/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # Fawry
2
2
  A plug-and-play library that makes interfacing with Fawry's payment gateway API a breeze:
3
- - [Charge customers](https://github.com/amrrbakry/fawry#charge-customers)
4
- - [Refund customers](https://github.com/amrrbakry/fawry#refund-customers)
5
- - Get payment status _(Not yet implemented)_
3
+ - [Charge customers](https://github.com/fawry-api/fawry#charge-customers)
4
+ - [Refund customers](https://github.com/fawry-api/fawry#refund-customers)
5
+ - [Get payment status](https://github.com/fawry-api/fawry#get-payment-status)
6
6
  - Parse Fawry's service callback V2 _(Not yet implemented)_
7
7
 
8
8
  _Fawry's production and sandbox environments are supported._
@@ -61,6 +61,23 @@ res = Fawry.refund(params, sandbox: true)
61
61
 
62
62
  res.success? # => true
63
63
  ```
64
+
65
+ ### Get Payment Status
66
+ ```ruby
67
+ params = { "merchant_code": 'merchant_code',
68
+ "merchant_ref_number": 'ssshxb98phmyvm434es62kage3nsm2cj',
69
+ "fawry_secure_key": 'fawry_secure_key' }
70
+
71
+ res = Fawry.payment_status(params, sandbox: true)
72
+ # => #<Fawry::FawryResponse:0x0000559974056898 @type="PaymentStatusResponse", @reference_number="931922417",
73
+ # @merchant_ref_number="ssshxb98phmyvm434es62kage3nsm2cj",
74
+ # @expiration_time=1573297736167, @status_code=200,
75
+ # @status_description="Operation done successfully", @payment_amount=20,
76
+ # @payment_method="PAYATFAWRY", @payment_status="UNPAID">
77
+
78
+ res.success? # => true
79
+ res.payment_status # => UNPAID
80
+ ```
64
81
  ## Development
65
82
 
66
83
  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.
@@ -14,6 +14,7 @@ Gem::Specification.new do |spec|
14
14
  service callback)."
15
15
  spec.homepage = 'https://github.com/amrrbakry/fawry'
16
16
  spec.license = 'MIT'
17
+ spec.required_ruby_version = '~> 2.6'
17
18
 
18
19
  spec.metadata['homepage_uri'] = 'https://github.com/amrrbakry/fawry'
19
20
  spec.metadata['source_code_uri'] = 'https://github.com/amrrbakry/fawry'
@@ -7,8 +7,10 @@ require 'fawry/fawry_request'
7
7
  require 'fawry/fawry_response'
8
8
  require 'fawry/requests/charge_request'
9
9
  require 'fawry/requests/refund_request'
10
+ require 'fawry/requests/payment_status_request'
10
11
  require 'fawry/contracts/charge_request_contract'
11
12
  require 'fawry/contracts/refund_request_contract'
13
+ require 'fawry/contracts/payment_status_request_contract'
12
14
 
13
15
  module Fawry
14
16
  class << self
@@ -51,7 +53,7 @@ module Fawry
51
53
  # has Fawry API response keys as instance methods
52
54
  # plus some convenience methods e.g. success?
53
55
  def charge(params, opts = {})
54
- FawryRequest.new('charge', params, opts).fire
56
+ FawryRequest.new('charge', params, opts).fire_charge_request
55
57
  end
56
58
 
57
59
  # Sends a refund request to Fawry API
@@ -79,7 +81,33 @@ module Fawry
79
81
  # has Fawry API response keys as instance methods
80
82
  # plus some convenience methods e.g. success?
81
83
  def refund(params, opts = {})
82
- FawryRequest.new('refund', params, opts).fire
84
+ FawryRequest.new('refund', params, opts).fire_refund_request
85
+ end
86
+
87
+ # Sends a payment status request to Fawry API
88
+ # performs param validation and builds
89
+ # the request signature
90
+ #
91
+ # @param params [Hash] list of params to send to fawry
92
+ # required(:merchant_code).value(:string)
93
+ # required(:merchant_ref_number).value(:string)
94
+ # required(:fawry_secure_key).value(:string)
95
+ #
96
+ # @param opts [Hash] list of options to
97
+ # configure the request
98
+ # @option opts :sandbox [Boolean] whether to
99
+ # send the request to fawry sandbox env or not
100
+ # false by default
101
+ #
102
+ # @raise [Fawry::InvalidFawryRequest] raised when one
103
+ # or more of the params are invalid. the message
104
+ # specifices which params and why are they invalid
105
+ #
106
+ # @return [Fawry::FawryResponse] an object that
107
+ # has Fawry API response keys as instance methods
108
+ # plus some convenience methods e.g. success?
109
+ def payment_status(params, opts = {})
110
+ FawryRequest.new('payment_status', params, opts).fire_payment_status_request
83
111
  end
84
112
  end
85
113
  end
@@ -19,6 +19,17 @@ module Fawry
19
19
  end
20
20
  end
21
21
 
22
+ def get(path, params, body, options)
23
+ conn = options[:sandbox] ? sandbox_connection : connection
24
+
25
+ conn.get(path) do |request|
26
+ request.params = params
27
+ request.body = body.to_json
28
+ # Fawry doesn't understand encoded params
29
+ request.options = request.options.merge(params_encoder: ParamsSpecialEncoder)
30
+ end
31
+ end
32
+
22
33
  private
23
34
 
24
35
  def connection
@@ -30,6 +41,21 @@ module Fawry
30
41
  @sandbox_connection ||= Faraday.new(url: FAWRY_SANDBOX_BASE_URL, headers: { 'Content-Type': 'application/json',
31
42
  'Accept': 'application/json' })
32
43
  end
44
+
45
+ # Fawry does not understand encoded params
46
+ # so we use this encoder to convert the params
47
+ # hash to a string of query params without encoding
48
+ # { a: 1, b: 2 } => a=1&b=2
49
+ class ParamsSpecialEncoder
50
+ def self.encode(hash)
51
+ hash.each_with_object([]) { |(k, v), arr| arr << "#{k}=#{v}" }.join('&')
52
+ end
53
+
54
+ def self.decode(string)
55
+ arr = string.split('&')
56
+ arr.map { |str| str.split('=') }.to_h
57
+ end
58
+ end
33
59
  end
34
60
  end
35
61
  end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'dry-validation'
4
+
5
+ module Fawry
6
+ module Contracts
7
+ class PaymentStatusRequestContract < Dry::Validation::Contract
8
+ params do
9
+ required(:merchant_code).value(:string)
10
+ required(:merchant_ref_number).value(:string)
11
+ required(:fawry_secure_key).value(:string)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -16,6 +16,7 @@ module Fawry
16
16
 
17
17
  private
18
18
 
19
+ # rubocop:disable Metrics/MethodLength
19
20
  def build_request
20
21
  case action
21
22
  when 'charge'
@@ -26,7 +27,12 @@ module Fawry
26
27
  self.class.include Requests::RefundRequest
27
28
  validate_refund_params!
28
29
  @request = build_refund_request
30
+ when 'payment_status'
31
+ self.class.include Requests::PaymentStatusRequest
32
+ validate_payment_status_params!
33
+ @request = build_payment_status_request
29
34
  end
35
+ # rubocop:enable Metrics/MethodLength
30
36
  end
31
37
  end
32
38
  end
@@ -7,7 +7,7 @@ module Fawry
7
7
  module ChargeRequest
8
8
  DEFAULTS = { payment_method: 'PAYATFAWRY', currency_code: 'EGP' }.freeze
9
9
 
10
- def fire
10
+ def fire_charge_request
11
11
  fawry_api_response = Connection.post(request[:path], request[:params], request[:body], request[:options])
12
12
  response_body = JSON.parse(fawry_api_response.body)
13
13
 
@@ -29,6 +29,8 @@ module Fawry
29
29
  @request_params ||= DEFAULTS.merge(params)
30
30
  end
31
31
 
32
+ # rubocop:disable Metrics/AbcSize
33
+ # rubocop:disable Metrics/MethodLength
32
34
  def charge_request_transformed_params
33
35
  {
34
36
  merchantCode: request_params[:merchant_code],
@@ -46,6 +48,8 @@ module Fawry
46
48
  signature: charge_request_signature
47
49
  }.compact
48
50
  end
51
+ # rubocop:enable Metrics/MethodLength
52
+ # rubocop:enable Metrics/AbcSize
49
53
 
50
54
  def validate_charge_params!
51
55
  contract = Contracts::ChargeRequestContract.new.call(request_params)
@@ -56,12 +60,14 @@ module Fawry
56
60
  request_params[:charge_items].each { |hash| hash[:itemId] = hash.delete(:item_id) }
57
61
  end
58
62
 
63
+ # rubocop:disable Metrics/AbcSize
59
64
  def charge_request_signature
60
65
  Digest::SHA256.hexdigest("#{request_params[:merchant_code]}#{request_params[:merchant_ref_num]}"\
61
66
  "#{request_params[:customer_profile_id]}#{request_params[:payment_method]}"\
62
67
  "#{format('%<amount>.2f', amount: request_params[:amount])}"\
63
68
  "#{request_params[:card_token]}#{request_params[:fawry_secure_key]}")
64
69
  end
70
+ # rubocop:enable Metrics/AbcSize
65
71
  end
66
72
  end
67
73
  end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'digest'
4
+
5
+ module Fawry
6
+ module Requests
7
+ module PaymentStatusRequest
8
+ def fire_payment_status_request
9
+ fawry_api_response = Connection.get(request[:path], request[:params], request[:body], request[:options])
10
+ response_body = JSON.parse(fawry_api_response.body)
11
+
12
+ FawryResponse.new(response_body)
13
+ end
14
+
15
+ private
16
+
17
+ def build_payment_status_request
18
+ {
19
+ path: 'status',
20
+ params: payment_status_request_transformed_params,
21
+ body: {},
22
+ options: options
23
+ }
24
+ end
25
+
26
+ def request_params
27
+ @request_params = params
28
+ end
29
+
30
+ def payment_status_request_transformed_params
31
+ {
32
+ merchantCode: request_params[:merchant_code],
33
+ merchantRefNumber: request_params[:merchant_ref_number],
34
+ signature: payment_status_request_signature
35
+ }.compact
36
+ end
37
+
38
+ def validate_payment_status_params!
39
+ contract = Contracts::PaymentStatusRequestContract.new.call(request_params)
40
+ raise InvalidFawryRequest, contract.errors.to_h if contract.failure?
41
+ end
42
+
43
+ def payment_status_request_signature
44
+ Digest::SHA256.hexdigest("#{request_params[:merchant_code]}#{request_params[:merchant_ref_number]}"\
45
+ "#{request_params[:fawry_secure_key]}")
46
+ end
47
+ end
48
+ end
49
+ end
@@ -5,7 +5,7 @@ require 'digest'
5
5
  module Fawry
6
6
  module Requests
7
7
  module RefundRequest
8
- def fire
8
+ def fire_refund_request
9
9
  fawry_api_response = Connection.post(request[:path], request[:params], request[:body], request[:options])
10
10
  response_body = JSON.parse(fawry_api_response.body)
11
11
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Fawry
4
- VERSION = '0.1.0'
4
+ VERSION = '0.2.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fawry
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Amr Bakry
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-11-05 00:00:00.000000000 Z
11
+ date: 2019-11-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dry-validation
@@ -149,11 +149,13 @@ files:
149
149
  - lib/fawry.rb
150
150
  - lib/fawry/connection.rb
151
151
  - lib/fawry/contracts/charge_request_contract.rb
152
+ - lib/fawry/contracts/payment_status_request_contract.rb
152
153
  - lib/fawry/contracts/refund_request_contract.rb
153
154
  - lib/fawry/errors.rb
154
155
  - lib/fawry/fawry_request.rb
155
156
  - lib/fawry/fawry_response.rb
156
157
  - lib/fawry/requests/charge_request.rb
158
+ - lib/fawry/requests/payment_status_request.rb
157
159
  - lib/fawry/requests/refund_request.rb
158
160
  - lib/fawry/version.rb
159
161
  homepage: https://github.com/amrrbakry/fawry
@@ -168,9 +170,9 @@ require_paths:
168
170
  - lib
169
171
  required_ruby_version: !ruby/object:Gem::Requirement
170
172
  requirements:
171
- - - ">="
173
+ - - "~>"
172
174
  - !ruby/object:Gem::Version
173
- version: '0'
175
+ version: '2.6'
174
176
  required_rubygems_version: !ruby/object:Gem::Requirement
175
177
  requirements:
176
178
  - - ">="