-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(notification): setup adyen notifications
- Loading branch information
1 parent
1160d76
commit 98ee30d
Showing
5 changed files
with
132 additions
and
35 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import { Notification } from '@adyen/api-library/lib/src/typings/notification/notification'; | ||
|
||
export type PaymentNotificationSchemaDTO = Notification; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,36 +1,24 @@ | ||
import { SessionAuthenticationHook } from '@commercetools/connect-payments-sdk'; | ||
import { FastifyInstance, FastifyPluginOptions } from 'fastify'; | ||
import { | ||
PaymentRequestSchema, | ||
PaymentRequestSchemaDTO, | ||
PaymentResponseSchema, | ||
PaymentResponseSchemaDTO, | ||
} from '../dtos/mock-payment.dto'; | ||
import { MockPaymentService } from '../services/mock-payment.service'; | ||
import { PaymentNotificationSchemaDTO } from '../dtos/adyen-payment.dts'; | ||
import { AdyenPaymentService } from '../services/adyen-payment.service'; | ||
|
||
const ACK_NOTIFICATION = '[accepted]'; | ||
|
||
type PaymentRoutesOptions = { | ||
paymentService: MockPaymentService; | ||
paymentService: AdyenPaymentService; | ||
sessionAuthHook: SessionAuthenticationHook; | ||
}; | ||
|
||
export const paymentRoutes = async (fastify: FastifyInstance, opts: FastifyPluginOptions & PaymentRoutesOptions) => { | ||
fastify.post<{ Body: PaymentRequestSchemaDTO; Reply: PaymentResponseSchemaDTO }>( | ||
'/payments', | ||
{ | ||
preHandler: [opts.sessionAuthHook.authenticate()], | ||
schema: { | ||
body: PaymentRequestSchema, | ||
response: { | ||
200: PaymentResponseSchema, | ||
}, | ||
}, | ||
}, | ||
async (request, reply) => { | ||
const resp = await opts.paymentService.createPayment({ | ||
data: request.body, | ||
}); | ||
/** | ||
* Listen to the notification from Adyen | ||
*/ | ||
fastify.post<{ Body: PaymentNotificationSchemaDTO; Reply: any }>('/notifications', {}, async (request, reply) => { | ||
await opts.notificationService.processNotification({ | ||
data: request.body, | ||
}); | ||
|
||
return reply.status(200).send(resp); | ||
}, | ||
); | ||
return reply.status(200).send(ACK_NOTIFICATION); | ||
}); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,22 +1,42 @@ | ||
import { CommercetoolsCartService, CommercetoolsPaymentService } from '@commercetools/connect-payments-sdk'; | ||
import { NotificationConverter } from './converters/notification.converter'; | ||
import { ProcessNotification as ProcessNotificationRequest } from './types/adyen-payment.type'; | ||
import { hmacValidator } from '@adyen/api-library'; | ||
import { config } from '../config/config'; | ||
|
||
import { PaymentNotification } from './types/adyen-payment.type'; | ||
|
||
export type MockPaymentServiceOptions = { | ||
export type AdyenPaymentServiceOptions = { | ||
ctCartService: CommercetoolsCartService; | ||
ctPaymentService: CommercetoolsPaymentService; | ||
notificationConverter: NotificationConverter; | ||
}; | ||
|
||
export class MockPaymentService { | ||
export class AdyenPaymentService { | ||
private ctCartService: CommercetoolsCartService; | ||
private ctPaymentService: CommercetoolsPaymentService; | ||
private notificationConverter: NotificationConverter; | ||
|
||
constructor(opts: MockPaymentServiceOptions) { | ||
constructor(opts: AdyenPaymentServiceOptions) { | ||
this.ctCartService = opts.ctCartService; | ||
this.ctPaymentService = opts.ctPaymentService; | ||
this.notificationConverter = opts.notificationConverter; | ||
} | ||
|
||
public async processNotification(opts: ProcessNotificationRequest): Promise<void> { | ||
await this.validateHmac(opts); | ||
const updateData = await this.notificationConverter.convert(opts); | ||
await this.ctPaymentService.updatePayment(updateData); | ||
} | ||
|
||
public async processNotification(opts: PaymentNotification): Promise<void> { | ||
// TODO | ||
private async validateHmac(opts: ProcessNotificationRequest): Promise<void> { | ||
if (!opts.data.notificationItems || opts.data.notificationItems.length === 0) { | ||
//TODO: throw an error 401 | ||
} | ||
|
||
const validator = new hmacValidator(); | ||
const item = opts.data.notificationItems[0].NotificationRequestItem; | ||
|
||
if (!validator.validateHMAC(item, config.adyenHMACKey)) { | ||
//TODO: throw an error 401 | ||
} | ||
} | ||
} |
84 changes: 84 additions & 0 deletions
84
processor/src/services/converters/notification.converter.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
import { Money } from '@commercetools/platform-sdk'; | ||
|
||
import { NotificationRequestItem } from '@adyen/api-library/lib/src/typings/notification/notificationRequestItem'; | ||
|
||
import { ProcessNotification } from '../types/adyen-payment.type'; | ||
import { TransactionData, UpdatePayment } from '@commercetools/connect-payments-sdk'; | ||
|
||
export class NotificationConverter { | ||
constructor() {} | ||
|
||
public async convert(opts: ProcessNotification): Promise<UpdatePayment> { | ||
const item = opts.data.notificationItems[0].NotificationRequestItem; | ||
|
||
return { | ||
id: item.merchantReference, | ||
pspReference: item.pspReference, | ||
transaction: this.populateTransaction(item), | ||
}; | ||
} | ||
|
||
private populateTransaction(item: NotificationRequestItem): TransactionData { | ||
switch (item.eventCode) { | ||
case NotificationRequestItem.EventCodeEnum.Authorisation: | ||
return { | ||
type: 'Authorization', | ||
state: item.success ? 'Success' : 'Failure', | ||
amount: this.populateAmount(item), | ||
interactionId: item.pspReference, | ||
}; | ||
case NotificationRequestItem.EventCodeEnum.Capture: | ||
return { | ||
type: 'Charge', | ||
state: 'Failure', | ||
amount: this.populateAmount(item), | ||
interactionId: item.pspReference, | ||
}; | ||
case NotificationRequestItem.EventCodeEnum.CaptureFailed: | ||
return { | ||
type: 'Charge', | ||
state: 'Failure', | ||
amount: this.populateAmount(item), | ||
interactionId: item.pspReference, | ||
}; | ||
case NotificationRequestItem.EventCodeEnum.Cancellation: | ||
return { | ||
type: 'CancelAuthorization', | ||
state: item.success ? 'Success' : 'Failure', | ||
amount: this.populateAmount(item), | ||
interactionId: item.pspReference, | ||
}; | ||
case NotificationRequestItem.EventCodeEnum.Refund: | ||
return { | ||
type: 'Refund', | ||
state: item.success ? 'Success' : 'Failure', | ||
amount: this.populateAmount(item), | ||
interactionId: item.pspReference, | ||
}; | ||
case NotificationRequestItem.EventCodeEnum.RefundFailed: | ||
return { | ||
type: 'Refund', | ||
state: 'Failure', | ||
amount: this.populateAmount(item), | ||
interactionId: item.pspReference, | ||
}; | ||
case NotificationRequestItem.EventCodeEnum.Chargeback: | ||
return { | ||
type: 'Chargeback', | ||
state: 'Success', | ||
amount: this.populateAmount(item), | ||
interactionId: item.pspReference, | ||
}; | ||
default: | ||
//TODO: throw unsupported notification error | ||
throw new Error('Unsupported notification'); | ||
} | ||
} | ||
|
||
private populateAmount(item: NotificationRequestItem): Money { | ||
return { | ||
centAmount: item.amount.value as number, | ||
currencyCode: item.amount.currency as string, | ||
}; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
import { Notification } from '@adyen/api-library/lib/src/typings/notification/notification'; | ||
import { PaymentNotificationSchemaDTO } from '../../dtos/adyen-payment.dts'; | ||
|
||
export type PaymentNotification = Notification; | ||
export type ProcessNotification = { | ||
data: PaymentNotificationSchemaDTO; | ||
}; |