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