API Reference - SpankPay Developer Documentation
Sat Sep 10 2022 19:28:12 GMT+0000 (Coordinated Universal Time)
Saved by @JohnnyBGoode
javascript tab="Javascript (manually)" const crypto = require('crypto') const crypto = require('crypto') /** * Decodes a SpankPay webhook, returning a triple of: * [data, timestamp, error] * * Where `data` is the webhook object, and `timestamp` is the * call's timestamp (integer seconds since epoch, UTC). * * If an error is encountered (for example, because the * signature is invalid), `error` will be a non-null * string describing the error. * * For example: * const [data, timestamp, error] = decodeSpankPayWebhook( * process.env.SPANKPAY_API_SECRET, * req.headers['x-spankpay-signature'], * req.body, * ) */ function decodeSpankPayWebhook(secret, sig, data) { if (!data || data.slice(0, 1) != '{') { const msg = ( `Empty or non-JSON webhook data: ` + JSON.stringify(shorten(data)) ) return [null, null, msg] } const sigData = {} sig.split('&').forEach(bit => { const [key, val] = bit.split('=') sigData[key] = val }) const timestamp = parseInt(sigData.t) if (!isFinite(timestamp)) return [null, null, `Invalid or missing timestamp: ${sig}`] const hash = crypto.createHmac('sha256', secret) hash.update(`${timestamp}.${data}`) const actualSig = hash.digest('hex') if (sigData.s !== actualSig) return [null, null, `Invalid signature. ${sigData.s} !== ${actualSig}`] let dataObj try { dataObj = JSON.parse(data) } catch (e) { return [null, null, `Error decoding JSON: ${'' + e}`] } return [dataObj, timestamp, null] } function shorten(s, len) { if (!len) len = 16 if (!s || s.length <= len) return s return s.slice(0, len / 2) + '…' + s.slice(s.length - len / 2) } function signSpankPayData(secret, data, t) { if (t === undefined) t = parseInt(Date.now() / 1000) const hash = crypto.createHmac('sha256', secret) hash.update(`${t}.${data}`) return `t=${t}&s=${hash.digest('hex')}` } if (typeof require !== 'undefined' && require.main == module) { const secret = 'sk_spankpay' const data = '{"SpankPay": "BOOTY"}' const sig = signSpankPayData(secret, data, 696969) console.log(`Signing '${data}' with secret key '${secret}': ${sig}`) examples = [ ["correctly signed", sig, data], ["missing timestamp", "", data], ["missing signature", "t=696969", data], ["invalid signature", "t=696969&s=invalid", data], ["invalid data", sig, '{"invalid": true}'], ["empty data", sig, null], ["non-JSON data", sig, "invalid"], ] for (const [name, sig, data] of examples) { console.log(`Decoding ${name}:`, decodeSpankPayWebhook(secret, sig, data)) } }
Comments