Webhook Format
JSON
This is the default format. We will send the payload exactly as it appears in the other pages of this documentation, which is a JSON object with a Content-Type of application/json
JWT (JSON Web Token)
This format is based on JSON Web Tokens and provides a mechanism by which messages can be verified to ensure that only messages coming Moneyhub can be accepted by your system. These messages will be encoded like a JWT and delivered with a Content-Type of application/jwt
Given the Payment Completed webhook, the JWT encoded version look something like the following:
eyJraWQiOiJEOUpBTm1ZZlNHX2tidDJLUnBUS283UUNOSDJfUkstMGE3ODd5am0wN3p3IiwiYWxnIjoiUlMyNTYifQ.eyJpc3MiOiJodHRwczovL2lkZW50aXR5LWRldi5tb25leWh1Yi5jby51ayIsImF1ZCI6ImQ5ZGM5ZDVlLWQxOTAtNDM4Yy1iNjU4LWE0YmUzNzc5MTAwZCIsImp0aSI6ImM5ZDEzM2UwLWU3MDgtNDAyZC1hNmI3LWRjOGZmOWMyOWExYyIsInN1YiI6IjVmNzVhOWY5NDdmOWJkNzRkOTIxYTZjOSIsImV2ZW50cyI6eyJ1cm46Y29tOm1vbmV5aHViOmV2ZW50czpwYXltZW50LWNvbXBsZXRlZCI6eyJwYXltZW50SWQiOiJkYzk0NDZlZS1hZmMxLTRiNDctYmFiNS0yYjAxYzdkYTA5ZTMiLCJzdGF0dXMiOiJjb21wbGV0ZWQiLCJwYXltZW50U3VibWlzc2lvbklkIjoiMmJlOGNiZTUtZTEzOC00M2M1LWJjNTgtNzYwY2VmYTg5MjQ4Iiwic3VibWl0dGVkQXQiOiIyMDIwLTEwLTAxVDEwOjA1OjQ1LjM3NFoifX0sImlhdCI6MTYwMTU0Njc4MX0.Fld7AM3ywFUXaZYA8uFoGyiWalRhvM8V24a_n0pahYs8o2YGVk-5DCBVNwGGJZT0LMchXiVAo5QeRvauqCv6BsApyycQiGTpAbX0l9V97FANGotB9KRuwstXqZ9tNo9a70-oNJGu8CDsBO2i-mmdNGsCW5QQNGH3z_TtwBq8fX5zYhulc7HMvZr93kfO-zMZUHdeUmUBnqeig0IdCIM-67H1WzAYZ_s86ZMuZLEj5m_VyNas5rbEox4B8GW6aDzQO0YsBbp5jXzfkR0NVNUSip5Q1kTDtK24YbUz9Pt_pmsGof6a_3pSOw_oEAWnHH-C3a4zKQvUBklb9YeGVPv4OQ
Once decoded the payload would look like:
{
"iss": "https://identity.moneyhub.co.uk",
"aud": "d9dc9d5e-d190-438c-b658-a4be3779100d",
"jti": "c9d133e0-e708-402d-a6b7-dc8ff9c29a1c",
"sub": "5f75a9f947f9bd74d921a6c9",
"events": {
"urn:com:moneyhub:events:payment-completed": {
"paymentId": "dc9446ee-afc1-4b47-bab5-2b01c7da09e3",
"status": "completed",
"paymentSubmissionId": "2be8cbe5-e138-43c5-bc58-760cefa89248",
"submittedAt": "2020-10-01T10:05:45.374Z"
}
},
"iat": 1601546781
}
You'll need to use a JWT library to decode and verify the messages
While you can decode the messages without verifying them, it's better to do both at the same time. In order to verify the message you'll need to retrieve our public signing key
The key is subject to change over time without notice so don't keep it as a static resource
Here is a example written in Node where we retrieve the public signing key to verify the webhook messages:
const got = require("got")
const {JWKS} = require("jose")
const getPublicMoneyhubKeyAsPEM = async () => {
try {
const {jwks_uri} = await got("https://identity.moneyhub.co.uk/oidc/.well-known/openid-configuration").json()
const jwks = await got(jwks_uri).json()
const signingKey = JWKS.asKeyStore(jwks).get({use: "sig"})
console.log(signingKey.toPEM())
} catch (e) {
console.error(e)
}
}
getPublicMoneyhubKeyAsPEM()
This could then be extended to verify and decode the message like so:
const got = require("got")
const {JWKS,JWT} = require("jose")
const decodeAndVerifyMessage = async (message) => {
try {
const {jwks_uri} = await got("https://identity.moneyhub.co.uk/oidc/.well-known/openid-configuration").json()
const jwks = await got(jwks_uri).json()
const signingKey = JWKS.asKeyStore(jwks).get({use: "sig"})
const payload = JWT.verify(message, signingKey)
console.log(payload)
} catch (e) {
console.error("Failed to verify the message", e)
}
}
decodeAndVerifyMessage(message)
Updated 4 months ago