dk_payment_gateway 1.0.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.
data/EXAMPLES.md ADDED
@@ -0,0 +1,491 @@
1
+ # DK Payment Gateway - Usage Examples
2
+
3
+ This document provides comprehensive examples for all API operations supported by the DK Payment Gateway gem.
4
+
5
+ ## Table of Contents
6
+
7
+ 1. [Setup and Authentication](#setup-and-authentication)
8
+ 2. [Pull Payment Examples](#pull-payment-examples)
9
+ 3. [Intra-Bank Transaction Examples](#intra-bank-transaction-examples)
10
+ 4. [QR Payment Examples](#qr-payment-examples)
11
+ 5. [Transaction Status Examples](#transaction-status-examples)
12
+ 6. [Complete Workflow Examples](#complete-workflow-examples)
13
+
14
+ ## Setup and Authentication
15
+
16
+ ### Basic Configuration
17
+
18
+ ```ruby
19
+ require 'dk_payment_gateway'
20
+
21
+ DkPaymentGateway.configure do |config|
22
+ config.base_url = "http://internal-gateway.uat.digitalkidu.bt/api/dkpg"
23
+ config.api_key = "98cf3639-df33-4587-9d36-dae9d2bb974c"
24
+ config.username = "your_username"
25
+ config.password = "your_password"
26
+ config.client_id = "0fefeac4-e969-46ce-8d02-92db4ed8e62e"
27
+ config.client_secret = "your_client_secret"
28
+ config.source_app = "SRC_AVS_0201"
29
+ end
30
+
31
+ # Initialize client
32
+ client = DkPaymentGateway.client
33
+
34
+ # Authenticate (fetches token and private key)
35
+ client.authenticate!
36
+ ```
37
+
38
+ ### Using Environment Variables
39
+
40
+ ```ruby
41
+ # Set environment variables
42
+ # export DK_API_KEY="your_api_key"
43
+ # export DK_USERNAME="your_username"
44
+ # export DK_PASSWORD="your_password"
45
+ # export DK_CLIENT_ID="your_client_id"
46
+ # export DK_CLIENT_SECRET="your_client_secret"
47
+
48
+ DkPaymentGateway.configure do |config|
49
+ config.base_url = ENV['DK_BASE_URL'] || "http://internal-gateway.uat.digitalkidu.bt/api/dkpg"
50
+ config.api_key = ENV['DK_API_KEY']
51
+ config.username = ENV['DK_USERNAME']
52
+ config.password = ENV['DK_PASSWORD']
53
+ config.client_id = ENV['DK_CLIENT_ID']
54
+ config.client_secret = ENV['DK_CLIENT_SECRET']
55
+ config.source_app = ENV['DK_SOURCE_APP'] || "SRC_AVS_0201"
56
+ end
57
+ ```
58
+
59
+ ## Pull Payment Examples
60
+
61
+ ### Example 1: Complete Pull Payment Flow
62
+
63
+ ```ruby
64
+ # Step 1: Generate STAN number
65
+ source_app_suffix = "0201" # Last 4 digits of SRC_AVS_0201
66
+ stan = DkPaymentGateway::PullPayment.generate_stan(source_app_suffix)
67
+ puts "Generated STAN: #{stan}"
68
+
69
+ # Step 2: Request authorization (sends OTP to remitter)
70
+ begin
71
+ auth_response = client.pull_payment.authorize(
72
+ transaction_datetime: Time.now.utc.strftime("%Y-%m-%dT%H:%M:%SZ"),
73
+ stan_number: stan,
74
+ transaction_amount: 1500.00,
75
+ transaction_fee: 10.00,
76
+ payment_desc: "Online purchase - Order #ORD123456",
77
+ account_number: "110158212197",
78
+ account_name: "Merchant Store",
79
+ email_id: "merchant@example.com",
80
+ phone_number: "17811440",
81
+ remitter_account_number: "770182571",
82
+ remitter_account_name: "Customer Name",
83
+ remitter_bank_id: "1040"
84
+ )
85
+
86
+ puts "Authorization successful!"
87
+ puts "Transaction ID: #{auth_response['bfs_txn_id']}"
88
+ puts "STAN: #{auth_response['stan_number']}"
89
+
90
+ # Store the transaction ID for the debit request
91
+ bfs_txn_id = auth_response['bfs_txn_id']
92
+
93
+ # Step 3: Customer receives OTP and provides it
94
+ # In a real application, you would collect this from the user
95
+ otp = "123456" # Customer's OTP
96
+
97
+ # Step 4: Complete the payment with OTP
98
+ debit_response = client.pull_payment.debit(
99
+ request_id: "REQ_#{Time.now.to_i}_#{SecureRandom.hex(4)}",
100
+ bfs_txn_id: bfs_txn_id,
101
+ bfs_remitter_otp: otp,
102
+ bfs_order_no: "ORD123456"
103
+ )
104
+
105
+ if debit_response['code'] == '00'
106
+ puts "Payment completed successfully!"
107
+ puts "Transaction ID: #{debit_response['bfs_txn_id']}"
108
+ puts "Status: #{debit_response['description']}"
109
+ else
110
+ puts "Payment failed: #{debit_response['description']}"
111
+ end
112
+
113
+ rescue DkPaymentGateway::TransactionError => e
114
+ puts "Transaction error: #{e.message}"
115
+ puts "Error code: #{e.response_code}"
116
+ rescue DkPaymentGateway::InvalidParameterError => e
117
+ puts "Invalid parameter: #{e.message}"
118
+ end
119
+ ```
120
+
121
+ ### Example 2: Custom STAN Generation
122
+
123
+ ```ruby
124
+ # Using timestamp-based STAN
125
+ source_app_suffix = "0201"
126
+ stan_timestamp = DkPaymentGateway::PullPayment.generate_stan(source_app_suffix)
127
+ puts "Timestamp STAN: #{stan_timestamp}"
128
+
129
+ # Using custom transaction identifier
130
+ custom_identifier = "12345678"
131
+ stan_custom = DkPaymentGateway::PullPayment.generate_stan(source_app_suffix, custom_identifier)
132
+ puts "Custom STAN: #{stan_custom}"
133
+ ```
134
+
135
+ ## Intra-Bank Transaction Examples
136
+
137
+ ### Example 1: Complete Intra-Bank Transfer
138
+
139
+ ```ruby
140
+ # Step 1: Verify beneficiary account
141
+ begin
142
+ inquiry_response = client.intra_transaction.account_inquiry(
143
+ request_id: "INQ_#{Time.now.to_i}_#{SecureRandom.hex(4)}",
144
+ amount: 5000.00,
145
+ currency: "BTN",
146
+ bene_bank_code: "1060",
147
+ bene_account_number: "100100148337",
148
+ source_account_name: "Rinzin Jamtsho",
149
+ source_account_number: "100100365856"
150
+ )
151
+
152
+ puts "Account inquiry successful!"
153
+ puts "Inquiry ID: #{inquiry_response['inquiry_id']}"
154
+ puts "Beneficiary Name: #{inquiry_response['account_name']}"
155
+
156
+ # Step 2: Proceed with fund transfer
157
+ inquiry_id = inquiry_response['inquiry_id']
158
+
159
+ transfer_response = client.intra_transaction.fund_transfer(
160
+ request_id: "TXN_#{Time.now.to_i}_#{SecureRandom.hex(4)}",
161
+ inquiry_id: inquiry_id,
162
+ transaction_datetime: Time.now.utc.strftime("%Y-%m-%dT%H:%M:%SZ"),
163
+ transaction_amount: 5000.00,
164
+ currency: "BTN",
165
+ payment_type: "INTRA",
166
+ source_account_name: "Rinzin Jamtsho",
167
+ source_account_number: "100100365856",
168
+ bene_cust_name: inquiry_response['account_name'],
169
+ bene_account_number: "100100148337",
170
+ bene_bank_code: "1060",
171
+ narration: "Salary payment for October 2025"
172
+ )
173
+
174
+ puts "Transfer initiated successfully!"
175
+ puts "Transaction Status ID: #{transfer_response['txn_status_id']}"
176
+
177
+ rescue DkPaymentGateway::TransactionError => e
178
+ puts "Transfer failed: #{e.message}"
179
+ puts "Error code: #{e.response_code}"
180
+ end
181
+ ```
182
+
183
+ ### Example 2: Bulk Transfer Processing
184
+
185
+ ```ruby
186
+ # Process multiple transfers
187
+ transfers = [
188
+ { account: "100100148337", amount: 1000.00, name: "Employee 1", narration: "Salary Oct 2025" },
189
+ { account: "100100148338", amount: 1500.00, name: "Employee 2", narration: "Salary Oct 2025" },
190
+ { account: "100100148339", amount: 2000.00, name: "Employee 3", narration: "Salary Oct 2025" }
191
+ ]
192
+
193
+ results = []
194
+
195
+ transfers.each do |transfer|
196
+ begin
197
+ # Step 1: Account inquiry
198
+ inquiry = client.intra_transaction.account_inquiry(
199
+ request_id: "INQ_#{Time.now.to_i}_#{SecureRandom.hex(4)}",
200
+ amount: transfer[:amount],
201
+ currency: "BTN",
202
+ bene_bank_code: "1060",
203
+ bene_account_number: transfer[:account],
204
+ source_account_number: "100100365856"
205
+ )
206
+
207
+ # Step 2: Fund transfer
208
+ result = client.intra_transaction.fund_transfer(
209
+ request_id: "TXN_#{Time.now.to_i}_#{SecureRandom.hex(4)}",
210
+ inquiry_id: inquiry['inquiry_id'],
211
+ transaction_datetime: Time.now.utc.strftime("%Y-%m-%dT%H:%M:%SZ"),
212
+ transaction_amount: transfer[:amount],
213
+ currency: "BTN",
214
+ payment_type: "INTRA",
215
+ source_account_number: "100100365856",
216
+ bene_cust_name: transfer[:name],
217
+ bene_account_number: transfer[:account],
218
+ bene_bank_code: "1060",
219
+ narration: transfer[:narration]
220
+ )
221
+
222
+ results << { account: transfer[:account], status: "success", txn_id: result['txn_status_id'] }
223
+ puts "✓ Transfer to #{transfer[:account]}: Success"
224
+
225
+ rescue DkPaymentGateway::Error => e
226
+ results << { account: transfer[:account], status: "failed", error: e.message }
227
+ puts "✗ Transfer to #{transfer[:account]}: Failed - #{e.message}"
228
+ end
229
+
230
+ # Add delay between requests to avoid rate limiting
231
+ sleep 1
232
+ end
233
+
234
+ puts "\nTransfer Summary:"
235
+ puts "Successful: #{results.count { |r| r[:status] == 'success' }}"
236
+ puts "Failed: #{results.count { |r| r[:status] == 'failed' }}"
237
+ ```
238
+
239
+ ## QR Payment Examples
240
+
241
+ ### Example 1: Generate Static QR Code
242
+
243
+ ```ruby
244
+ # Static QR - customer enters amount at payment time
245
+ begin
246
+ qr_response = client.qr_payment.generate_qr(
247
+ request_id: "QR_#{Time.now.to_i}_#{SecureRandom.hex(4)}",
248
+ currency: "BTN",
249
+ bene_account_number: "100100148337",
250
+ amount: 0, # 0 = static QR
251
+ mcc_code: "5411", # Grocery store
252
+ remarks: "Payment to Merchant Store"
253
+ )
254
+
255
+ # Save QR code image
256
+ filename = "static_qr_#{Time.now.to_i}.png"
257
+ client.qr_payment.save_qr_image(qr_response['image'], filename)
258
+ puts "Static QR code saved to #{filename}"
259
+
260
+ rescue DkPaymentGateway::Error => e
261
+ puts "QR generation failed: #{e.message}"
262
+ end
263
+ ```
264
+
265
+ ### Example 2: Generate Dynamic QR Code
266
+
267
+ ```ruby
268
+ # Dynamic QR - fixed amount
269
+ begin
270
+ qr_response = client.qr_payment.generate_qr(
271
+ request_id: "QR_#{Time.now.to_i}_#{SecureRandom.hex(4)}",
272
+ currency: "BTN",
273
+ bene_account_number: "100100148337",
274
+ amount: 250.50, # Fixed amount
275
+ mcc_code: "5812", # Restaurant
276
+ remarks: "Invoice #INV-2025-001"
277
+ )
278
+
279
+ # Save QR code image
280
+ filename = "invoice_qr_#{Time.now.to_i}.png"
281
+ client.qr_payment.save_qr_image(qr_response['image'], filename)
282
+ puts "Dynamic QR code saved to #{filename}"
283
+ puts "Amount: BTN 250.50"
284
+
285
+ rescue DkPaymentGateway::Error => e
286
+ puts "QR generation failed: #{e.message}"
287
+ end
288
+ ```
289
+
290
+ ## Transaction Status Examples
291
+
292
+ ### Example 1: Check Current Day Transaction
293
+
294
+ ```ruby
295
+ begin
296
+ status = client.transaction_status.check_current_day(
297
+ request_id: "STATUS_#{Time.now.to_i}",
298
+ transaction_id: "test_txn_update23567",
299
+ bene_account_number: "100100365856"
300
+ )
301
+
302
+ puts "Transaction Status:"
303
+ puts "Status: #{status['status']['status_desc']}"
304
+ puts "Amount: BTN #{status['status']['amount']}"
305
+ puts "Timestamp: #{status['status']['txn_ts']}"
306
+ puts "Debit Account: #{status['status']['debit_account']}"
307
+ puts "Credit Account: #{status['status']['credit_account']}"
308
+
309
+ rescue DkPaymentGateway::TransactionError => e
310
+ puts "Status check failed: #{e.message}"
311
+ end
312
+ ```
313
+
314
+ ### Example 2: Check Historical Transaction
315
+
316
+ ```ruby
317
+ begin
318
+ status = client.transaction_status.check_previous_days(
319
+ request_id: "STATUS_#{Time.now.to_i}",
320
+ transaction_id: "test_txn_update23567",
321
+ transaction_date: "2025-09-18",
322
+ bene_account_number: "100100365856"
323
+ )
324
+
325
+ if status.is_a?(Array)
326
+ status.each do |txn|
327
+ puts "Transaction found:"
328
+ puts " Status: #{txn['status_desc']}"
329
+ puts " Amount: BTN #{txn['amount']}"
330
+ puts " Date: #{txn['txn_ts']}"
331
+ end
332
+ end
333
+
334
+ rescue DkPaymentGateway::TransactionError => e
335
+ puts "Status check failed: #{e.message}"
336
+ end
337
+ ```
338
+
339
+ ## Complete Workflow Examples
340
+
341
+ ### Example: E-commerce Payment Flow
342
+
343
+ ```ruby
344
+ class PaymentProcessor
345
+ def initialize
346
+ @client = DkPaymentGateway.client
347
+ @client.authenticate!
348
+ end
349
+
350
+ def process_order_payment(order)
351
+ # Step 1: Initiate payment authorization
352
+ stan = DkPaymentGateway::PullPayment.generate_stan("0201")
353
+
354
+ auth_response = @client.pull_payment.authorize(
355
+ transaction_datetime: Time.now.utc.strftime("%Y-%m-%dT%H:%M:%SZ"),
356
+ stan_number: stan,
357
+ transaction_amount: order[:total_amount],
358
+ transaction_fee: calculate_fee(order[:total_amount]),
359
+ payment_desc: "Order ##{order[:order_id]}",
360
+ account_number: merchant_account,
361
+ account_name: merchant_name,
362
+ email_id: order[:customer_email],
363
+ phone_number: order[:customer_phone],
364
+ remitter_account_number: order[:customer_account],
365
+ remitter_account_name: order[:customer_name],
366
+ remitter_bank_id: order[:customer_bank_id]
367
+ )
368
+
369
+ # Store transaction ID
370
+ order[:bfs_txn_id] = auth_response['bfs_txn_id']
371
+
372
+ # Return transaction ID to customer for OTP entry
373
+ auth_response
374
+ end
375
+
376
+ def complete_payment(order, otp)
377
+ debit_response = @client.pull_payment.debit(
378
+ request_id: "ORD_#{order[:order_id]}_#{Time.now.to_i}",
379
+ bfs_txn_id: order[:bfs_txn_id],
380
+ bfs_remitter_otp: otp,
381
+ bfs_order_no: order[:order_id]
382
+ )
383
+
384
+ if debit_response['code'] == '00'
385
+ # Payment successful - update order status
386
+ update_order_status(order[:order_id], 'paid')
387
+ send_confirmation_email(order)
388
+ true
389
+ else
390
+ # Payment failed
391
+ update_order_status(order[:order_id], 'payment_failed')
392
+ false
393
+ end
394
+ end
395
+
396
+ private
397
+
398
+ def calculate_fee(amount)
399
+ # Example fee calculation
400
+ [amount * 0.01, 5.0].max # 1% with minimum 5 BTN
401
+ end
402
+
403
+ def merchant_account
404
+ "110158212197"
405
+ end
406
+
407
+ def merchant_name
408
+ "My E-commerce Store"
409
+ end
410
+
411
+ def update_order_status(order_id, status)
412
+ # Update in database
413
+ end
414
+
415
+ def send_confirmation_email(order)
416
+ # Send email
417
+ end
418
+ end
419
+
420
+ # Usage
421
+ processor = PaymentProcessor.new
422
+
423
+ order = {
424
+ order_id: "ORD123456",
425
+ total_amount: 2500.00,
426
+ customer_email: "customer@example.com",
427
+ customer_phone: "17811440",
428
+ customer_account: "770182571",
429
+ customer_name: "John Doe",
430
+ customer_bank_id: "1040"
431
+ }
432
+
433
+ # Initiate payment
434
+ auth = processor.process_order_payment(order)
435
+ puts "Please enter OTP sent to #{order[:customer_phone]}"
436
+
437
+ # Customer enters OTP
438
+ otp = gets.chomp
439
+
440
+ # Complete payment
441
+ if processor.complete_payment(order, otp)
442
+ puts "Payment successful! Order confirmed."
443
+ else
444
+ puts "Payment failed. Please try again."
445
+ end
446
+ ```
447
+
448
+ ## Error Handling Best Practices
449
+
450
+ ```ruby
451
+ def safe_payment_operation
452
+ client = DkPaymentGateway.client
453
+ client.authenticate!
454
+
455
+ # Your payment logic here
456
+
457
+ rescue DkPaymentGateway::ConfigurationError => e
458
+ log_error("Configuration issue", e)
459
+ notify_admin("Payment gateway configuration error: #{e.message}")
460
+
461
+ rescue DkPaymentGateway::AuthenticationError => e
462
+ log_error("Authentication failed", e)
463
+ # Retry authentication or notify admin
464
+
465
+ rescue DkPaymentGateway::InvalidParameterError => e
466
+ log_error("Invalid parameters", e)
467
+ # Return user-friendly error message
468
+ { error: "Invalid payment details", details: e.response_detail }
469
+
470
+ rescue DkPaymentGateway::TransactionError => e
471
+ log_error("Transaction failed", e)
472
+ # Handle based on error code
473
+ case e.response_code
474
+ when "4002"
475
+ { error: "Invalid transaction details" }
476
+ when "5001"
477
+ { error: "Service temporarily unavailable" }
478
+ else
479
+ { error: "Transaction failed", code: e.response_code }
480
+ end
481
+
482
+ rescue DkPaymentGateway::NetworkError => e
483
+ log_error("Network error", e)
484
+ # Retry logic or queue for later
485
+
486
+ rescue DkPaymentGateway::Error => e
487
+ log_error("General payment gateway error", e)
488
+ { error: "Payment processing error" }
489
+ end
490
+ ```
491
+