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

Popular posts from this blog

Ladies Here Are Astounding And Classy Short Gowns You Can Add To Your Wardrobe.