fix : qr code generation to be dynamic

This commit is contained in:
aungthetkhaing
2025-05-22 15:19:54 +06:30
parent 138d62a9f5
commit eec8b3c600
4 changed files with 136 additions and 64 deletions

View File

@@ -213,33 +213,38 @@ class Foodcourt::QrpayController < BaseFoodcourtController
end
end
qr_str = "00020101021226480015com.mmqrpay.www0115223743000377032020600000052045814530310454075000.005802MM5908Code2LAB6006Yangon61051101062730125ORDER_1747826957_5ae9cb900523MMQR1075L175919500000010813PAY_BY_QRCODE64300002MY0109ကုဒ်တူလက်0207ရန်ကုန်6304AD40";
@string_to_encode = qr_str
@paymethod = PaymentMethodSetting.find_by(payment_method: "MMQR")
qrcode = RQRCode::QRCode.new(@string_to_encode)
@qr_svg = qrcode.as_svg(
color: "000", # Hex color for the QR code modules (black)
shape_rendering: "crispEdges", # Renders sharp edges
module_size: 2, # Size of each module (dot/square)
standalone: true, # Outputs a complete SVG document
use_path: true # Modern SVG path rendering
)
@merchant = KbzMerchant.new(@paymethod)
png_data = qrcode.as_png(
bit_depth: 1,
border_modules: 4,
color_mode: ChunkyPNG::COLOR_GRAYSCALE,
color: 'black',
file: nil,
fill: 'white',
module_px_size: 8, # Pixel size of each module
resize_exactly_to: false,
resize_gte_to: false,
size: 240 # Approximate size of the image in pixels (e.g., 240x240)
).to_s
@response = @merchant.create_order(amount: @sale_data.grand_total, merch_order_id: @sale_data.receipt_no)
@qr_string = @response['qrCode']
ActionCable.server.broadcast('second_display_view_channel', { data: qr_str, qr_svg: @qr_svg })
qrcode = RQRCode::QRCode.new(@qr_string)
@qr_svg = qrcode.as_svg(
color: "000",
shape_rendering: "crispEdges",
module_size: 2,
standalone: true,
use_path: true
)
# png_data = qrcode.as_png(
# bit_depth: 1,
# border_modules: 4,
# color_mode: ChunkyPNG::COLOR_GRAYSCALE,
# color: 'black',
# file: nil,
# fill: 'white',
# module_px_size: 8, # Pixel size of each module
# resize_exactly_to: false,
# resize_gte_to: false,
# size: 240 # Approximate size of the image in pixels (e.g., 240x240)
# ).to_s
ActionCable.server.broadcast('second_display_view_channel', { data: @qr_string, qr_svg: @qr_svg })
end
end
end

View File

@@ -5,20 +5,18 @@ class KbzMerchant
def initialize(payment_method)
@payment_method = payment_method
@api_url = payment_method.test_mode? ?
'http://api.kbzpay.com/payment/gateway/uat/precreate' :
'https://api.kbzpay.com/payment/gateway/precreate'
@api_url ='http://api.kbzpay.com/payment/gateway/uat/precreate'
end
def create_order(transaction_params)
payload = build_payload(transaction_params)
def create_order(amount:, merch_order_id:)
payload = build_payload(amount, merch_order_id)
response = send_request(payload)
handle_response(response)
end
private
def build_payload(params)
def build_payload(amount, merch_order_id, timeout='120m')
base_params = {
method: 'kbz.payment.precreate',
timestamp: Time.now.utc.to_i.to_s,
@@ -27,13 +25,13 @@ class KbzMerchant
sign_type: 'SHA256',
version: '1.0',
biz_content: {
appid: @payment_method.appid,
merch_code: @payment_method.merch_code,
merch_order_id: params[:merch_order_id],
appid: @payment_method.gateway_url,
merch_code: @payment_method.merchant_account_id,
merch_order_id: merch_order_id,
trade_type: 'PAY_BY_QRCODE',
total_amount: params[:total_amount].to_s,
total_amount: amount.to_s,
trans_currency: 'MMK',
timeout_express: params[:timeout] || '120m'
timeout_express: timeout || '120m'
}.compact
}
@@ -53,11 +51,10 @@ class KbzMerchant
end
def generate_signature(flattened_params)
key = 'uatfoodcourt@12'
sorted_params = flattened_params.except('sign', 'sign_type').sort
string_a = sorted_params.map { |k, v| "#{k}=#{v}" }.join('&')
puts "String a: #{string_a}"
string_to_sign = "#{string_a}&key=#{key}"
string_to_sign = "#{string_a}&key=#{@payment_method.auth_token}"
puts "String to sign: #{string_to_sign}"
Digest::SHA256.hexdigest(string_to_sign).upcase
end
@@ -78,8 +75,8 @@ class KbzMerchant
body: { Request: payload }.to_json,
timeout: 15
)
puts "Response: #{response}"
response.body
# puts "Response: #{response}"
rescue HTTParty::Error => e
raise PaymentError, "HTTP error: #{e.message}"
rescue SocketError => e
@@ -89,7 +86,7 @@ class KbzMerchant
def handle_response(response)
json_response = JSON.parse(response.body)
json_response = JSON.parse(response)
if json_response.dig('Response', 'result') == 'SUCCESS'
json_response['Response']
else

View File

@@ -1,57 +1,125 @@
<div class="row clearfix h-100">
<div class="col-lg-6 col-md-6 col-sm-6 h-100">
<div class="card h-100" style="opacity: 0.75;">
<div class="card h-100" style="opacity: 0.85; background-color: #f8f9fa;">
<div class="card-header bg-primary text-white">
<h4 class="mb-0">Invoice Details</h4>
</div>
<div class="card-block h-100">
<div class="card-text">
<div id="order-detail-slimscroll" data-height="190">
<div id="order-detail-slimscroll" style="max-height: 60vh; overflow-y: auto;">
<table class="table table-striped second_display_items" id="order-items-table">
<thead>
<thead class="thead-light">
<tr>
<th>#</th>
<th class="item-name">Items</th>
<th class="item-">QTY</th>
<th class="item-">Price</th>
<th class="item-qty">QTY</th>
<th class="item-price">Price</th>
</tr>
</thead>
<tbody>
<!-- Items will be populated here -->
</tbody>
</table>
</div>
</div>
</div>
<div class="card-footer">
<table class="table" border="0">
<div class="card-footer bg-light">
<table class="table table-borderless">
<tr>
<td class="charges-name"><strong>Sub Total:</strong></td>
<td></td>
<td></td>
<td class="item-attr"><strong id="s_sub_total">0.00</strong></td>
<td class="text-right item-attr"><strong id="s_sub_total">0.00</strong></td>
</tr>
<tr>
<td class="charges-name"><strong>Discount Amount:</strong></td>
<td></td>
<td></td>
<td class="item-attr"><strong id="s_total_discount">0.00</strong></td>
<td class="charges-name"><strong>Discount:</strong></td>
<td class="text-right item-attr"><strong id="s_total_discount">0.00</strong></td>
</tr>
<tr>
<td class="charges-name"><strong>Tax Amount:</strong></td>
<td></td>
<td></td>
<td class="item-attr"><strong id="s_tatal_tax">0.00</strong></td>
<td class="text-right item-attr"><strong id="s_tatal_tax">0.00</strong></td>
</tr>
<tr>
<td class="charges-name"><strong>Grand:</strong></td>
<td></td>
<td></td>
<td class="item-attr"><strong id="s_grand_total">0.00</strong></td>
<tr class="table-active">
<td class="charges-name"><strong>Grand Total:</strong></td>
<td class="text-right item-attr"><strong id="s_grand_total">0.00</strong></td>
</tr>
</table>
</div>
</div>
</div>
<div class="col-lg-6 col-md-6 col-sm-6 h-100">
<div id="qrpay_svg" style="background-color: #ddd;">
<div class="col-lg-6 col-md-6 col-sm-6 h-100 d-flex flex-column">
<div class="card h-100" style="opacity: 0.85;">
<div class="card-header text-white" style="background-color: #ffc107;">
<h4 class="mb-0">Payment Options</h4>
</div>
<div class="card-body d-flex flex-column align-items-center justify-content-center">
<div class="text-center mb-4">
<h5>Scan to Pay</h5>
<p class="text-muted">Use your mobile wallet app</p>
</div>
<!-- QR Code Container -->
<div id="qr-payment-container" class="text-center p-3 bg-white rounded border" style="max-width: 300px;">
<div id="qr-code" class="mb-2">
<!-- QR Code will be generated here -->
<div class="">
<div id="qrpay_svg">
</div>
</div>
</div>
<div class="payment-details">
<p class="mb-1"><strong>Amount:</strong> <span id="qr-amount"><%= number_to_currency(@total_amount) %></span></p>
<p class="mb-1"><strong>Invoice #:</strong> <span id="qr-invoice"><%= @invoice_id %></span></p>
<p class="text-muted small">Expires in 15 minutes</p>
</div>
</div>
<div class="payment-instructions mt-4 text-center">
<h6>How to Pay:</h6>
<ol class="text-left small pl-3">
<li>Open your mobile wallet app</li>
<li>Tap on 'Scan QR Code'</li>
<li>Point your camera at this code</li>
<li>Confirm the payment details</li>
</ol>
</div>
</div>
</div>
</div>
</div>
<style>
/* Add these styles to your existing CSS */
.card {
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
border: none;
border-radius: 8px;
}
.card-header {
border-radius: 8px 8px 0 0 !important;
padding: 12px 20px;
}
.table thead th {
border-bottom: 2px solid #dee2e6;
}
#qr-payment-container {
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.payment-instructions {
background-color: #f8f9fa;
padding: 15px;
border-radius: 8px;
max-width: 300px;
}
.text-right {
text-align: right;
}
.table-active {
background-color: rgba(0,0,0,0.05);
}
</style>

View File

@@ -677,6 +677,8 @@ scope "(:locale)", locale: /en|mm/ do
get 'sale/:sale_id' => 'sales#show'
get 'order/:order_id' => "orders#show"
get 'qrpay/payment_loading' => 'qrpay#payment_loading'
# Other Charges
get "/:sale_id/:type/other_charges" => "other_charges#index"
post "/:sale_id/other_charges" => "other_charges#create"