Finee
// ====== CONFIG HELPERS ======
function CFG_(k, def){ return PropertiesService.getScriptProperties().getProperty(k) || def || ''; }
function respondJson_(obj, status){
var out = ContentService.createTextOutput(JSON.stringify(obj)).setMimeType(ContentService.MimeType.JSON);
if (status) out.setHeader('X-Status', String(status)); // Apps Script cannot set HTTP status code directly
return out;
}
// ====== ENTRYPOINTS ======
function doPost(e){
try{
var body = e.postData && e.postData.contents ? e.postData.contents : '{}';
var req = JSON.parse(body);
if (req.action === 'verify_and_fulfill') return verifyAndFulfill_(req);
return respondJson_({error:'Unknown action'}, 400);
}catch(err){
return respondJson_({error:String(err)}, 500);
}
}
// ====== VERIFY WITH PAYSTACK & (OPTIONAL) FULFILL ======
function verifyAndFulfill_(req){
var reference = req.reference;
if (!reference) return respondJson_({error:'Missing reference'}, 400);
var sk = CFG_('PAYSTACK_SECRET_KEY');
if (!sk) return respondJson_({error:'Server not configured: missing secret key'}, 500);
// 1) Verify transaction
var verifyUrl = 'https://api.paystack.co/transaction/verify/' + encodeURIComponent(reference);
var vr = UrlFetchApp.fetch(verifyUrl, {
method: 'get',
headers: { 'Authorization': 'Bearer ' + sk, 'Accept':'application/json' },
muteHttpExceptions: true
});
var vStatus = vr.getResponseCode();
var vText = vr.getContentText();
var vJson = tryParseJson_(vText);
if (vStatus !== 200 || !vJson || vJson.status !== true || !vJson.data || vJson.data.status !== 'success'){
logOrder_(reference, req, 'verification_failed', vJson);
return respondJson_({ok:false, step:'verify', upstream_code:vStatus, upstream:vJson}, vStatus);
}
// 2) Optional: auto-fulfill (call your provider to send the data bundle)
var fulfilled = false, fulfillResp = null;
var hubKey = CFG_('HUBNET_API_KEY','');
var hubUrl = CFG_('HUBNET_PURCHASE_URL',''); // set this to your provider purchase endpoint
if (hubKey && hubUrl && req.phone && req.network && req.bundle){
try{
// EXAMPLE: adjust fields to match your provider’s API (this is a placeholder)
var payload = {
phone: req.phone,
network: req.network,
bundle: req.bundle,
amount_ghs: req.amount_ghs,
pay_reference: reference
};
var fr = UrlFetchApp.fetch(hubUrl, {
method: 'post',
contentType: 'application/json',
headers: { 'Accept':'application/json', 'token': 'Bearer ' + hubKey },
payload: JSON.stringify(payload),
muteHttpExceptions: true
});
fulfillResp = {code: fr.getResponseCode(), body: tryParseJson_(fr.getContentText())};
fulfilled = (fr.getResponseCode() >= 200 && fr.getResponseCode() < 300);
}catch(e){
fulfillResp = {error:String(e)};
}
}
// 3) Log the order to a Google Sheet for records
logOrder_(reference, req, fulfilled ? 'fulfilled' : 'verified_only', {verify:vJson, fulfill:fulfillResp});
// 4) Respond to the client
return respondJson_({ok:true, verified:true, fulfilled:fulfilled, verify:vJson, fulfill:fulfillResp}, 200);
}
// ====== UTILITIES ======
function tryParseJson_(t){ try{ return JSON.parse(t); }catch(e){ return {raw:t}; } }
function logOrder_(reference, req, status, meta){
try{
var ss = SpreadsheetApp.getActiveSpreadsheet() || SpreadsheetApp.create('BuyData Orders');
var sh = ss.getSheetByName('orders') || ss.insertSheet('orders');
if (sh.getLastRow() === 0){
sh.appendRow(['timestamp','reference','name','email','phone','network','bundle','amount_ghs','status','meta_json']);
}
sh.appendRow([
new Date(), reference, req.name||'', req.email||'', req.phone||'', req.network||'',
req.bundle||'', req.amount_ghs||'', status, JSON.stringify(meta||{})
]);
}catch(e){
// Swallow errors silently
}
}
Comments
Post a Comment