paymob_accept 0.2.1 → 0.3.1

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: a6ebddca8de134c54bbf5d5f8dceecde5ae4f65cc735f403e40c04afa13e3f5e
4
- data.tar.gz: f635a17547b178a9ed8428d1fccf8a8157440e1656b6808375d5984b4e26a8e4
3
+ metadata.gz: 3f07b80f4fe23b6ca6da25649d650917ebf48802ce93903ca44dde300acf0f89
4
+ data.tar.gz: 4238ee5fa6e5267b27deac4b3f45701759515420ae4cfc255621691ef8f9b616
5
5
  SHA512:
6
- metadata.gz: 3925164b5d6519cf7216d719222c79c3882a70e88d56b1227c59a9c6bec93e4c9e499f22a7351620eb66c320550104615dddd2bc99b9da03fc82335c41d0c3b1
7
- data.tar.gz: 6009edcbbbc9f9feeaad04f26169cd14b9131102fb651944fee152b4c8c2b2bd62e109a1030b87ee5be5831faea4f0077bff157add1535a0cd87e5d9343616b1
6
+ metadata.gz: f29651bddc3f492f908304e0aa1f552b597ba9e8feeaff5f67f1bb045b2b8791f5bf66cf72a16291ae43b7036da4277dc5276dd75550351a4fe476396e7af127
7
+ data.tar.gz: f761e0b4eb1faafd6688beafdf195416ec2db6160265d9227b3e94c332bddf5c4f493965d2a3ce2767c0f9622ad36b90a5e699e21b7d1307f7c85c1ebe499d91
data/Gemfile.lock CHANGED
@@ -1,15 +1,15 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- paymob_accept (0.2.0)
4
+ paymob_accept (0.3.1)
5
5
  faraday
6
6
  json-schema
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
- addressable (2.8.0)
12
- public_suffix (>= 2.0.2, < 5.0)
11
+ addressable (2.8.1)
12
+ public_suffix (>= 2.0.2, < 6.0)
13
13
  diff-lcs (1.5.0)
14
14
  faraday (2.5.2)
15
15
  faraday-net_http (>= 2.0, < 3.1)
@@ -17,7 +17,7 @@ GEM
17
17
  faraday-net_http (3.0.0)
18
18
  json-schema (3.0.0)
19
19
  addressable (>= 2.8)
20
- public_suffix (4.0.7)
20
+ public_suffix (5.0.0)
21
21
  rake (13.0.6)
22
22
  rspec (3.11.0)
23
23
  rspec-core (~> 3.11.0)
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # PaymobAccept
1
+ # Paymob Accept
2
2
 
3
3
  `paymob_accept` is a Ruby gem created by [OneOrder](https://www.oneorder.net/) for integrating [Paymob](https://paymob.com/en) payment solutions with your Ruby application.
4
4
 
@@ -26,13 +26,14 @@ Configure the gem with your configuration
26
26
 
27
27
  ```ruby
28
28
  PaymobAccept.configure do |config|
29
- config.api_key = "######"
30
- config.online_integration_id = "######"
31
- config.kiosk_integration_id = "######"
32
- config.cash_integration_id = "######"
33
- config.wallet_integration_id = "######"
34
- config.auth_integration_id = "######"
35
- config.moto_integration_id = "######"
29
+ config.api_key = "######"
30
+ config.hmac_key = "######"
31
+ config.online_integration_id = "######"
32
+ config.kiosk_integration_id = "######"
33
+ config.cash_integration_id = "######"
34
+ config.wallet_integration_id = "######"
35
+ config.auth_integration_id = "######"
36
+ config.moto_integration_id = "######"
36
37
  end
37
38
  ```
38
39
 
@@ -111,11 +112,15 @@ The `:method` key in the `charge` method could be one of the following:
111
112
 
112
113
  Please refer to the official Paymob documentation for in-depth explanation about each payment method.
113
114
 
114
- The return value of the `charge` method in general is the response of Paymob's server which varies according to the payment method except in `:online`. In an `:online` payment if an `iframe_id` is provided, the return value is an iFrame URL with an embedded payment token. If the `iframe_id` is not provided, only the payment token is returned
115
+ The return value of the `charge` method in general is the response of Paymob's server which varies according to the payment method except in `:online`. In an `:online` payment if an `iframe_id` is provided, the return value is an iFrame URL with an embedded payment token. If the `iframe_id` is not provided, only the payment token and order_id is returned
115
116
 
116
117
  ### Paying with a saved card token
117
118
 
118
- To pre-fill an iFrame with a customer card data or process a MOTO charge, make sure the `customer_data` hash has a `cc_token` key in addition to the fields mentioned above.
119
+ ```ruby
120
+ def pay_moto(customer:, address:, cc_token:, amount_cents:, amount_currency:)
121
+ ```
122
+
123
+ - To pre-fill an iFrame with a customer card data or process a MOTO charge, make sure to pass the `cc_token` key in addition to the fields mentioned above.
119
124
 
120
125
  ## Dealing with charges
121
126
 
@@ -130,9 +135,16 @@ To pre-fill an iFrame with a customer card data or process a MOTO charge, make s
130
135
  - Void a transaction: `service.void!(transaction_id: transaction_id)`
131
136
  - Capture an auth transaction: `service.capture!(transaction_id: transaction_id, amount_cents: amount_cents)`
132
137
 
138
+ ## HMAC validation
139
+
140
+ `PaymobAccept::Hmac.validate(paymob_response: , hmac_key:)`
141
+
142
+ `hmac_key` can be either passed once to the configuration block, otherwise, it must be passed to the `validate` function.
143
+
144
+
133
145
  ## Roadmap
134
146
 
135
- - [ ] HMAC validation
147
+ - [x] HMAC validation
136
148
 
137
149
  ## Contributing
138
150
 
@@ -28,20 +28,20 @@ module PaymobAccept
28
28
  end
29
29
 
30
30
  # 3. Payment Key Request
31
- def generate_payment_intent(customer:, address:, integration_id:, amount_cents:, amount_currency:, iframe_id: nil, order_id: nil, auth_token: get_auth_token)
31
+ def generate_payment_intent(customer:, address:, integration_id:, amount_cents:, amount_currency:, cc_token: nil, iframe_id: nil, order_id: nil, auth_token: get_auth_token)
32
32
  if order_id.nil?
33
33
  order = create_order(amount_cents: amount_cents, amount_currency: amount_currency)
34
34
  order_id = order['id']
35
35
  end
36
36
  payment_token = generate_payment_key(auth_token: auth_token, customer: customer, address: address, order_id: order_id, amount_cents: amount_cents, amount_currency: amount_currency,
37
- integration_id: integration_id)
37
+ integration_id: integration_id, cc_token: cc_token)
38
38
 
39
- format_bill_reference(payment_token, iframe_id)
39
+ { token: format_bill_reference(payment_token, iframe_id), order_id: order_id }
40
40
  end
41
41
 
42
42
  private
43
43
 
44
- def generate_payment_key(customer:, address:, amount_cents:, amount_currency:, integration_id:, order_id: nil, auth_token: get_auth_token)
44
+ def generate_payment_key(customer:, address:, amount_cents:, amount_currency:, integration_id:, cc_token: nil, order_id: nil, auth_token: get_auth_token)
45
45
  body = {
46
46
  "auth_token": auth_token,
47
47
  "amount_cents": amount_cents.to_i,
@@ -65,7 +65,7 @@ module PaymobAccept
65
65
  },
66
66
  "integration_id": integration_id
67
67
  }
68
- body['token'] = customer[:cc_token] unless customer[:cc_token].nil?
68
+ body['token'] = cc_token unless cc_token.nil?
69
69
 
70
70
  response = @client.request('/acceptance/payment_keys', body)
71
71
 
@@ -98,7 +98,6 @@ module PaymobAccept
98
98
  "last_name": { "type": 'string' },
99
99
  "email": { "type": 'string' },
100
100
  "phone_number": { "type": 'string' },
101
- "cc_token": { "type": 'string' },
102
101
  "wallet_mobile_number": { "type": 'string' }
103
102
  },
104
103
  "required": %w[email phone_number]
@@ -36,15 +36,15 @@ module PaymobAccept
36
36
  end
37
37
 
38
38
  # Return an iFrame URL if an iframe_id is provided. Otherwise, returns a payment token
39
- # The iFrame will be prepoulated with the credit card info if customer[cc_token] is present and is valid stored credit card token on Paymob's server
40
- def pay_online(customer:, address:, amount_cents:, amount_currency:, iframe_id: nil)
39
+ # The iFrame will be prepoulated with the credit card info if cc_token is present and is valid stored credit card token on Paymob's server
40
+ def pay_online(customer:, address:, amount_cents:, amount_currency:, cc_token: nil, iframe_id: nil)
41
41
  generate_payment_intent(customer: customer, address: address, amount_cents: amount_cents, amount_currency: amount_currency,
42
- integration_id: online_integration_id, iframe_id: iframe_id)
42
+ integration_id: online_integration_id, iframe_id: iframe_id, cc_token: cc_token)
43
43
  end
44
44
 
45
45
  # Paying MOTO (ie. with a saved card token)
46
- def pay_moto(customer:, address:, amount_cents:, amount_currency:)
47
- if customer[:cc_token].nil?
46
+ def pay_moto(customer:, address:, cc_token:, amount_cents:, amount_currency:)
47
+ if cc_token.nil?
48
48
  raise ArgumentError,
49
49
  'You need to provide a credit card token for MOTO payments'
50
50
  end
@@ -52,7 +52,7 @@ module PaymobAccept
52
52
  bill_reference = generate_payment_intent(customer: customer, address: address, amount_cents: amount_cents, amount_currency: amount_currency,
53
53
  integration_id: auth_integration_id)
54
54
  body = {
55
- "source": { "subtype": 'TOKEN', "identifier": customer[:cc_token] },
55
+ "source": { "subtype": 'TOKEN', "identifier": cc_token },
56
56
  "payment_token": bill_reference
57
57
  }
58
58
  @client.request('/acceptance/payments/pay', body)
@@ -1,7 +1,7 @@
1
1
  module PaymobAccept
2
2
  class Configuration
3
3
  attr_accessor :api_key, :online_integration_id, :cash_integration_id, :kiosk_integration_id,
4
- :auth_integration_id, :wallet_integration_id, :moto_integration_id
4
+ :auth_integration_id, :wallet_integration_id, :moto_integration_id, :hmac_key
5
5
  end
6
6
 
7
7
  class ConfigurationMissingError < StandardError; end
@@ -0,0 +1,21 @@
1
+ module PaymobAccept
2
+ module Hmac
3
+ FILTERED_KEYS = %w[amount_cents created_at currency error_occured has_parent_transaction id
4
+ integration_id is_3d_secure is_auth is_capture is_refunded is_standalone_payment
5
+ is_voided order.id owner
6
+ pending source_data.pan source_data.sub_type source_data.type success].freeze
7
+
8
+ class << self
9
+ def validate(paymob_response:, hmac_key: PaymobAccept.configuration.hmac_key)
10
+ raise ArgumentError, 'hmac_key is required' if hmac_key.nil?
11
+
12
+ digest = OpenSSL::Digest.new('sha512')
13
+ concatenated_str = FILTERED_KEYS.map do |element|
14
+ paymob_response.dig('obj', *element.split('.'))
15
+ end.join
16
+ secure_hash = OpenSSL::HMAC.hexdigest(digest, hmac_key, concatenated_str)
17
+ secure_hash == paymob_response['hmac']
18
+ end
19
+ end
20
+ end
21
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PaymobAccept
4
- VERSION = '0.2.1'
4
+ VERSION = '0.3.1'
5
5
  end
data/lib/paymob_accept.rb CHANGED
@@ -9,6 +9,7 @@ require 'paymob_accept/api/pay'
9
9
  require 'paymob_accept/api/client'
10
10
  require 'paymob_accept/api/charge'
11
11
 
12
+ require 'paymob_accept/hmac'
12
13
  require 'json'
13
14
  require 'faraday'
14
15
  require 'faraday/net_http'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: paymob_accept
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - OneOrder
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-10-02 00:00:00.000000000 Z
11
+ date: 2022-10-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -63,6 +63,7 @@ files:
63
63
  - lib/paymob_accept/api/pay.rb
64
64
  - lib/paymob_accept/configuration.rb
65
65
  - lib/paymob_accept/errors/bad_gateway.rb
66
+ - lib/paymob_accept/hmac.rb
66
67
  - lib/paymob_accept/version.rb
67
68
  - paymob_accept.gemspec
68
69
  homepage: https://github.com/oneorder-tech/paymob-accept