fawry 0.1.0 → 0.2.0

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: 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
  - - ">="