@@ -9,6 +9,8 @@ import { getRemoteAddress } from '../../utils/http'
99import { hmacSha256 } from '../../utils/secret'
1010import { IController } from '../../@types/controllers'
1111import { IPaymentsService } from '../../@types/services'
12+ import { opennodeWebhookCallbackBodySchema } from '../../schemas/opennode-callback-schema'
13+ import { validateSchema } from '../../utils/validation'
1214
1315const debug = createLogger ( 'opennode-callback-controller' )
1416
@@ -22,12 +24,6 @@ export class OpenNodeCallbackController implements IController {
2224 response : Response ,
2325 ) {
2426 debug ( 'request headers: %o' , request . headers )
25- debug (
26- 'request body metadata: hasId=%s hasHashedOrder=%s status=%s' ,
27- typeof request . body ?. id === 'string' ,
28- typeof request . body ?. hashed_order === 'string' ,
29- typeof request . body ?. status === 'string' ? request . body . status : 'missing' ,
30- )
3127
3228 const settings = createSettings ( )
3329 const remoteAddress = getRemoteAddress ( request , settings )
@@ -41,22 +37,24 @@ export class OpenNodeCallbackController implements IController {
4137 return
4238 }
4339
44- const validStatuses = [ 'expired' , 'refunded' , 'unpaid' , 'processing' , 'underpaid' , 'paid' ]
45-
46- if (
47- ! request . body
48- || typeof request . body . id !== 'string'
49- || typeof request . body . hashed_order !== 'string'
50- || typeof request . body . status !== 'string'
51- || ! validStatuses . includes ( request . body . status )
52- ) {
40+ const bodyValidation = validateSchema ( opennodeWebhookCallbackBodySchema ) ( request . body )
41+ if ( bodyValidation . error ) {
42+ debug ( 'opennode callback request rejected: invalid body %o' , bodyValidation . error )
5343 response
5444 . status ( 400 )
5545 . setHeader ( 'content-type' , 'text/plain; charset=utf8' )
56- . send ( 'Bad Request ' )
46+ . send ( 'Malformed body ' )
5747 return
5848 }
5949
50+ const body = bodyValidation . value
51+ debug (
52+ 'request body metadata: hasId=%s hasHashedOrder=%s status=%s' ,
53+ typeof body . id === 'string' ,
54+ typeof body . hashed_order === 'string' ,
55+ body . status ,
56+ )
57+
6058 const openNodeApiKey = process . env . OPENNODE_API_KEY
6159 if ( ! openNodeApiKey ) {
6260 debug ( 'OPENNODE_API_KEY is not configured; unable to verify OpenNode callback from %s' , remoteAddress )
@@ -67,8 +65,8 @@ export class OpenNodeCallbackController implements IController {
6765 return
6866 }
6967
70- const expectedBuf = hmacSha256 ( openNodeApiKey , request . body . id )
71- const actualHex = request . body . hashed_order
68+ const expectedBuf = hmacSha256 ( openNodeApiKey , body . id )
69+ const actualHex = body . hashed_order
7270 const expectedHexLength = expectedBuf . length * 2
7371
7472 if (
@@ -105,8 +103,8 @@ export class OpenNodeCallbackController implements IController {
105103 }
106104
107105 const invoice : Pick < Invoice , 'id' | 'status' > = {
108- id : request . body . id ,
109- status : statusMap [ request . body . status ] ,
106+ id : body . id ,
107+ status : statusMap [ body . status ] ,
110108 }
111109
112110 debug ( 'invoice' , invoice )
0 commit comments