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.
@@ -0,0 +1,199 @@
1
+ # DK Payment Gateway - Example Applications
2
+
3
+ This directory contains example applications demonstrating how to use the DK Payment Gateway gem.
4
+
5
+ ## Prerequisites
6
+
7
+ Before running these examples, make sure you have:
8
+
9
+ 1. Installed the gem:
10
+ ```bash
11
+ gem install dk_payment_gateway
12
+ ```
13
+
14
+ 2. Set up your environment variables in a `.env` file:
15
+ ```bash
16
+ DK_BASE_URL=http://internal-gateway.uat.digitalkidu.bt/api/dkpg
17
+ DK_API_KEY=your_api_key
18
+ DK_USERNAME=your_username
19
+ DK_PASSWORD=your_password
20
+ DK_CLIENT_ID=your_client_id
21
+ DK_CLIENT_SECRET=your_client_secret
22
+ DK_SOURCE_APP=SRC_AVS_0201
23
+ ```
24
+
25
+ 3. Install dotenv gem (optional, for loading .env files):
26
+ ```bash
27
+ gem install dotenv
28
+ ```
29
+
30
+ ## Examples
31
+
32
+ ### 1. Simple Payment (`simple_payment.rb`)
33
+
34
+ Demonstrates a complete pull payment flow:
35
+ - Authentication
36
+ - Payment authorization (sends OTP)
37
+ - OTP collection from user
38
+ - Payment completion with OTP
39
+
40
+ **Run:**
41
+ ```bash
42
+ ruby examples/simple_payment.rb
43
+ ```
44
+
45
+ **What it does:**
46
+ 1. Authenticates with the API
47
+ 2. Initiates a payment authorization for BTN 100.00
48
+ 3. Prompts for OTP
49
+ 4. Completes the payment
50
+
51
+ ### 2. Intra-Bank Transfer (`intra_transfer.rb`)
52
+
53
+ Demonstrates transferring funds between DK accounts:
54
+ - Account verification
55
+ - Fund transfer
56
+ - Transaction confirmation
57
+
58
+ **Run:**
59
+ ```bash
60
+ ruby examples/intra_transfer.rb
61
+ ```
62
+
63
+ **What it does:**
64
+ 1. Authenticates with the API
65
+ 2. Verifies beneficiary account
66
+ 3. Asks for confirmation
67
+ 4. Executes the transfer
68
+
69
+ ### 3. QR Code Generation (`generate_qr.rb`)
70
+
71
+ Demonstrates generating QR codes for payments:
72
+ - Static QR (customer enters amount)
73
+ - Dynamic QR (fixed amount)
74
+ - QR image saving
75
+
76
+ **Run:**
77
+ ```bash
78
+ ruby examples/generate_qr.rb
79
+ ```
80
+
81
+ **What it does:**
82
+ 1. Authenticates with the API
83
+ 2. Asks user to choose QR type
84
+ 3. Generates QR code
85
+ 4. Saves QR image to file
86
+
87
+ ## Customizing Examples
88
+
89
+ ### Changing Payment Amounts
90
+
91
+ Edit the amount variables in each script:
92
+
93
+ ```ruby
94
+ # In simple_payment.rb
95
+ amount = 100.00 # Change this
96
+ fee = 5.00 # Change this
97
+
98
+ # In intra_transfer.rb
99
+ amount = 500.00 # Change this
100
+ ```
101
+
102
+ ### Changing Account Numbers
103
+
104
+ Update the account numbers to match your test accounts:
105
+
106
+ ```ruby
107
+ # Beneficiary account
108
+ account_number: "110158212197" # Change this
109
+
110
+ # Remitter account
111
+ remitter_account_number: "770182571" # Change this
112
+ ```
113
+
114
+ ### Changing Bank Codes
115
+
116
+ Use different bank codes as needed:
117
+
118
+ ```ruby
119
+ remitter_bank_id: "1040" # 1010, 1040, 1060, etc.
120
+ ```
121
+
122
+ ## Error Handling
123
+
124
+ All examples include error handling. If you encounter errors:
125
+
126
+ 1. **Authentication Error**
127
+ - Check your credentials in .env file
128
+ - Verify API endpoint is accessible
129
+
130
+ 2. **Transaction Error**
131
+ - Check account numbers are valid
132
+ - Verify sufficient balance
133
+ - Ensure OTP is correct
134
+
135
+ 3. **Network Error**
136
+ - Check internet connection
137
+ - Verify API endpoint URL
138
+
139
+ ## Testing in Development
140
+
141
+ For testing without affecting real accounts:
142
+
143
+ 1. Use the UAT (User Acceptance Testing) environment
144
+ 2. Use test account numbers provided by DK
145
+ 3. Use small amounts for testing
146
+
147
+ ## Creating Your Own Examples
148
+
149
+ Use these examples as templates:
150
+
151
+ ```ruby
152
+ #!/usr/bin/env ruby
153
+ require 'bundler/setup'
154
+ require 'dk_payment_gateway'
155
+
156
+ # Configure
157
+ DkPaymentGateway.configure do |config|
158
+ config.base_url = ENV['DK_BASE_URL']
159
+ config.api_key = ENV['DK_API_KEY']
160
+ # ... other config
161
+ end
162
+
163
+ # Your code here
164
+ client = DkPaymentGateway.client
165
+ client.authenticate!
166
+
167
+ # Use the client
168
+ # ...
169
+ ```
170
+
171
+ ## Additional Resources
172
+
173
+ - [Main README](../README.md) - Complete documentation
174
+ - [Quick Start Guide](../QUICK_START.md) - Get started in 5 minutes
175
+ - [API Reference](../API_REFERENCE.md) - Detailed API documentation
176
+ - [Examples Guide](../EXAMPLES.md) - More usage examples
177
+
178
+ ## Support
179
+
180
+ If you encounter issues with these examples:
181
+
182
+ 1. Check the error message
183
+ 2. Review the documentation
184
+ 3. Verify your credentials
185
+ 4. Check account numbers and amounts
186
+ 5. Ensure you're using the correct environment (UAT/Production)
187
+
188
+ ## Security Note
189
+
190
+ ⚠️ **Never commit your `.env` file or credentials to version control!**
191
+
192
+ Add to your `.gitignore`:
193
+ ```
194
+ .env
195
+ .env.*
196
+ *.pem
197
+ *.key
198
+ ```
199
+
@@ -0,0 +1,110 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # QR code generation example using DK Payment Gateway
5
+ # This demonstrates generating both static and dynamic QR codes
6
+
7
+ require 'bundler/setup'
8
+ require 'dk_payment_gateway'
9
+
10
+ # Configure the client
11
+ DkPaymentGateway.configure do |config|
12
+ config.base_url = ENV['DK_BASE_URL'] || "http://internal-gateway.uat.digitalkidu.bt/api/dkpg"
13
+ config.api_key = ENV['DK_API_KEY']
14
+ config.username = ENV['DK_USERNAME']
15
+ config.password = ENV['DK_PASSWORD']
16
+ config.client_id = ENV['DK_CLIENT_ID']
17
+ config.client_secret = ENV['DK_CLIENT_SECRET']
18
+ config.source_app = ENV['DK_SOURCE_APP'] || "SRC_AVS_0201"
19
+ end
20
+
21
+ def main
22
+ puts "=== DK Payment Gateway - QR Code Generation Example ==="
23
+ puts
24
+
25
+ # Initialize client
26
+ client = DkPaymentGateway.client
27
+
28
+ # Authenticate
29
+ puts "Authenticating..."
30
+ client.authenticate!
31
+ puts "✓ Authentication successful"
32
+ puts
33
+
34
+ # Merchant details
35
+ merchant_account = "100100148337"
36
+
37
+ puts "Select QR type:"
38
+ puts "1. Static QR (customer enters amount)"
39
+ puts "2. Dynamic QR (fixed amount)"
40
+ print "Choice (1 or 2): "
41
+ choice = gets.chomp
42
+ puts
43
+
44
+ begin
45
+ case choice
46
+ when "1"
47
+ generate_static_qr(client, merchant_account)
48
+ when "2"
49
+ generate_dynamic_qr(client, merchant_account)
50
+ else
51
+ puts "Invalid choice"
52
+ end
53
+ rescue DkPaymentGateway::Error => e
54
+ puts "✗ Error: #{e.message}"
55
+ end
56
+ end
57
+
58
+ def generate_static_qr(client, merchant_account)
59
+ puts "Generating Static QR Code..."
60
+ puts " Merchant Account: #{merchant_account}"
61
+ puts " Amount: Customer will enter"
62
+ puts
63
+
64
+ response = client.qr_payment.generate_qr(
65
+ request_id: DkPaymentGateway::Utils.generate_request_id("QR"),
66
+ currency: "BTN",
67
+ bene_account_number: merchant_account,
68
+ amount: 0, # 0 = static QR
69
+ mcc_code: "5411", # Grocery store
70
+ remarks: "Payment to merchant"
71
+ )
72
+
73
+ filename = "static_qr_#{Time.now.to_i}.png"
74
+ client.qr_payment.save_qr_image(response['image'], filename)
75
+
76
+ puts "✓ Static QR code generated successfully!"
77
+ puts " Saved to: #{filename}"
78
+ puts " Customers can scan this QR and enter any amount"
79
+ end
80
+
81
+ def generate_dynamic_qr(client, merchant_account)
82
+ print "Enter amount (BTN): "
83
+ amount = gets.chomp.to_f
84
+ puts
85
+
86
+ puts "Generating Dynamic QR Code..."
87
+ puts " Merchant Account: #{merchant_account}"
88
+ puts " Amount: BTN #{DkPaymentGateway::Utils.format_amount(amount)}"
89
+ puts
90
+
91
+ response = client.qr_payment.generate_qr(
92
+ request_id: DkPaymentGateway::Utils.generate_request_id("QR"),
93
+ currency: "BTN",
94
+ bene_account_number: merchant_account,
95
+ amount: amount,
96
+ mcc_code: "5812", # Restaurant
97
+ remarks: "Invoice payment"
98
+ )
99
+
100
+ filename = "dynamic_qr_#{amount.to_i}_#{Time.now.to_i}.png"
101
+ client.qr_payment.save_qr_image(response['image'], filename)
102
+
103
+ puts "✓ Dynamic QR code generated successfully!"
104
+ puts " Saved to: #{filename}"
105
+ puts " Amount is fixed at BTN #{DkPaymentGateway::Utils.format_amount(amount)}"
106
+ end
107
+
108
+ # Run the example
109
+ main if __FILE__ == $PROGRAM_NAME
110
+
@@ -0,0 +1,114 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Intra-bank transfer example using DK Payment Gateway
5
+ # This demonstrates transferring funds between DK accounts
6
+
7
+ require 'bundler/setup'
8
+ require 'dk_payment_gateway'
9
+
10
+ # Configure the client
11
+ DkPaymentGateway.configure do |config|
12
+ config.base_url = ENV['DK_BASE_URL'] || "http://internal-gateway.uat.digitalkidu.bt/api/dkpg"
13
+ config.api_key = ENV['DK_API_KEY']
14
+ config.username = ENV['DK_USERNAME']
15
+ config.password = ENV['DK_PASSWORD']
16
+ config.client_id = ENV['DK_CLIENT_ID']
17
+ config.client_secret = ENV['DK_CLIENT_SECRET']
18
+ config.source_app = ENV['DK_SOURCE_APP'] || "SRC_AVS_0201"
19
+ end
20
+
21
+ def main
22
+ puts "=== DK Payment Gateway - Intra-Bank Transfer Example ==="
23
+ puts
24
+
25
+ # Initialize client
26
+ client = DkPaymentGateway.client
27
+
28
+ # Authenticate
29
+ puts "Authenticating..."
30
+ client.authenticate!
31
+ puts "✓ Authentication successful"
32
+ puts
33
+
34
+ # Transfer details
35
+ source_account = "100100365856"
36
+ beneficiary_account = "100100148337"
37
+ amount = 500.00
38
+
39
+ puts "Transfer Details:"
40
+ puts " From: #{source_account}"
41
+ puts " To: #{beneficiary_account}"
42
+ puts " Amount: BTN #{amount}"
43
+ puts
44
+
45
+ begin
46
+ # Step 1: Verify beneficiary account
47
+ puts "Step 1: Verifying beneficiary account..."
48
+
49
+ inquiry_response = client.intra_transaction.account_inquiry(
50
+ request_id: DkPaymentGateway::Utils.generate_request_id("INQ"),
51
+ amount: amount,
52
+ currency: "BTN",
53
+ bene_bank_code: "1060",
54
+ bene_account_number: beneficiary_account,
55
+ source_account_number: source_account
56
+ )
57
+
58
+ puts "✓ Account verified"
59
+ puts " Inquiry ID: #{inquiry_response['inquiry_id']}"
60
+ puts " Beneficiary Name: #{inquiry_response['account_name']}"
61
+ puts
62
+
63
+ # Step 2: Confirm transfer
64
+ print "Proceed with transfer? (yes/no): "
65
+ confirmation = gets.chomp.downcase
66
+
67
+ unless confirmation == 'yes' || confirmation == 'y'
68
+ puts "Transfer cancelled"
69
+ return
70
+ end
71
+ puts
72
+
73
+ # Step 3: Execute transfer
74
+ puts "Step 2: Executing transfer..."
75
+
76
+ transfer_response = client.intra_transaction.fund_transfer(
77
+ request_id: DkPaymentGateway::Utils.generate_request_id("TXN"),
78
+ inquiry_id: inquiry_response['inquiry_id'],
79
+ transaction_datetime: Time.now.utc.strftime("%Y-%m-%dT%H:%M:%SZ"),
80
+ transaction_amount: amount,
81
+ currency: "BTN",
82
+ payment_type: "INTRA",
83
+ source_account_number: source_account,
84
+ bene_cust_name: inquiry_response['account_name'],
85
+ bene_account_number: beneficiary_account,
86
+ bene_bank_code: "1060",
87
+ narration: "Test transfer"
88
+ )
89
+
90
+ puts "✓ Transfer completed successfully!"
91
+ puts " Transaction Status ID: #{transfer_response['txn_status_id']}"
92
+ puts
93
+
94
+ # Step 4: Verify transaction status
95
+ puts "Step 3: Verifying transaction status..."
96
+
97
+ # Wait a moment for transaction to process
98
+ sleep 2
99
+
100
+ # Note: You would use the actual transaction_id returned by the system
101
+ # This is just an example
102
+ puts "✓ Transfer processed"
103
+
104
+ rescue DkPaymentGateway::TransactionError => e
105
+ puts "✗ Transaction error: #{e.message}"
106
+ puts " Error code: #{e.response_code}"
107
+ rescue DkPaymentGateway::Error => e
108
+ puts "✗ Error: #{e.message}"
109
+ end
110
+ end
111
+
112
+ # Run the example
113
+ main if __FILE__ == $PROGRAM_NAME
114
+
@@ -0,0 +1,102 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Simple payment example using DK Payment Gateway
5
+ # This demonstrates a basic pull payment flow
6
+
7
+ require 'bundler/setup'
8
+ require 'dk_payment_gateway'
9
+
10
+ # Configure the client
11
+ DkPaymentGateway.configure do |config|
12
+ config.base_url = ENV['DK_BASE_URL'] || 'https://internal-gateway.uat.digitalkidu.bt'
13
+ config.api_key = ENV['DK_API_KEY']
14
+ config.username = ENV['DK_USERNAME']
15
+ config.password = ENV['DK_PASSWORD']
16
+ config.client_id = ENV['DK_CLIENT_ID']
17
+ config.client_secret = ENV['DK_CLIENT_SECRET']
18
+ config.source_app = ENV['DK_SOURCE_APP'] || 'SRC_AVS_0201'
19
+ end
20
+
21
+ def main
22
+ puts '=== DK Payment Gateway - Simple Payment Example ==='
23
+ puts
24
+
25
+ # Initialize client
26
+ client = DkPaymentGateway.client
27
+
28
+ # Authenticate
29
+ puts 'Authenticating...'
30
+ client.authenticate!
31
+ puts '✓ Authentication successful'
32
+ puts
33
+
34
+ # Payment details
35
+ amount = 100.00
36
+ fee = 5.00
37
+
38
+ puts 'Payment Details:'
39
+ puts " Amount: BTN #{amount}"
40
+ puts " Fee: BTN #{fee}"
41
+ puts " Total: BTN #{amount + fee}"
42
+ puts
43
+
44
+ # Step 1: Request authorization
45
+ puts 'Step 1: Requesting payment authorization...'
46
+
47
+ stan = DkPaymentGateway::PullPayment.generate_stan('0201')
48
+
49
+ begin
50
+ auth_response = client.pull_payment.authorize(
51
+ transaction_datetime: Time.now.utc.strftime('%Y-%m-%dT%H:%M:%SZ'),
52
+ stan_number: stan,
53
+ transaction_amount: amount,
54
+ transaction_fee: fee,
55
+ payment_desc: 'Test payment - Order #TEST001',
56
+ account_number: '110158212197',
57
+ account_name: 'Test Merchant',
58
+ phone_number: '17811440',
59
+ remitter_account_number: '770182571',
60
+ remitter_account_name: 'Test Customer',
61
+ remitter_bank_id: '1040'
62
+ )
63
+
64
+ puts '✓ Authorization successful'
65
+ puts " Transaction ID: #{auth_response['bfs_txn_id']}"
66
+ puts " STAN: #{auth_response['stan_number']}"
67
+ puts
68
+
69
+ # Step 2: Get OTP from user
70
+ puts "Step 2: OTP has been sent to customer's phone"
71
+ print 'Enter OTP: '
72
+ otp = gets.chomp
73
+ puts
74
+
75
+ # Step 3: Complete payment
76
+ puts 'Step 3: Completing payment with OTP...'
77
+
78
+ debit_response = client.pull_payment.debit(
79
+ request_id: DkPaymentGateway::Utils.generate_request_id('PAY'),
80
+ bfs_txn_id: auth_response['bfs_txn_id'],
81
+ bfs_remitter_otp: otp
82
+ )
83
+
84
+ if debit_response['code'] == '00'
85
+ puts '✓ Payment completed successfully!'
86
+ puts " Transaction ID: #{debit_response['bfs_txn_id']}"
87
+ puts " Status: #{debit_response['description']}"
88
+ else
89
+ puts '✗ Payment failed'
90
+ puts " Code: #{debit_response['code']}"
91
+ puts " Description: #{debit_response['description']}"
92
+ end
93
+ rescue DkPaymentGateway::TransactionError => e
94
+ puts "✗ Transaction error: #{e.message}"
95
+ puts " Error code: #{e.response_code}"
96
+ rescue DkPaymentGateway::Error => e
97
+ puts "✗ Error: #{e.message}"
98
+ end
99
+ end
100
+
101
+ # Run the example
102
+ main if __FILE__ == $PROGRAM_NAME
@@ -0,0 +1,102 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "uri"
4
+ require "securerandom"
5
+
6
+ module DkPaymentGateway
7
+ class Authentication
8
+ attr_reader :client
9
+
10
+ def initialize(client)
11
+ @client = client
12
+ end
13
+
14
+ # Fetch authorization token
15
+ # Returns the access token string
16
+ def fetch_token
17
+ response = client.post(
18
+ "/v1/auth/token",
19
+ body: token_request_body,
20
+ headers: token_request_headers,
21
+ skip_auth: true
22
+ )
23
+
24
+ validate_token_response!(response)
25
+
26
+ response["response_data"]["access_token"]
27
+ rescue => e
28
+ raise AuthenticationError, "Failed to fetch token: #{e.message}"
29
+ end
30
+
31
+ # Fetch RSA private key for signing requests
32
+ # Returns the private key as a string
33
+ def fetch_private_key
34
+ raise AuthenticationError, "Access token required to fetch private key" unless client.access_token
35
+
36
+ request_id = generate_request_id
37
+
38
+ response = client.post(
39
+ "/v1/sign/key",
40
+ body: {
41
+ request_id: request_id,
42
+ source_app: client.config.source_app
43
+ },
44
+ skip_auth: false
45
+ )
46
+
47
+ # The response is plain text containing the private key
48
+ if response.is_a?(String) && response.include?("BEGIN RSA PRIVATE KEY")
49
+ response
50
+ elsif response.is_a?(Hash) && response["response_code"] == "3001"
51
+ raise AuthenticationError, "Private key not found: #{response['response_detail']}"
52
+ else
53
+ raise AuthenticationError, "Invalid private key response"
54
+ end
55
+ rescue DkPaymentGateway::Error => e
56
+ raise
57
+ rescue => e
58
+ raise AuthenticationError, "Failed to fetch private key: #{e.message}"
59
+ end
60
+
61
+ private
62
+
63
+ def token_request_body
64
+ params = {
65
+ username: client.config.username,
66
+ password: client.config.password,
67
+ client_id: client.config.client_id,
68
+ client_secret: client.config.client_secret,
69
+ grant_type: "password",
70
+ scopes: "keys:read",
71
+ source_app: client.config.source_app,
72
+ request_id: generate_request_id
73
+ }
74
+
75
+ # Convert to URL-encoded format
76
+ URI.encode_www_form(params)
77
+ end
78
+
79
+ def token_request_headers
80
+ {
81
+ "Content-Type" => "application/x-www-form-urlencoded",
82
+ "X-gravitee-api-key" => client.config.api_key
83
+ }
84
+ end
85
+
86
+ def validate_token_response!(response)
87
+ unless response.is_a?(Hash) && response["response_code"] == "0000"
88
+ error_detail = response["response_detail"] || response["response_message"] || "Unknown error"
89
+ raise AuthenticationError, "Token request failed: #{error_detail}"
90
+ end
91
+
92
+ unless response["response_data"] && response["response_data"]["access_token"]
93
+ raise AuthenticationError, "No access token in response"
94
+ end
95
+ end
96
+
97
+ def generate_request_id
98
+ "#{Time.now.to_i}-#{SecureRandom.hex(8)}"
99
+ end
100
+ end
101
+ end
102
+