-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscript.js
More file actions
112 lines (96 loc) · 3.75 KB
/
Copy pathscript.js
File metadata and controls
112 lines (96 loc) · 3.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
document.getElementById('generateBtn').addEventListener('click', generateQR);
document.getElementById('copyBtn').addEventListener('click', copyToClipboard);
// Set default timestamp to current time
const now = new Date();
now.setMinutes(now.getMinutes() - now.getTimezoneOffset());
document.getElementById('timestamp').value = now.toISOString().slice(0, 19);
function generateQR() {
const sellerName = document.getElementById('sellerName').value.trim();
const vatNumber = document.getElementById('vatNumber').value.trim();
let timestamp = document.getElementById('timestamp').value;
const invoiceTotal = document.getElementById('invoiceTotal').value.trim();
const vatTotal = document.getElementById('vatTotal').value.trim();
if (!sellerName || !vatNumber || !timestamp || !invoiceTotal || !vatTotal) {
alert('Please fill in all fields');
return;
}
// Format timestamp to YYYY-MM-DDTHH:MM:SSZ if needed, or keep as is.
// datetime-local gives YYYY-MM-DDTHH:MM:SS
// ZATCA often expects 'Z' at the end if it's UTC, or just the string.
// Let's ensure it has seconds and append 'Z' to match the previous default format for consistency,
// assuming the user wants to treat the picked time as the invoice time.
// A simple approach is to just ensure it looks like an ISO string.
if (timestamp.length === 16) {
timestamp += ':00'; // Add seconds if missing
}
if (!timestamp.endsWith('Z')) {
timestamp += 'Z'; // Append Z to indicate ISO format (UTC)
}
// 1. Seller Name
const tag1 = getTLV(1, sellerName);
// 2. VAT Registration Number
const tag2 = getTLV(2, vatNumber);
// 3. Time Stamp
const tag3 = getTLV(3, timestamp);
// 4. Invoice Total
const tag4 = getTLV(4, invoiceTotal);
// 5. VAT Total
const tag5 = getTLV(5, vatTotal);
// Concatenate all TLV buffers
const allTags = concatenateBuffers([tag1, tag2, tag3, tag4, tag5]);
// Base64 Encode
const base64 = arrayBufferToBase64(allTags);
// Display
const outputSection = document.getElementById('outputSection');
const textarea = document.getElementById('qrOutput');
outputSection.classList.remove('hidden');
textarea.value = base64;
}
function getTLV(tag, value) {
const encoder = new TextEncoder();
const valBytes = encoder.encode(value);
const length = valBytes.length;
// Tag is 1 byte
const tagByte = new Uint8Array([tag]);
// Length is 1 byte (assuming < 256 for this simple app)
const lenByte = new Uint8Array([length]);
return concatenateBuffers([tagByte, lenByte, valBytes]);
}
function concatenateBuffers(arrays) {
let totalLength = 0;
for (const arr of arrays) {
totalLength += arr.length;
}
const result = new Uint8Array(totalLength);
let offset = 0;
for (const arr of arrays) {
result.set(arr, offset);
offset += arr.length;
}
return result;
}
function arrayBufferToBase64(buffer) {
let binary = '';
const bytes = new Uint8Array(buffer);
const len = bytes.byteLength;
for (let i = 0; i < len; i++) {
binary += String.fromCharCode(bytes[i]);
}
return window.btoa(binary);
}
function copyToClipboard() {
const textarea = document.getElementById('qrOutput');
textarea.select();
document.execCommand('copy'); // Fallback for older browsers or non-secure contexts
// Modern API
if (navigator.clipboard) {
navigator.clipboard.writeText(textarea.value).then(() => {
const btn = document.getElementById('copyBtn');
const originalText = btn.innerText;
btn.innerText = 'Copied!';
setTimeout(() => {
btn.innerText = originalText;
}, 2000);
});
}
}