-
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.
Merge pull request #8 from commercetools/ddeliziact/initial_setup
feat(operations): basic operation implementation
- Loading branch information
Showing
12 changed files
with
345 additions
and
2 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
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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
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,14 @@ | ||
import { Client, CheckoutAPI } from '@adyen/api-library'; | ||
import { config } from '../../config/config'; | ||
|
||
export const AdyenAPI = (): CheckoutAPI => { | ||
const apiClient = new Client({ | ||
apiKey: config.adyenApiKey, | ||
environment: config.adyenEnvironment.toUpperCase() as Environment, | ||
...(config.adyenLiveUrlPrefix && { | ||
liveEndpointUrlPrefix: config.adyenLiveUrlPrefix, | ||
}), | ||
}); | ||
|
||
return new CheckoutAPI(apiClient); | ||
}; |
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
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 |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { SessionAuthenticationHook } from '@commercetools/connect-payments-sdk'; | ||
import { FastifyInstance, FastifyPluginOptions } from 'fastify'; | ||
import { PaymentNotificationSchemaDTO } from '../dtos/adyen-payment.dts'; | ||
import { AdyenPaymentService } from '../services/adyen-payment.service'; | ||
|
||
const ACK_NOTIFICATION = '[accepted]'; | ||
|
||
type PaymentRoutesOptions = { | ||
paymentService: AdyenPaymentService; | ||
sessionAuthHook: SessionAuthenticationHook; | ||
}; | ||
|
||
export const paymentRoutes = async (fastify: FastifyInstance, opts: FastifyPluginOptions & PaymentRoutesOptions) => { | ||
/** | ||
* 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(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 |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { FastifyInstance } from 'fastify'; | ||
import { paymentSDK } from '../../payment-sdk'; | ||
import { paymentRoutes } from '../../routes/mock-payment.route'; | ||
import { MockPaymentService } from '../../services/mock-payment.service'; | ||
|
||
export default async function (server: FastifyInstance) { | ||
const mockPaymentService = new MockPaymentService({ | ||
ctCartService: paymentSDK.ctCartService, | ||
ctPaymentService: paymentSDK.ctPaymentService, | ||
}); | ||
|
||
await server.register(paymentRoutes, { | ||
paymentService: mockPaymentService, | ||
sessionAuthHook: paymentSDK.sessionAuthHookFn, | ||
}); | ||
} |
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,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'; | ||
|
||
export type AdyenPaymentServiceOptions = { | ||
ctCartService: CommercetoolsCartService; | ||
ctPaymentService: CommercetoolsPaymentService; | ||
notificationConverter: NotificationConverter; | ||
}; | ||
|
||
export class AdyenPaymentService { | ||
private ctCartService: CommercetoolsCartService; | ||
private ctPaymentService: CommercetoolsPaymentService; | ||
private notificationConverter: NotificationConverter; | ||
|
||
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); | ||
} | ||
|
||
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, | ||
}; | ||
} | ||
} |
Oops, something went wrong.