fawry 1.0.0 → 1.1.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: fbda1f1ab11ae04767a26c8989237f7ce246a3de49aaa4032ec43504b8e5779c
4
- data.tar.gz: cf4891b451a00c47d74254c1e065512572f4e5f19c94db7956b2e94dc210d538
3
+ metadata.gz: 34dc9f1782c59c274ae83ab7cb5bf7542c02df23f12d3343c0bacc06d0385acf
4
+ data.tar.gz: 1e902699e6671b59e4d83ab246c6811fe4472c2b370843ce2b614e5e74811e80
5
5
  SHA512:
6
- metadata.gz: 2f0571abf34444cb9343f603e0b195ccb6ce683f2d5d4d5e82515a8058e361095aa4af21df17cd15db1ed0fe16195b354d1d708a9855e9c11d9e8eea151cfaca
7
- data.tar.gz: 3414b7912f9eab50220ae66ac0d5010b2ecb9b6d359d25929ed7effe671128030d19928a7d1c57107f6ed467dfc315b95b79ad0199ac8f033f4a3e817538e83c
6
+ metadata.gz: e18d4c44a20192fafd829aae6b9726bdbef550f1f5a32fc28865d61bf7336f93d86c2eec07605eea53d29990ef45eabfd175c29e3e8425ca230d4f0ccd195d63
7
+ data.tar.gz: 4eed6906aa47aa7e45d7b18fecf2ff2878aca3939e49f071f0e0ce16ffbc2278e0b204261cd03dbe5009f5c5c97bec7b08cc57f8faae52880229e57225fd9ecb
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- fawry (1.0.0)
4
+ fawry (1.1.1)
5
5
  dry-validation (~> 1.3, >= 1.3.1)
6
6
  faraday (~> 0.17.0)
7
7
 
@@ -12,13 +12,14 @@ GEM
12
12
  public_suffix (>= 2.0.2, < 5.0)
13
13
  ast (2.4.0)
14
14
  byebug (11.0.1)
15
- concurrent-ruby (1.1.5)
15
+ concurrent-ruby (1.1.7)
16
16
  crack (0.4.3)
17
17
  safe_yaml (~> 1.0.0)
18
18
  diff-lcs (1.3)
19
- dry-configurable (0.9.0)
19
+ dry-configurable (0.11.6)
20
20
  concurrent-ruby (~> 1.0)
21
21
  dry-core (~> 0.4, >= 0.4.7)
22
+ dry-equalizer (~> 0.2)
22
23
  dry-container (0.7.2)
23
24
  concurrent-ruby (~> 1.0)
24
25
  dry-configurable (~> 0.1, >= 0.1.3)
@@ -26,33 +27,33 @@ GEM
26
27
  concurrent-ruby (~> 1.0)
27
28
  dry-equalizer (0.3.0)
28
29
  dry-inflector (0.2.0)
29
- dry-initializer (3.0.2)
30
- dry-logic (1.0.5)
30
+ dry-initializer (3.0.4)
31
+ dry-logic (1.0.8)
31
32
  concurrent-ruby (~> 1.0)
32
33
  dry-core (~> 0.2)
33
34
  dry-equalizer (~> 0.2)
34
- dry-schema (1.4.2)
35
+ dry-schema (1.5.5)
35
36
  concurrent-ruby (~> 1.0)
36
37
  dry-configurable (~> 0.8, >= 0.8.3)
37
38
  dry-core (~> 0.4)
38
39
  dry-equalizer (~> 0.2)
39
40
  dry-initializer (~> 3.0)
40
41
  dry-logic (~> 1.0)
41
- dry-types (~> 1.2)
42
- dry-types (1.2.2)
42
+ dry-types (~> 1.4)
43
+ dry-types (1.4.0)
43
44
  concurrent-ruby (~> 1.0)
44
45
  dry-container (~> 0.3)
45
46
  dry-core (~> 0.4, >= 0.4.4)
46
47
  dry-equalizer (~> 0.3)
47
48
  dry-inflector (~> 0.1, >= 0.1.2)
48
49
  dry-logic (~> 1.0, >= 1.0.2)
49
- dry-validation (1.4.0)
50
+ dry-validation (1.5.6)
50
51
  concurrent-ruby (~> 1.0)
51
52
  dry-container (~> 0.7, >= 0.7.1)
52
53
  dry-core (~> 0.4)
53
54
  dry-equalizer (~> 0.2)
54
55
  dry-initializer (~> 3.0)
55
- dry-schema (~> 1.0, >= 1.3.1)
56
+ dry-schema (~> 1.5, >= 1.5.2)
56
57
  faraday (0.17.1)
57
58
  multipart-post (>= 1.2, < 3)
58
59
  hashdiff (1.0.0)
@@ -63,7 +64,7 @@ GEM
63
64
  ast (~> 2.4.0)
64
65
  public_suffix (4.0.1)
65
66
  rainbow (3.0.0)
66
- rake (10.5.0)
67
+ rake (13.0.1)
67
68
  rspec (3.9.0)
68
69
  rspec-core (~> 3.9.0)
69
70
  rspec-expectations (~> 3.9.0)
@@ -101,11 +102,11 @@ DEPENDENCIES
101
102
  bundler (~> 2.0)
102
103
  byebug (~> 11.0, >= 11.0.1)
103
104
  fawry!
104
- rake (~> 10.0)
105
+ rake (~> 13.0)
105
106
  rspec (~> 3.0)
106
107
  rspec_junit_formatter
107
108
  rubocop (~> 0.76.0)
108
109
  webmock (~> 3.7, >= 3.7.6)
109
110
 
110
111
  BUNDLED WITH
111
- 2.0.2
112
+ 2.1.4
@@ -0,0 +1,186 @@
1
+ [![CircleCI](https://circleci.com/gh/fawry-api/fawry.svg?style=svg)](https://circleci.com/gh/fawry-api/fawry)
2
+
3
+ # Fawry
4
+
5
+ **تنويه:** نحن لسنا تابعين رسميًا لشركة فوري.
6
+
7
+ مكتبة لتسهيل التعامل مع خدمات الدفع الخاصة بشبكة الدفع الإلكتروني فوري:
8
+
9
+ - [لإجراء عملية دفع](https://github.com/fawry-api/fawry#charge-customers)
10
+ - [لإجراء عملية استرداد](https://github.com/fawry-api/fawry#refund-customers)
11
+ - [حالة الدفع](https://github.com/fawry-api/fawry#get-payment-status)
12
+ - [عرض رموز الكروت](https://github.com/fawry-api/fawry#list-card-tokens)
13
+ - [إضافة رمز كارت](https://github.com/fawry-api/fawry#create-card-token)
14
+ - [حذف رمز كارت](https://github.com/fawry-api/fawry#delete-card-token)
15
+ - [تحليل رد خدمة فوري V2](https://github.com/fawry-api/fawry#parse-fawry-service-callback-v2)
16
+ - [طلب البيانات الخاصة بإعدادات الإستخدام](https://github.com/fawry-api/fawry#configuration-keys-as-environment-variables)
17
+
18
+ _المكتبة تدعم النظام التجريبي لفوري ايضا_
19
+
20
+ ## لإضافة وتشغيل المكتبة
21
+
22
+ أضف هذا السطر إلى ملف Gemfile الخاص بتطبيقك:
23
+
24
+ ```ruby
25
+ gem 'fawry'
26
+ ```
27
+
28
+ ثم نفذ:
29
+
30
+ $ bundle
31
+
32
+ أو قم بتثبيته بنفسك على النحو التالي:
33
+
34
+ $ gem install fawry
35
+
36
+ ## طريقة الإستعمال
37
+
38
+ ### لإجراء عملية دفع
39
+
40
+ ```ruby
41
+ params = { "merchant_code": 'merchant_code',
42
+ "merchant_ref_num": 'io5jxf3jp27kfh8m719arcqgw7izo7db',
43
+ "customer_profile_id": 'ocvsydvbu2gcp528wvl64i9z5srdalg5',
44
+ "customer_mobile": '012345678901',
45
+ "payment_method": 'PAYATFAWRY',
46
+ "currency_code": 'EGP',
47
+ "amount": 20,
48
+ "fawry_secure_key": 'fawry_secure_key',
49
+ "description": 'the charge request description',
50
+ "charge_items": [{ "item_id": 'fk3fn9flk8et9a5t9w3c5h3oc684ivho',
51
+ "description": 'desc', "price": 20, "quantity": 1 }] }
52
+
53
+ # استخدم خيار النظام التجريبي للاتصال بالنظام التجريبي الخاص بفوري
54
+ # sandbox: true
55
+ res = Fawry.charge(params, sandbox: true)
56
+ # => #<Fawry::FawryResponse:0x0000564257d0ea90 @type="ChargeResponse", @reference_number="931600239",
57
+ # @merchant_ref_number="io5jxf3jp27kfh8m719arcqgw7izo7db",
58
+ # @expiration_time=1573153206979, @status_code=200,
59
+ # @status_description="Operation done successfully">
60
+
61
+ res.success? # => true
62
+ res.reference_number # => 931600239
63
+ ```
64
+
65
+ ### لإجراء عملية استرداد
66
+
67
+ ```ruby
68
+ params = { "merchant_code": 'merchant_code',
69
+ "reference_number": '931337410',
70
+ "refund_amount": 20,
71
+ "fawry_secure_key": 'fawry_secure_key' }
72
+
73
+ res = Fawry.refund(params, sandbox: true)
74
+ # => #<Fawry::FawryResponse:0x0000564257d0ea90 @type="ResponseDataModel", @status_code=200,
75
+ # @status_description="Operation done successfully">
76
+
77
+ res.success? # => true
78
+ ```
79
+
80
+ ### حالة الدفع
81
+
82
+ ```ruby
83
+ params = { "merchant_code": 'merchant_code',
84
+ "merchant_ref_number": 'ssshxb98phmyvm434es62kage3nsm2cj',
85
+ "fawry_secure_key": 'fawry_secure_key' }
86
+
87
+ res = Fawry.payment_status(params, sandbox: true)
88
+ # => #<Fawry::FawryResponse:0x0000559974056898 @type="PaymentStatusResponse", @reference_number="931922417",
89
+ # @merchant_ref_number="ssshxb98phmyvm434es62kage3nsm2cj",
90
+ # @expiration_time=1573297736167, @status_code=200,
91
+ # @status_description="Operation done successfully", @payment_amount=20,
92
+ # @payment_method="PAYATFAWRY", @payment_status="UNPAID">
93
+
94
+ res.success? # => true
95
+ res.payment_status # => UNPAID
96
+ ```
97
+
98
+ ### عرض رموز الكروت
99
+
100
+ ```ruby
101
+ params = { "merchant_code": 'merchant_code',
102
+ "customer_profile_id": 'customer_profile_id',
103
+ "fawry_secure_key": 'fawry_secure_key' }
104
+
105
+ res = Fawry.list_tokens(params, sandbox: true)
106
+
107
+ #<Fawry::FawryResponse:0x0000556cb3a31798 @fawry_api_response={"type"=>"CustomerTokensResponse", "cards"=>[{"token"=>"b5sshhdsl98df96200f254c19b2718bfc825a0678888216c28962b3e66a393084ee9aed6", "creationDate"=>1599487402318, "lastFourDigits"=>"4242", "brand"=>"Visa Card"}, {"token"=>"fb98dslsksmkdds7857ed7042ce30a2a5b777e1f1ac6ac58da1c8c0199f61df7a8bc098e96", "creationDate"=>1599489158457, "lastFourDigits"=>"0001", "brand"=>"Visa Card"}, {"token"=>"cc03fwqaacbd94e468a1b756ac1cbb285a41a2428df9f1a727457b41f9447d0058c7c", "creationDate"=>1599584834346, "lastFourDigits"=>"2346", "brand"=>"MasterCard"}, {"token"=>"f04a8bc9c973f900515f4b58e52c9ff03070baf3f534bdfdad0e97679534f60ddkjk13", "creationDate"=>1600260415739, "lastFourDigits"=>"8769", "brand"=>"Visa Card"}], "statusCode"=>200, "statusDescription"=>"Operation done successfully"}, @type="CustomerTokensResponse", @cards=[{"token"=>"b5sshhdsl98df96200f254c19b2718bfc825a0678888216c28962b3e66a393084ee9aed6", "creationDate"=>1599487402318, "lastFourDigits"=>"4242", "brand"=>"Visa Card"}, {"token"=>"fb98dslsksmkdds7857ed7042ce30a2a5b777e1f1ac6ac58da1c8c0199f61df7a8bc098e96", "creationDate"=>1599489158457, "lastFourDigits"=>"0001", "brand"=>"Visa Card"}, {"token"=>"cc03fwqaacbd94e468a1b756ac1cbb285a41a2428df9f1a727457b41f9447d0058c7c", "creationDate"=>1599584834346, "lastFourDigits"=>"2346", "brand"=>"MasterCard"}, {"token"=>"f04a8bc9c973f900515f4b58e52c9ff03070baf3f534bdfdad0e97679534f60ddkjk13", "creationDate"=>1600260415739, "lastFourDigits"=>"8769", "brand"=>"Visa Card"}], @status_code=200, @status_description="Operation done successfully">
108
+
109
+ res.success? # => true
110
+ res.cards # => cards
111
+ ```
112
+
113
+ ### إضافة رمز كارت
114
+
115
+ ```ruby
116
+ params = { "merchant_code" : "merchant_code",
117
+ "customer_profile_id" : "customer_profile_id",
118
+ "customer_mobile" : "customer_mobile",
119
+ "customer_email" : "customer_email",
120
+ "card_number" : "card_number",
121
+ "expiry_year" : "expiry_year",
122
+ "expiry_month" : "expiry_month",
123
+ "cvv" : "cvv" }
124
+ res = Fawry.create_card_token(params, sandbox: true)
125
+ #<Fawry::FawryResponse:0x0000556cb3eb0080 @fawry_api_response={"type"=>"CardTokenResponse", "card"=>{"token"=>"b598f96200f254c19b2718bfc825a063278888216c28962b3e66a393084ee9aed6", "creationDate"=>1607011562353, "lastFourDigits"=>"4242"}, "statusCode"=>200, "statusDescription"=>"Operation done successfully"}, @type="CardTokenResponse", @status_code=200, @status_description="Operation done successfully", @card={"token"=>"b598f96200f254c19b2718bfc825a063278888216c28962b3e66a393084ee9aed6", "creationDate"=>1607011562353, "lastFourDigits"=>"4242"}>
126
+
127
+ res.success?
128
+ res.card
129
+ ```
130
+
131
+ ### حذف رمز كارت
132
+
133
+ ```ruby
134
+ params = { "merchant_code": 'merchant_code',
135
+ "customer_profile_id": 'customer_profile_id',
136
+ "card_token": 'card_token' }
137
+
138
+ res = Fawry.delete_token(params, sandbox: true)
139
+ #<Fawry::FawryResponse:0x0000556cb57c2460 @fawry_api_response={"type"=>"CardTokenResponse", "statusCode"=>200, "statusDescription"=>"Operation done successfully"}, @type="CardTokenResponse", @status_code=200, @status_description="Operation done successfully">
140
+ res.success?
141
+
142
+ ```
143
+
144
+ ### رد اتصال خدمة تحليل فوري v2
145
+
146
+ ```ruby
147
+ # تم إرسال المعلمات من خادم فوري
148
+ callback_params = { "requestId": 'c72827d084ea4b88949d91dd2db4996e', "fawryRefNumber": '970177',
149
+ "merchantRefNumber": '9708f1cea8b5426cb57922df51b7f790',
150
+ "customerMobile": '01004545545', "customerMail": 'fawry@fawry.com',
151
+ "paymentAmount": 152.00, "orderAmount": 150.00, "fawryFees": 2.00,
152
+ "shippingFees": '', "orderStatus": 'NEW', "paymentMethod": 'PAYATFAWRY',
153
+ "messageSignature": 'b0175565323e464b01dc9407160368af5568196997fb6e379374a4f4fbbcf587',
154
+ "orderExpiryDate": 1_533_554_719_314,
155
+ "orderItems": [{ "itemCode": 'e6aacbd5a498487ab1a10ae71061535d', "price": 150.0, "quantity": 1 }] }
156
+
157
+ # FAWRY_SECURE_KEY يجب تعيين متغير البيئة
158
+ fawry_callback = Fawry.parse_callback(callback_params, {})
159
+ # <Fawry::FawryCallback:0x000056339ac43730 @request_id="c72827d084ea4b88949d91dd2db4996e", @fawry_ref_number="970177",
160
+ # @merchant_ref_number="9708f1cea8b5426cb57922df51b7f790", @customer_mobile="01004545545",
161
+ # @customer_mail="fawry@fawry.com", @order_status="NEW", @order_amount=150.0, @fawry_fees=2.0, ...>
162
+
163
+ fawry_callback.fawry_ref_number # => 970177
164
+ fawry_callback.order_status # => NEW
165
+ ```
166
+
167
+ ### طلب البيانات الخاصة بإعدادات الإستخدام
168
+
169
+ يمكن إرسال بيانات تهيئة فوري مثل رمز التاجر ومفتاح الأمان خلال البيانات المعطاه (`merchant_code`, `fawry_secure_key` ) الى **charge**, **refund**, **payment_status** طرق, _أو_ يمكن تعيينها كمتغيرات لنظام التشغيل: (`FAWRY_MERCHANT_CODE`, `FAWRY_SECURE_KEY`).
170
+
171
+ لتحليل fawry معاودة الاتصال ، يجب عليك ضبط متغير البيئة `FAWRY_SECURE_KEY`.
172
+
173
+ ## الخطوات القادمة المطلوب تنفيذها:
174
+
175
+ - إضافة خيار لرفع الاستثناء عند فشل الطلب
176
+
177
+ ## تطوير المكتبة
178
+
179
+ بعد التحقق من الريبو ، قم بتشغيل `bin/setup` لتثبيت التبعيات.
180
+ ثم نفذ الأمر `rake spec` لإجراء الاختبارات. يمكنك أيضا الجري `bin/console` للمطالبة التفاعلية التي تسمح لك بالتجربة.
181
+
182
+ لتثبيت هذه المكتبة على جهازك ، قم بتشغيل `bundle exec rake install`. لإصدار إصدار جديد ، قم بتحديث رقم الإصدار بتنسيق `version.rb`, ثم نفذ الأمر `bundle exec rake release`, الذي سينشئ علامة git للإصدار ، ويدفع التزامات git والعلامات ، ويدفع ملف `.gem` يا صديق [rubygems.org](https://rubygems.org).
183
+
184
+ ## المساهمة
185
+
186
+ يتم الترحيب بتقارير الأخطاء وطلبات السحب على GitHub في https://github.com/amrrbakry/fawry. يهدف هذا المشروع إلى أن يكون مساحة آمنة ومرحبة للتعاون ، ومن المتوقع أن يلتزم المساهمون بـ [Contributor Covenant](http://contributor-covenant.org) القواعد السلوكية.
data/README.md CHANGED
@@ -2,11 +2,18 @@
2
2
 
3
3
  # Fawry
4
4
 
5
+ [README - متوفر باللغة العربية](https://github.com/fawry-api/fawry/blob/master/README-ar.md)
6
+
7
+ **Disclaimer:** we are _not officially affilated_ with the _Fawry_ company.
8
+
5
9
  A plug-and-play library that makes interfacing with Fawry's payment gateway API a breeze:
6
10
 
7
11
  - [Charge customers](https://github.com/fawry-api/fawry#charge-customers)
8
12
  - [Refund customers](https://github.com/fawry-api/fawry#refund-customers)
9
13
  - [Get payment status](https://github.com/fawry-api/fawry#get-payment-status)
14
+ - [List card tokens](https://github.com/fawry-api/fawry#list-card-tokens)
15
+ - [Create card token](https://github.com/fawry-api/fawry#create-card-token)
16
+ - [Delete card token](https://github.com/fawry-api/fawry#delete-card-token)
10
17
  - [Parse Fawry's service callback V2](https://github.com/fawry-api/fawry#parse-fawry-service-callback-v2)
11
18
  - [Configuration keys as environment variables](https://github.com/fawry-api/fawry#configuration-keys-as-environment-variables)
12
19
 
@@ -56,7 +63,7 @@ res.success? # => true
56
63
  res.reference_number # => 931600239
57
64
  ```
58
65
 
59
- ### Refund Customers
66
+ ### Refund Customers
60
67
 
61
68
  ```ruby
62
69
  params = { "merchant_code": 'merchant_code',
@@ -71,7 +78,7 @@ res = Fawry.refund(params, sandbox: true)
71
78
  res.success? # => true
72
79
  ```
73
80
 
74
- ### Get Payment Status
81
+ ### Get Payment Status
75
82
 
76
83
  ```ruby
77
84
  params = { "merchant_code": 'merchant_code',
@@ -89,7 +96,54 @@ res.success? # => true
89
96
  res.payment_status # => UNPAID
90
97
  ```
91
98
 
92
- ### Parse Fawry service callback v2
99
+ ### List Card Tokens
100
+
101
+ ```ruby
102
+ params = { "merchant_code": 'merchant_code',
103
+ "customer_profile_id": 'customer_profile_id',
104
+ "fawry_secure_key": 'fawry_secure_key' }
105
+
106
+ res = Fawry.list_tokens(params, sandbox: true)
107
+ #<Fawry::FawryResponse:0x0000556cb3a31798 @fawry_api_response={"type"=>"CustomerTokensResponse", "cards"=>[{"token"=>"b5sshhdsl98df96200f254c19b2718bfc825a0678888216c28962b3e66a393084ee9aed6", "creationDate"=>1599487402318, "lastFourDigits"=>"4242", "brand"=>"Visa Card"}, {"token"=>"fb98dslsksmkdds7857ed7042ce30a2a5b777e1f1ac6ac58da1c8c0199f61df7a8bc098e96", "creationDate"=>1599489158457, "lastFourDigits"=>"0001", "brand"=>"Visa Card"}, {"token"=>"cc03fwqaacbd94e468a1b756ac1cbb285a41a2428df9f1a727457b41f9447d0058c7c", "creationDate"=>1599584834346, "lastFourDigits"=>"2346", "brand"=>"MasterCard"}, {"token"=>"f04a8bc9c973f900515f4b58e52c9ff03070baf3f534bdfdad0e97679534f60ddkjk13", "creationDate"=>1600260415739, "lastFourDigits"=>"8769", "brand"=>"Visa Card"}], "statusCode"=>200, "statusDescription"=>"Operation done successfully"}, @type="CustomerTokensResponse", @cards=[{"token"=>"b5sshhdsl98df96200f254c19b2718bfc825a0678888216c28962b3e66a393084ee9aed6", "creationDate"=>1599487402318, "lastFourDigits"=>"4242", "brand"=>"Visa Card"}, {"token"=>"fb98dslsksmkdds7857ed7042ce30a2a5b777e1f1ac6ac58da1c8c0199f61df7a8bc098e96", "creationDate"=>1599489158457, "lastFourDigits"=>"0001", "brand"=>"Visa Card"}, {"token"=>"cc03fwqaacbd94e468a1b756ac1cbb285a41a2428df9f1a727457b41f9447d0058c7c", "creationDate"=>1599584834346, "lastFourDigits"=>"2346", "brand"=>"MasterCard"}, {"token"=>"f04a8bc9c973f900515f4b58e52c9ff03070baf3f534bdfdad0e97679534f60ddkjk13", "creationDate"=>1600260415739, "lastFourDigits"=>"8769", "brand"=>"Visa Card"}], @status_code=200, @status_description="Operation done successfully">
108
+
109
+ res.success? # => true
110
+ res.cards # => cards
111
+ ```
112
+
113
+ ### Create Card Token
114
+
115
+ ```ruby
116
+ params = { "merchant_code" : "merchant_code",
117
+ "customer_profile_id" : "customer_profile_id",
118
+ "customer_mobile" : "customer_mobile",
119
+ "customer_email" : "customer_email",
120
+ "card_number" : "card_number",
121
+ "expiry_year" : "expiry_year",
122
+ "expiry_month" : "expiry_month",
123
+ "cvv" : "cvv" }
124
+ res = Fawry.create_card_token(params, sandbox: true)
125
+ #<Fawry::FawryResponse:0x0000556cb3eb0080 @fawry_api_response={"type"=>"CardTokenResponse", "card"=>{"token"=>"b598f96200f254c19b2718bfc825a063278888216c28962b3e66a393084ee9aed6", "creationDate"=>1607011562353, "lastFourDigits"=>"4242"}, "statusCode"=>200, "statusDescription"=>"Operation done successfully"}, @type="CardTokenResponse", @status_code=200, @status_description="Operation done successfully", @card={"token"=>"b598f96200f254c19b2718bfc825a063278888216c28962b3e66a393084ee9aed6", "creationDate"=>1607011562353, "lastFourDigits"=>"4242"}>
126
+
127
+ res.success?
128
+ res.card
129
+ ```
130
+
131
+ ### Delete Card Token
132
+
133
+ ```ruby
134
+ params = { "merchant_code": "merchant_code",
135
+ "customer_profile_id": "customer_profile_id",
136
+ "card_token": "card_token",
137
+ "fawry_secure_key": "fawry_secure_key" }
138
+
139
+ res = Fawry.delete_token(params, sandbox: true)
140
+ #<Fawry::FawryResponse:0x0000556cb57c2460 @fawry_api_response={"type"=>"CardTokenResponse", "statusCode"=>200, "statusDescription"=>"Operation done successfully"}, @type="CardTokenResponse", @status_code=200, @status_description="Operation done successfully">
141
+
142
+ res.success?
143
+
144
+ ```
145
+
146
+ ### Parse Fawry service callback v2
93
147
 
94
148
  ```ruby
95
149
  # params sent from fawry server
@@ -103,7 +157,7 @@ callback_params = { "requestId": 'c72827d084ea4b88949d91dd2db4996e', "fawryRefNu
103
157
  "orderItems": [{ "itemCode": 'e6aacbd5a498487ab1a10ae71061535d', "price": 150.0, "quantity": 1 }] }
104
158
 
105
159
  # FAWRY_SECURE_KEY env var must be set
106
- fawry_callback = Fawry.parse_callback(callback_params, {})
160
+ fawry_callback = Fawry.parse_callback(callback_params)
107
161
  # <Fawry::FawryCallback:0x000056339ac43730 @request_id="c72827d084ea4b88949d91dd2db4996e", @fawry_ref_number="970177",
108
162
  # @merchant_ref_number="9708f1cea8b5426cb57922df51b7f790", @customer_mobile="01004545545",
109
163
  # @customer_mail="fawry@fawry.com", @order_status="NEW", @order_amount=150.0, @fawry_fees=2.0, ...>
@@ -33,7 +33,7 @@ Gem::Specification.new do |spec|
33
33
 
34
34
  spec.add_development_dependency 'bundler', '~> 2.0'
35
35
  spec.add_development_dependency 'byebug', '~> 11.0', '>= 11.0.1'
36
- spec.add_development_dependency 'rake', '~> 10.0'
36
+ spec.add_development_dependency 'rake', '~> 13.0'
37
37
  spec.add_development_dependency 'rspec', '~> 3.0'
38
38
  spec.add_development_dependency 'rspec_junit_formatter'
39
39
  spec.add_development_dependency 'rubocop', '~> 0.76.0'
@@ -10,9 +10,15 @@ require 'fawry/fawry_callback'
10
10
  require 'fawry/requests/charge_request'
11
11
  require 'fawry/requests/refund_request'
12
12
  require 'fawry/requests/payment_status_request'
13
+ require 'fawry/requests/create_card_token_request'
14
+ require 'fawry/requests/list_tokens_request'
15
+ require 'fawry/requests/delete_token_request'
13
16
  require 'fawry/contracts/charge_request_contract'
14
17
  require 'fawry/contracts/refund_request_contract'
15
18
  require 'fawry/contracts/payment_status_request_contract'
19
+ require 'fawry/contracts/create_card_token_request_contract'
20
+ require 'fawry/contracts/list_tokens_request_contract'
21
+ require 'fawry/contracts/delete_token_request_contract'
16
22
 
17
23
  module Fawry
18
24
  class << self
@@ -112,6 +118,92 @@ module Fawry
112
118
  FawryRequest.new('payment_status', params, opts).fire_payment_status_request
113
119
  end
114
120
 
121
+ # Sends a card token request to Fawry API
122
+ # performs param validation and builds
123
+ # the request signature
124
+ #
125
+ # @param params [Hash] list of params to send to fawry
126
+ # required(:customer_profile_id).value(:string)
127
+ # required(:customer_mobile).value(:string)
128
+ # required(:merchant_code).value(:string)
129
+ # required(:customer_email).value(:string)
130
+ # required(:card_number).value(:string)
131
+ # required(:expiry_year).value(:string)
132
+ # required(:expiry_month).value(:string)
133
+ # required(:cvv).value(:string)
134
+ #
135
+ # @param opts [Hash] list of options to
136
+ # configure the request
137
+ # @option opts :sandbox [Boolean] whether to
138
+ # send the request to fawry sandbox env or not
139
+ # false by default
140
+ #
141
+ # @raise [Fawry::InvalidFawryRequestError] raised when one
142
+ # or more of the params are invalid. the message
143
+ # specifices which params and why are they invalid
144
+ #
145
+ # @return [Fawry::FawryResponse] an object that
146
+ # has Fawry API response keys as instance methods
147
+ # plus some convenience methods e.g. success?
148
+
149
+ def create_card_token(params, opts = {})
150
+ FawryRequest.new('create_card_token', params, opts).fire_create_card_token_request
151
+ end
152
+
153
+ # Sends a list tokens request to Fawry API
154
+ # performs param validation and builds
155
+ # the request signature
156
+ #
157
+ # @param params [Hash] list of params to send to fawry
158
+ # required(:merchant_code).value(:string)
159
+ # required(:customer_profile_id).value(:string)
160
+ # optional(:fawry_secure_key).value(:string)
161
+ #
162
+ # @param opts [Hash] list of options to
163
+ # configure the request
164
+ # @option opts :sandbox [Boolean] whether to
165
+ # send the request to fawry sandbox env or not
166
+ # false by default
167
+ #
168
+ # @raise [Fawry::InvalidFawryRequestError] raised when one
169
+ # or more of the params are invalid. the message
170
+ # specifices which params and why are they invalid
171
+ #
172
+ # @return [Fawry::FawryResponse] an object that
173
+ # has Fawry API response keys as instance methods
174
+ # plus some convenience methods e.g. success?
175
+
176
+ def list_tokens(params, opts = {})
177
+ FawryRequest.new('list_tokens', params, opts).fire_list_tokens_request
178
+ end
179
+
180
+ # Sends delete token request to Fawry API
181
+ # performs param validation and builds
182
+ # the request signature
183
+ #
184
+ # @param params [Hash] list of params to send to fawry
185
+ # required(:customer_profile_id).value(:string)
186
+ # optional(:merchant_code).value(:string)
187
+ # optional(:fawry_secure_key).value(:string)
188
+ #
189
+ # @param opts [Hash] list of options to
190
+ # configure the request
191
+ # @option opts :sandbox [Boolean] whether to
192
+ # send the request to fawry sandbox env or not
193
+ # false by default
194
+ #
195
+ # @raise [Fawry::InvalidFawryRequestError] raised when one
196
+ # or more of the params are invalid. the message
197
+ # specifices which params and why are they invalid
198
+ #
199
+ # @return [Fawry::FawryResponse] an object that
200
+ # has Fawry API response keys as instance methods
201
+ # plus some convenience methods e.g. success?
202
+
203
+ def delete_token(params, opts = {})
204
+ FawryRequest.new('delete_token', params, opts).fire_delete_token_request
205
+ end
206
+
115
207
  # Parses Fawry callback v2 into
116
208
  # FawryCallback object with callback
117
209
  # params as instance methods
@@ -5,9 +5,9 @@ require 'json'
5
5
 
6
6
  module Fawry
7
7
  class Connection
8
- FAWRY_BASE_URL = 'https://www.atfawry.com/ECommerceWeb/Fawry/payments/'
8
+ FAWRY_BASE_URL = 'https://www.atfawry.com/ECommerceWeb/Fawry/'
9
9
 
10
- FAWRY_SANDBOX_BASE_URL = 'https://atfawry.fawrystaging.com//ECommerceWeb/Fawry/payments/'
10
+ FAWRY_SANDBOX_BASE_URL = 'https://atfawry.fawrystaging.com//ECommerceWeb/Fawry/'
11
11
 
12
12
  class << self
13
13
  def post(path, params, body, options)
@@ -30,6 +30,17 @@ module Fawry
30
30
  end
31
31
  end
32
32
 
33
+ def delete(path, params, body, options)
34
+ conn = options[:sandbox] ? sandbox_connection : connection
35
+
36
+ conn.delete(path) do |request|
37
+ request.params = params
38
+ request.body = body.to_json
39
+ # Fawry doesn't understand encoded params
40
+ request.options = request.options.merge(params_encoder: ParamsSpecialEncoder)
41
+ end
42
+ end
43
+
33
44
  private
34
45
 
35
46
  def connection
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'dry-validation'
4
+
5
+ module Fawry
6
+ module Contracts
7
+ class CreateCardTokenRequestContract < Dry::Validation::Contract
8
+ params do
9
+ required(:customer_profile_id).value(:string)
10
+ required(:customer_mobile).value(:string)
11
+ required(:merchant_code).value(:string)
12
+ required(:customer_email).value(:string)
13
+ required(:card_number).value(:string)
14
+ required(:expiry_year).value(:string)
15
+ required(:expiry_month).value(:string)
16
+ required(:cvv).value(:string)
17
+ end
18
+
19
+ rule(:customer_email) do
20
+ unless /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i.match?(value)
21
+ key? && key.failure('has invalid format')
22
+ end
23
+ end
24
+
25
+ rule(:merchant_code) do
26
+ if ENV['FAWRY_MERCHANT_CODE'].nil? && value.nil?
27
+ key(:merchant_code).failure('fawry merchant code is required as a param or an env var')
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'dry-validation'
4
+
5
+ module Fawry
6
+ module Contracts
7
+ class DeleteTokenRequestContract < Dry::Validation::Contract
8
+ params do
9
+ required(:merchant_code).value(:string)
10
+ required(:customer_profile_id).value(:string)
11
+ required(:fawry_secure_key).value(:string)
12
+ required(:card_token).value(:string)
13
+ end
14
+
15
+ rule(:fawry_secure_key) do
16
+ if ENV['FAWRY_SECURE_KEY'].nil? && value.nil?
17
+ key(:fawry_secure_key).failure('fawry secure key is required as a param or an env var')
18
+ end
19
+ end
20
+
21
+ rule(:merchant_code) do
22
+ if ENV['FAWRY_MERCHANT_CODE'].nil? && value.nil?
23
+ key(:merchant_code).failure('fawry merchant code is required as a param or an env var')
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'dry-validation'
4
+
5
+ module Fawry
6
+ module Contracts
7
+ class ListTokensRequestContract < Dry::Validation::Contract
8
+ params do
9
+ required(:merchant_code).value(:string)
10
+ required(:customer_profile_id).value(:string)
11
+ optional(:fawry_secure_key).value(:string)
12
+ end
13
+
14
+ rule(:fawry_secure_key) do
15
+ if ENV['FAWRY_SECURE_KEY'].nil? && value.nil?
16
+ key(:fawry_secure_key).failure('fawry secure key is required as a param or an env var')
17
+ end
18
+ end
19
+
20
+ rule(:merchant_code) do
21
+ if ENV['FAWRY_MERCHANT_CODE'].nil? && value.nil?
22
+ key(:merchant_code).failure('fawry merchant code is required as a param or an env var')
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -17,6 +17,8 @@ module Fawry
17
17
  private
18
18
 
19
19
  # rubocop:disable Metrics/MethodLength
20
+ # rubocop:disable Metrics/AbcSize
21
+ # rubocop:disable Metrics/CyclomaticComplexity
20
22
  def build_request
21
23
  case action
22
24
  when 'charge'
@@ -31,7 +33,21 @@ module Fawry
31
33
  self.class.include Requests::PaymentStatusRequest
32
34
  validate_payment_status_params!
33
35
  @request = build_payment_status_request
36
+ when 'create_card_token'
37
+ self.class.include Requests::CreateCardTokenRequest
38
+ validate_card_token_params!
39
+ @request = build_create_card_token_request
40
+ when 'list_tokens'
41
+ self.class.include Requests::ListTokensRequest
42
+ validate_list_tokens_params!
43
+ @request = build_list_tokens_request
44
+ when 'delete_token'
45
+ self.class.include Requests::DeleteTokenRequest
46
+ validate_delete_token_params!
47
+ @request = build_delete_token_request
34
48
  end
49
+ # rubocop:enable Metrics/CyclomaticComplexity
50
+ # rubocop:enable Metrics/AbcSize
35
51
  # rubocop:enable Metrics/MethodLength
36
52
  end
37
53
  end
@@ -18,7 +18,7 @@ module Fawry
18
18
 
19
19
  def build_charge_request
20
20
  {
21
- path: 'charge',
21
+ path: 'payments/charge',
22
22
  params: {},
23
23
  body: charge_request_transformed_params,
24
24
  options: options
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'digest'
4
+
5
+ module Fawry
6
+ module Requests
7
+ module CreateCardTokenRequest
8
+ def fire_create_card_token_request
9
+ fawry_api_response = Connection.post(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_create_card_token_request
18
+ {
19
+ path: 'cards/cardToken',
20
+ params: {},
21
+ body: create_card_token_request_transformed_params,
22
+ options: options
23
+ }
24
+ end
25
+
26
+ def create_card_token_request
27
+ @create_card_token_request ||= params
28
+ end
29
+
30
+ # rubocop:disable Metrics/AbcSize
31
+ def create_card_token_request_transformed_params
32
+ {
33
+ merchantCode: fawry_merchant_code,
34
+ customerProfileId: create_card_token_request[:customer_profile_id],
35
+ customerMobile: create_card_token_request[:customer_mobile],
36
+ customerEmail: create_card_token_request[:customer_email],
37
+ cardNumber: create_card_token_request[:card_number],
38
+ expiryYear: create_card_token_request[:expiry_year],
39
+ expiryMonth: create_card_token_request[:expiry_month],
40
+ cvv: create_card_token_request[:cvv]
41
+ }.compact
42
+ end
43
+
44
+ # rubocop:enable Metrics/AbcSize
45
+
46
+ def fawry_merchant_code
47
+ ENV.fetch('FAWRY_MERCHANT_CODE') { create_card_token_request[:merchant_code] }
48
+ end
49
+
50
+ def fawry_secure_key
51
+ ENV.fetch('FAWRY_SECURE_KEY') { create_card_token_request[:fawry_secure_key] }
52
+ end
53
+
54
+ def validate_card_token_params!
55
+ contract = Contracts::CreateCardTokenRequestContract.new.call(create_card_token_request)
56
+ raise InvalidFawryRequestError, contract.errors.to_h if contract.failure?
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'digest'
4
+
5
+ module Fawry
6
+ module Requests
7
+ module DeleteTokenRequest
8
+ def fire_delete_token_request
9
+ fawry_api_response = Connection.delete(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_delete_token_request
18
+ {
19
+ path: 'cards/cardToken',
20
+ params: {},
21
+ body: delete_token_request_transformed_params,
22
+ options: options
23
+ }
24
+ end
25
+
26
+ def request_params
27
+ @request_params = params
28
+ end
29
+
30
+ def delete_token_request_transformed_params
31
+ {
32
+ merchantCode: fawry_merchant_code,
33
+ customerProfileId: request_params[:customer_profile_id],
34
+ signature: delete_token_request_signature,
35
+ cardToken: request_params[:card_token]
36
+ }.compact
37
+ end
38
+
39
+ def fawry_merchant_code
40
+ ENV.fetch('FAWRY_MERCHANT_CODE') { request_params[:merchant_code] }
41
+ end
42
+
43
+ def fawry_secure_key
44
+ ENV.fetch('FAWRY_SECURE_KEY') { request_params[:fawry_secure_key] }
45
+ end
46
+
47
+ def card_token
48
+ request_params[:card_token]
49
+ end
50
+
51
+ def validate_delete_token_params!
52
+ contract = Contracts::ListTokensRequestContract.new.call(request_params)
53
+ raise InvalidFawryRequestError, contract.errors.to_h if contract.failure?
54
+ end
55
+
56
+ def delete_token_request_signature
57
+ Digest::SHA256.hexdigest("#{fawry_merchant_code}#{request_params[:customer_profile_id]}"\
58
+ "#{card_token}#{fawry_secure_key}")
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'digest'
4
+
5
+ module Fawry
6
+ module Requests
7
+ module ListTokensRequest
8
+ def fire_list_tokens_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_list_tokens_request
18
+ {
19
+ path: 'cards/cardToken',
20
+ params: list_tokens_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 list_tokens_request_transformed_params
31
+ {
32
+ merchantCode: fawry_merchant_code,
33
+ customerProfileId: request_params[:customer_profile_id],
34
+ signature: list_tokens_request_signature
35
+ }.compact
36
+ end
37
+
38
+ def fawry_merchant_code
39
+ ENV.fetch('FAWRY_MERCHANT_CODE') { request_params[:merchant_code] }
40
+ end
41
+
42
+ def fawry_secure_key
43
+ ENV.fetch('FAWRY_SECURE_KEY') { request_params[:fawry_secure_key] }
44
+ end
45
+
46
+ def validate_list_tokens_params!
47
+ contract = Contracts::ListTokensRequestContract.new.call(request_params)
48
+ raise InvalidFawryRequestError, contract.errors.to_h if contract.failure?
49
+ end
50
+
51
+ def list_tokens_request_signature
52
+ Digest::SHA256.hexdigest("#{fawry_merchant_code}#{request_params[:customer_profile_id]}"\
53
+ "#{fawry_secure_key}")
54
+ end
55
+ end
56
+ end
57
+ end
@@ -16,7 +16,7 @@ module Fawry
16
16
 
17
17
  def build_payment_status_request
18
18
  {
19
- path: 'status',
19
+ path: 'payments/status',
20
20
  params: payment_status_request_transformed_params,
21
21
  body: {},
22
22
  options: options
@@ -16,7 +16,7 @@ module Fawry
16
16
 
17
17
  def build_refund_request
18
18
  {
19
- path: 'refund',
19
+ path: 'payments/refund',
20
20
  params: {},
21
21
  body: refund_request_transformed_params,
22
22
  options: options
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Fawry
4
- VERSION = '1.0.0'
4
+ VERSION = '1.1.1'
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: 1.0.0
4
+ version: 1.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Amr Bakry
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-12-26 00:00:00.000000000 Z
11
+ date: 2020-12-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dry-validation
@@ -84,14 +84,14 @@ dependencies:
84
84
  requirements:
85
85
  - - "~>"
86
86
  - !ruby/object:Gem::Version
87
- version: '10.0'
87
+ version: '13.0'
88
88
  type: :development
89
89
  prerelease: false
90
90
  version_requirements: !ruby/object:Gem::Requirement
91
91
  requirements:
92
92
  - - "~>"
93
93
  - !ruby/object:Gem::Version
94
- version: '10.0'
94
+ version: '13.0'
95
95
  - !ruby/object:Gem::Dependency
96
96
  name: rspec
97
97
  requirement: !ruby/object:Gem::Requirement
@@ -154,7 +154,7 @@ dependencies:
154
154
  - - ">="
155
155
  - !ruby/object:Gem::Version
156
156
  version: 3.7.6
157
- description:
157
+ description:
158
158
  email:
159
159
  - amrrbakry17@gmail.com
160
160
  executables: []
@@ -162,7 +162,6 @@ extensions: []
162
162
  extra_rdoc_files: []
163
163
  files:
164
164
  - ".circleci/config.yml"
165
- - ".github/workflows/greetings.yml"
166
165
  - ".gitignore"
167
166
  - ".rspec"
168
167
  - ".rubocop.yml"
@@ -170,6 +169,7 @@ files:
170
169
  - Gemfile
171
170
  - Gemfile.lock
172
171
  - LICENSE.txt
172
+ - README-ar.md
173
173
  - README.md
174
174
  - Rakefile
175
175
  - bin/console
@@ -178,6 +178,9 @@ files:
178
178
  - lib/fawry.rb
179
179
  - lib/fawry/connection.rb
180
180
  - lib/fawry/contracts/charge_request_contract.rb
181
+ - lib/fawry/contracts/create_card_token_request_contract.rb
182
+ - lib/fawry/contracts/delete_token_request_contract.rb
183
+ - lib/fawry/contracts/list_tokens_request_contract.rb
181
184
  - lib/fawry/contracts/payment_status_request_contract.rb
182
185
  - lib/fawry/contracts/refund_request_contract.rb
183
186
  - lib/fawry/errors.rb
@@ -185,6 +188,9 @@ files:
185
188
  - lib/fawry/fawry_request.rb
186
189
  - lib/fawry/fawry_response.rb
187
190
  - lib/fawry/requests/charge_request.rb
191
+ - lib/fawry/requests/create_card_token_request.rb
192
+ - lib/fawry/requests/delete_token_request.rb
193
+ - lib/fawry/requests/list_tokens_request.rb
188
194
  - lib/fawry/requests/payment_status_request.rb
189
195
  - lib/fawry/requests/refund_request.rb
190
196
  - lib/fawry/utils.rb
@@ -195,7 +201,7 @@ licenses:
195
201
  metadata:
196
202
  homepage_uri: https://github.com/amrrbakry/fawry
197
203
  source_code_uri: https://github.com/amrrbakry/fawry
198
- post_install_message:
204
+ post_install_message:
199
205
  rdoc_options: []
200
206
  require_paths:
201
207
  - lib
@@ -210,8 +216,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
210
216
  - !ruby/object:Gem::Version
211
217
  version: '0'
212
218
  requirements: []
213
- rubygems_version: 3.0.1
214
- signing_key:
219
+ rubygems_version: 3.0.8
220
+ signing_key:
215
221
  specification_version: 4
216
222
  summary: A library to interface with Fawry's payment gateway API (charge, refund,
217
223
  payment status, service callback).
@@ -1,13 +0,0 @@
1
- name: Greetings
2
-
3
- on: [pull_request, issues]
4
-
5
- jobs:
6
- greeting:
7
- runs-on: ubuntu-latest
8
- steps:
9
- - uses: actions/first-interaction@v1
10
- with:
11
- repo-token: ${{ secrets.GITHUB_TOKEN }}
12
- issue-message: "Hello, thanks for taking the time to open this issue. We'll get to it as soon as possible."
13
- pr-message: "Hello, thanks for taking the time to open this PR. We'll get to it as soon as possible."