rma-payment-gateway 1.0.0 → 1.0.1

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: db28ad0604ff2c4059955f10b342d1b3b0646f6c7a356659c1fa92e6a223bfb5
4
- data.tar.gz: 055de1e3a1b750b7087db7dff5c3a93352b0f376beec3406300456ef290d565b
3
+ metadata.gz: 93083bc4a39780d2b7387e013edf0e71d01bcdd128582383c0805edf8173f461
4
+ data.tar.gz: 1dbea3526aed562579e070a1cc99470be1ff94d76bce1c2f6fd8780c6b033bbf
5
5
  SHA512:
6
- metadata.gz: 8c76f60d57151def8dea62e8e306b9249fd3ae6b9d6d2d786423ee94c7a0980ec146786d8c214e54eee8c7f622c21185e7665703d77420b7ed641afcd5ca86b4
7
- data.tar.gz: 185416f5968e942cc855151733cf7493f31bfc07af6bf8df0db1009e9416f7b7e8adf6456d037fa547ccedd424c5e698c0afc40de23bf5696e435e14b88a1b19
6
+ metadata.gz: f9f2d09bf865b4b4575fc18e54f990e98cd13f732c53a337a78ccbcc9ae8de7a94cdd9ac52a2b0a91a3191d803672bcd9d6e1fb4464cf883e3c3bd445c3d0f51
7
+ data.tar.gz: 94d79e7619c070b68d7e29704d27bcc2e6bfca44dd745801e1be6b63ea8220e9bc24629eb4212971364d41268a2f1fb68d5b251f96ba435fef8c05e1c32b59de
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # RMA Payment Gateway Ruby Gem
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/rma-payment-gateway.svg)](https://badge.fury.io/rb/rma-payment-gateway)
4
- [![Ruby](https://img.shields.io/badge/ruby-%3E%3D%203.2.0-ruby.svg)](https://www.ruby-lang.org/en/)
4
+ [![Ruby](https://img.shields.io/badge/ruby-%3E%3D%202.7.0-ruby.svg)](https://www.ruby-lang.org/en/)
5
5
 
6
6
  A Ruby gem for integrating with the RMA (Royal Monetary Authority of Bhutan) Payment Gateway API. This gem provides a simple and intuitive interface for processing payments through the RMA Payment Gateway system.
7
7
 
@@ -0,0 +1,81 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'rma/payment/gateway'
5
+
6
+ # Configure the gateway
7
+ Rma::Payment::Gateway.configure do |config|
8
+ config.base_url = ENV['RMA_BASE_URL'] || 'https://your-rma-gateway-url.com'
9
+ config.rsa_key_path = ENV['RMA_RSA_KEY_PATH'] || 'config/rma_private_key.pem'
10
+ config.beneficiary_id = ENV['RMA_BENEFICIARY_ID'] || 'your_beneficiary_id'
11
+ config.payment_description = ENV['RMA_PAYMENT_DESCRIPTION'] || 'Payment for services'
12
+ end
13
+
14
+ # Initialize client
15
+ client = Rma::Payment::Gateway::Client.new
16
+
17
+ def process_payment(client, order_no, amount, email, bank_id, account_no, otp)
18
+ puts "šŸš€ Starting payment process for Order: #{order_no}"
19
+ puts "šŸ’° Amount: #{amount} BTN"
20
+ puts "šŸ“§ Email: #{email}"
21
+ puts "-" * 50
22
+
23
+ begin
24
+ # Step 1: Authorization
25
+ puts "\n1ļøāƒ£ Requesting payment authorization..."
26
+ auth_response = client.authorization.call(order_no, amount, email)
27
+ transaction_id = auth_response["bfs_bfsTxnId"]
28
+
29
+ puts "āœ… Authorization successful!"
30
+ puts " Transaction ID: #{transaction_id}"
31
+ puts " Response Code: #{auth_response['bfs_responseCode']}"
32
+
33
+ # Step 2: Account Inquiry
34
+ puts "\n2ļøāƒ£ Verifying bank account..."
35
+ inquiry_response = client.account_inquiry.call(transaction_id, bank_id, account_no)
36
+
37
+ puts "āœ… Account verified!"
38
+ puts " Account Holder: #{inquiry_response['bfs_remitterName']}"
39
+ puts " Account Number: #{inquiry_response['bfs_remitterAccNo']}"
40
+ puts " šŸ“± OTP sent to registered mobile number"
41
+
42
+ # Step 3: Debit Request
43
+ puts "\n3ļøāƒ£ Completing payment with OTP..."
44
+ debit_response = client.debit_request.call(transaction_id, otp)
45
+
46
+ puts "šŸŽ‰ Payment completed successfully!"
47
+ puts " Transaction ID: #{debit_response['bfs_bfsTxnId']}"
48
+ puts " Amount Debited: #{debit_response['bfs_txnAmount']} BTN"
49
+ puts " Order Number: #{debit_response['bfs_orderNo']}"
50
+
51
+ return debit_response
52
+
53
+ rescue Rma::Payment::Gateway::InvalidParameterError => e
54
+ puts "āŒ Invalid parameters: #{e.message}"
55
+ rescue Rma::Payment::Gateway::AuthenticationError => e
56
+ puts "āŒ Authentication failed: #{e.message}"
57
+ rescue Rma::Payment::Gateway::NetworkError => e
58
+ puts "āŒ Network error: #{e.message}"
59
+ rescue Rma::Payment::Gateway::Error => e
60
+ puts "āŒ Payment failed: #{e.message}"
61
+ end
62
+ end
63
+
64
+ # Example usage
65
+ if __FILE__ == $0
66
+ # Sample payment data
67
+ order_no = "ORDER#{Time.now.to_i}"
68
+ amount = 100.50
69
+ email = "customer@example.com"
70
+ bank_id = "1010" # Bank of Bhutan
71
+ account_no = "12345678"
72
+ otp = "123456" # In real scenario, customer provides this
73
+
74
+ result = process_payment(client, order_no, amount, email, bank_id, account_no, otp)
75
+
76
+ if result
77
+ puts "\nšŸŽŠ Payment processing completed successfully!"
78
+ else
79
+ puts "\nšŸ’„ Payment processing failed!"
80
+ end
81
+ end
@@ -0,0 +1,251 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'rma/payment/gateway'
5
+
6
+ # Configure the gateway
7
+ Rma::Payment::Gateway.configure do |config|
8
+ config.base_url = ENV['RMA_BASE_URL'] || 'https://your-rma-gateway-url.com'
9
+ config.rsa_key_path = ENV['RMA_RSA_KEY_PATH'] || 'config/rma_private_key.pem'
10
+ config.beneficiary_id = ENV['RMA_BENEFICIARY_ID'] || 'your_beneficiary_id'
11
+ config.payment_description = ENV['RMA_PAYMENT_DESCRIPTION'] || 'Payment for services'
12
+ end
13
+
14
+ class PaymentProcessor
15
+ attr_reader :client, :logger
16
+
17
+ def initialize
18
+ @client = Rma::Payment::Gateway::Client.new
19
+ @logger = Logger.new(STDOUT)
20
+ end
21
+
22
+ def process_payment_with_comprehensive_error_handling(order_no, amount, email, bank_id, account_no, otp)
23
+ logger.info("Starting payment process for order: #{order_no}")
24
+
25
+ begin
26
+ # Step 1: Authorization with error handling
27
+ transaction_id = authorize_payment(order_no, amount, email)
28
+ return nil unless transaction_id
29
+
30
+ # Step 2: Account verification with error handling
31
+ account_verified = verify_account(transaction_id, bank_id, account_no)
32
+ return nil unless account_verified
33
+
34
+ # Step 3: Complete payment with error handling
35
+ complete_payment(transaction_id, otp)
36
+
37
+ rescue => e
38
+ logger.error("Unexpected error in payment process: #{e.message}")
39
+ logger.error(e.backtrace.join("\n"))
40
+ nil
41
+ end
42
+ end
43
+
44
+ private
45
+
46
+ def authorize_payment(order_no, amount, email)
47
+ logger.info("Authorizing payment...")
48
+
49
+ response = client.authorization.call(order_no, amount, email)
50
+ transaction_id = response["bfs_bfsTxnId"]
51
+
52
+ logger.info("Authorization successful: #{transaction_id}")
53
+ transaction_id
54
+
55
+ rescue Rma::Payment::Gateway::ConfigurationError => e
56
+ logger.error("Configuration error: #{e.message}")
57
+ logger.error("Please check your RMA gateway configuration")
58
+ notify_admin("Configuration Error", e)
59
+ nil
60
+
61
+ rescue Rma::Payment::Gateway::InvalidParameterError => e
62
+ logger.error("Invalid parameters: #{e.message}")
63
+ logger.error("Order: #{order_no}, Amount: #{amount}, Email: #{email}")
64
+
65
+ # Provide specific feedback based on the error
66
+ if e.message.include?('email')
67
+ logger.error("Email validation failed")
68
+ elsif e.message.include?('amount')
69
+ logger.error("Amount validation failed")
70
+ end
71
+ nil
72
+
73
+ rescue Rma::Payment::Gateway::AuthenticationError => e
74
+ logger.error("Authentication failed: #{e.message}")
75
+ logger.error("Check your RSA key and beneficiary ID")
76
+ notify_admin("Authentication Error", e)
77
+ nil
78
+
79
+ rescue Rma::Payment::Gateway::NetworkError => e
80
+ logger.error("Network error during authorization: #{e.message}")
81
+
82
+ # Implement retry logic for network errors
83
+ retry_authorization(order_no, amount, email, 3)
84
+
85
+ rescue Rma::Payment::Gateway::APIError => e
86
+ logger.error("API error during authorization: #{e.message}")
87
+ logger.error("Response code: #{e.response_code}")
88
+
89
+ case e.response_code
90
+ when '02'
91
+ logger.error("Invalid beneficiary - contact RMA support")
92
+ when '99'
93
+ logger.error("System error - try again later")
94
+ end
95
+ nil
96
+
97
+ rescue Rma::Payment::Gateway::Error => e
98
+ logger.error("Gateway error during authorization: #{e.message}")
99
+ nil
100
+ end
101
+
102
+ def verify_account(transaction_id, bank_id, account_no)
103
+ logger.info("Verifying account...")
104
+
105
+ response = client.account_inquiry.call(transaction_id, bank_id, account_no)
106
+ account_name = response["bfs_remitterName"]
107
+
108
+ logger.info("Account verified: #{account_name}")
109
+ true
110
+
111
+ rescue Rma::Payment::Gateway::InvalidParameterError => e
112
+ logger.error("Invalid account details: #{e.message}")
113
+
114
+ if e.message.include?('bank_id')
115
+ logger.error("Invalid bank code: #{bank_id}")
116
+ elsif e.message.include?('account_no')
117
+ logger.error("Invalid account number: #{account_no}")
118
+ end
119
+ false
120
+
121
+ rescue Rma::Payment::Gateway::APIError => e
122
+ logger.error("Account verification failed: #{e.message}")
123
+
124
+ case e.response_code
125
+ when '03'
126
+ logger.error("Invalid transaction ID")
127
+ when '04'
128
+ logger.error("Account not found or inactive")
129
+ end
130
+ false
131
+
132
+ rescue Rma::Payment::Gateway::Error => e
133
+ logger.error("Error during account verification: #{e.message}")
134
+ false
135
+ end
136
+
137
+ def complete_payment(transaction_id, otp)
138
+ logger.info("Completing payment...")
139
+
140
+ response = client.debit_request.call(transaction_id, otp)
141
+
142
+ logger.info("Payment completed successfully!")
143
+ logger.info("Amount: #{response['bfs_txnAmount']} BTN")
144
+ response
145
+
146
+ rescue Rma::Payment::Gateway::APIError => e
147
+ logger.error("Payment completion failed: #{e.message}")
148
+
149
+ case e.response_code
150
+ when '05'
151
+ logger.error("Invalid OTP provided")
152
+ when '06'
153
+ logger.error("OTP has expired - request new OTP")
154
+ when '04'
155
+ logger.error("Insufficient funds in account")
156
+ end
157
+ nil
158
+
159
+ rescue Rma::Payment::Gateway::Error => e
160
+ logger.error("Error during payment completion: #{e.message}")
161
+ nil
162
+ end
163
+
164
+ def retry_authorization(order_no, amount, email, max_retries)
165
+ retries = 0
166
+
167
+ while retries < max_retries
168
+ retries += 1
169
+ sleep(2 ** retries) # Exponential backoff
170
+
171
+ logger.info("Retrying authorization (attempt #{retries}/#{max_retries})...")
172
+
173
+ begin
174
+ response = client.authorization.call(order_no, amount, email)
175
+ logger.info("Authorization successful on retry #{retries}")
176
+ return response["bfs_bfsTxnId"]
177
+ rescue Rma::Payment::Gateway::NetworkError => e
178
+ logger.warn("Retry #{retries} failed: #{e.message}")
179
+ next if retries < max_retries
180
+ logger.error("All retry attempts failed")
181
+ end
182
+ end
183
+
184
+ nil
185
+ end
186
+
187
+ def notify_admin(error_type, exception)
188
+ # In a real application, you would send email, Slack notification, etc.
189
+ logger.error("ADMIN NOTIFICATION: #{error_type}")
190
+ logger.error("Exception: #{exception.class.name}")
191
+ logger.error("Message: #{exception.message}")
192
+ logger.error("Time: #{Time.current}")
193
+ end
194
+ end
195
+
196
+ # Example usage with comprehensive error handling
197
+ if __FILE__ == $0
198
+ processor = PaymentProcessor.new
199
+
200
+ # Test with various error scenarios
201
+ test_cases = [
202
+ {
203
+ name: "Valid Payment",
204
+ order_no: "ORDER#{Time.now.to_i}",
205
+ amount: 100.50,
206
+ email: "customer@example.com",
207
+ bank_id: "1010",
208
+ account_no: "12345678",
209
+ otp: "123456"
210
+ },
211
+ {
212
+ name: "Invalid Email",
213
+ order_no: "ORDER#{Time.now.to_i}",
214
+ amount: 100.50,
215
+ email: "invalid-email",
216
+ bank_id: "1010",
217
+ account_no: "12345678",
218
+ otp: "123456"
219
+ },
220
+ {
221
+ name: "Invalid Amount",
222
+ order_no: "ORDER#{Time.now.to_i}",
223
+ amount: -100,
224
+ email: "customer@example.com",
225
+ bank_id: "1010",
226
+ account_no: "12345678",
227
+ otp: "123456"
228
+ }
229
+ ]
230
+
231
+ test_cases.each do |test_case|
232
+ puts "\n" + "="*60
233
+ puts "Testing: #{test_case[:name]}"
234
+ puts "="*60
235
+
236
+ result = processor.process_payment_with_comprehensive_error_handling(
237
+ test_case[:order_no],
238
+ test_case[:amount],
239
+ test_case[:email],
240
+ test_case[:bank_id],
241
+ test_case[:account_no],
242
+ test_case[:otp]
243
+ )
244
+
245
+ if result
246
+ puts "āœ… Test passed: Payment processed successfully"
247
+ else
248
+ puts "āŒ Test failed: Payment processing failed"
249
+ end
250
+ end
251
+ end
@@ -0,0 +1,171 @@
1
+ # Example Rails integration
2
+
3
+ # app/models/payment.rb
4
+ class Payment < ApplicationRecord
5
+ belongs_to :order
6
+ belongs_to :user
7
+
8
+ enum status: {
9
+ pending: 0,
10
+ authorized: 1,
11
+ account_verified: 2,
12
+ completed: 3,
13
+ failed: 4,
14
+ refunded: 5
15
+ }
16
+
17
+ validates :order_id, presence: true
18
+ validates :amount, presence: true, numericality: { greater_than: 0 }
19
+ validates :transaction_id, uniqueness: true, allow_nil: true
20
+
21
+ def rma_client
22
+ @rma_client ||= Rma::Payment::Gateway::Client.new
23
+ end
24
+
25
+ def authorize!
26
+ response = rma_client.authorization.call(
27
+ order.order_number,
28
+ amount,
29
+ user.email
30
+ )
31
+
32
+ update!(
33
+ transaction_id: response["bfs_bfsTxnId"],
34
+ status: :authorized,
35
+ authorized_at: Time.current
36
+ )
37
+
38
+ response
39
+ end
40
+
41
+ def verify_account!(bank_id, account_no)
42
+ response = rma_client.account_inquiry.call(
43
+ transaction_id,
44
+ bank_id,
45
+ account_no
46
+ )
47
+
48
+ update!(
49
+ status: :account_verified,
50
+ account_holder_name: response["bfs_remitterName"],
51
+ verified_at: Time.current
52
+ )
53
+
54
+ response
55
+ end
56
+
57
+ def complete!(otp)
58
+ response = rma_client.debit_request.call(
59
+ transaction_id,
60
+ otp
61
+ )
62
+
63
+ update!(
64
+ status: :completed,
65
+ completed_at: Time.current
66
+ )
67
+
68
+ response
69
+ end
70
+ end
71
+
72
+ # app/services/rma_payment_service.rb
73
+ class RmaPaymentService
74
+ attr_reader :payment, :errors
75
+
76
+ def initialize(payment)
77
+ @payment = payment
78
+ @errors = []
79
+ end
80
+
81
+ def process_authorization
82
+ payment.authorize!
83
+ true
84
+ rescue Rma::Payment::Gateway::Error => e
85
+ @errors << e.message
86
+ payment.update(status: :failed, error_message: e.message)
87
+ false
88
+ end
89
+
90
+ def process_account_verification(bank_id, account_no)
91
+ payment.verify_account!(bank_id, account_no)
92
+ true
93
+ rescue Rma::Payment::Gateway::Error => e
94
+ @errors << e.message
95
+ payment.update(status: :failed, error_message: e.message)
96
+ false
97
+ end
98
+
99
+ def process_completion(otp)
100
+ payment.complete!(otp)
101
+ true
102
+ rescue Rma::Payment::Gateway::Error => e
103
+ @errors << e.message
104
+ payment.update(status: :failed, error_message: e.message)
105
+ false
106
+ end
107
+ end
108
+
109
+ # app/controllers/payments_controller.rb
110
+ class PaymentsController < ApplicationController
111
+ before_action :authenticate_user!
112
+ before_action :find_payment, except: [:create]
113
+
114
+ def create
115
+ @payment = current_user.payments.build(payment_params)
116
+ @payment.order = current_order
117
+
118
+ if @payment.save
119
+ service = RmaPaymentService.new(@payment)
120
+
121
+ if service.process_authorization
122
+ redirect_to account_verification_payment_path(@payment)
123
+ else
124
+ flash[:error] = service.errors.join(', ')
125
+ render :new
126
+ end
127
+ else
128
+ render :new
129
+ end
130
+ end
131
+
132
+ def account_verification
133
+ # Show form for bank details
134
+ end
135
+
136
+ def verify_account
137
+ service = RmaPaymentService.new(@payment)
138
+
139
+ if service.process_account_verification(params[:bank_id], params[:account_no])
140
+ redirect_to otp_verification_payment_path(@payment)
141
+ else
142
+ flash[:error] = service.errors.join(', ')
143
+ render :account_verification
144
+ end
145
+ end
146
+
147
+ def otp_verification
148
+ # Show form for OTP
149
+ end
150
+
151
+ def complete
152
+ service = RmaPaymentService.new(@payment)
153
+
154
+ if service.process_completion(params[:otp])
155
+ redirect_to payment_success_path(@payment)
156
+ else
157
+ flash[:error] = service.errors.join(', ')
158
+ render :otp_verification
159
+ end
160
+ end
161
+
162
+ private
163
+
164
+ def find_payment
165
+ @payment = current_user.payments.find(params[:id])
166
+ end
167
+
168
+ def payment_params
169
+ params.require(:payment).permit(:amount)
170
+ end
171
+ end