// --- DB init (ensure these fields exist when creating DB) ---
db.exec(`CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
email TEXT UNIQUE,
phone TEXT,
stripe_session_id TEXT,
paid INTEGER DEFAULT 0,
latitude REAL,
longitude REAL,
location_accuracy REAL,
location_timestamp TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);`);
// --- New route to accept location submissions (consent-based) ---
app.post('/submit-location', bodyParser.json(), (req, res) => {
// Expect { email, phone, latitude, longitude, accuracy, timestamp }
const { email, phone, latitude, longitude, accuracy, timestamp } = req.body;
if (!email && !phone) {
return res.status(400).json({ error: 'email or phone required' });
}
if (typeof latitude !== 'number' || typeof longitude !== 'number') {
return res.status(400).json({ error: 'latitude and longitude must be numbers' });
}
try {
// Upsert user record (keeps paid flag if exists)
const upsert = db.prepare(`
INSERT INTO users(email, phone, latitude, longitude, location_accuracy, location_timestamp)
VALUES(?, ?, ?, ?, ?, ?)
ON CONFLICT(email) DO UPDATE SET
phone = excluded.phone,
latitude = excluded.latitude,
longitude = excluded.longitude,
location_accuracy = excluded.location_accuracy,
location_timestamp = excluded.location_timestamp
`);
// If email is absent, we try to match by phone
if (email) {
upsert.run(email, phone || null, latitude, longitude, accuracy || null, timestamp || null);
} else {
// No email provided: insert with phone as unique key — simple fallback
const stmtPhone = db.prepare(`
INSERT OR REPLACE INTO users(id, email, phone, latitude, longitude, location_accuracy, location_timestamp)
VALUES(
COALESCE((SELECT id FROM users WHERE phone = ?), NULL),
NULL, ?, ?, ?, ?, ?
)
`);
stmtPhone.run(phone, phone, latitude, longitude, accuracy || null, timestamp || null);
}
return res.json({ ok: true });
} catch (err) {
console.error('submit-location error', err);
return res.status(500).json({ error: 'server error' });
}
});
// helper to post JSON
async function postJson(url, data){
const res = await fetch(url, {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(data)
});
return res.json();
}
document.getElementById('payForm').addEventListener('submit', async (e) => {
e.preventDefault();
const email = document.getElementById('email').value;
const phone = document.getElementById('phone').value;
// Ask for geolocation permission
if (!('geolocation' in navigator)) {
document.getElementById('msg').innerText = 'Geolocation not supported by this browser.';
return;
}
document.getElementById('msg').innerText = 'Requesting location permission...';
navigator.geolocation.getCurrentPosition(async (pos) => {
const { latitude, longitude, accuracy } = pos.coords;
const ts = new Date(pos.timestamp).toISOString();
// send location to server (consent-based)
try {
await postJson('/submit-location', {
email: email || null,
phone: phone || null,
latitude: Number(latitude),
longitude: Number(longitude),
accuracy: Number(accuracy || 0),
timestamp: ts
});
document.getElementById('msg').innerText = 'Location sent to server (with your permission). Proceeding to payment...';
} catch (err) {
console.error(err);
document.getElementById('msg').innerText = 'Failed to send location to server.';
return;
}
// After location is saved, proceed with payment creation as before
try {
const res = await fetch('/create-checkout-session', {
method: 'POST',
headers: {'Content-Type':'application/json'},
body: JSON.stringify({ email, phone })
});
const data = await res.json();
if (data.url) {
window.location = data.url;
} else {
document.getElementById('msg').innerText = 'Failed to start payment';
}
} catch (err) {
console.error(err);
document.getElementById('msg').innerText = 'Payment start failed';
}
}, (error) => {
// permission denied or other error
console.error('geolocation error', error);
document.getElementById('msg').innerText = 'Location permission denied or failed. You can still proceed.';
// optionally continue to payment even if user denies:
// (call create-checkout-session here if you want)
}, {
enableHighAccuracy: true,
timeout: 10000,
maximumAge: 0
});
});
0 Comments