Skip to content

Commit

Permalink
DEVEXP-523: E2E Verification/Callbacks (#131)
Browse files Browse the repository at this point in the history
  • Loading branch information
asein-sinch authored Sep 23, 2024
1 parent b0071d9 commit bc4cd2a
Show file tree
Hide file tree
Showing 8 changed files with 103 additions and 13 deletions.
7 changes: 2 additions & 5 deletions examples/webhooks/src/services/verification-event.service.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
import { Injectable } from '@nestjs/common';
import { Response } from 'express';
import {
Verification,
VerificationCallback,
} from '@sinch/sdk-core';
import { Verification } from '@sinch/sdk-core';

@Injectable()
export class VerificationEventService {

handleEvent(event: VerificationCallback, res: Response) {
handleEvent(event: Verification.VerificationCallbackEvent, res: Response) {
console.log(`:: INCOMING EVENT :: ${event.event}`);
switch (event.event) {
case 'VerificationRequestEvent':
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Given('the Conversation service "Contacts" is available', function () {
contactsApi = conversationService.contact;
});

When('I send a request to create an contact', async () => {
When('I send a request to create a contact', async () => {
contact = await contactsApi.create({
contactCreateRequestBody: {
channel_identities: [
Expand Down
2 changes: 0 additions & 2 deletions packages/verification/src/models/v1/identity/identity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,4 @@ export interface Identity {
type: 'number';
/** For type `number` use an [E.164](https://community.sinch.com/t5/Glossary/E-164/ta-p/7537)-compatible phone number. */
endpoint: string;
/** */
verified?: boolean;
}
1 change: 1 addition & 0 deletions packages/verification/src/models/v1/mod-callbacks/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './verification-callback-event';
// 'Verification Request Event' received from Sinch server
export * from './verification-request-event';
// Response to send to Sinch server for a 'Verification Request Event'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { VerificationRequestEvent } from './verification-request-event';
import { VerificationResultEvent } from './verification-result-event';

export type VerificationCallbackEvent = VerificationRequestEvent | VerificationResultEvent;
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export type { VerificationRequestEvent } from './verification-request-event';
export type { VerificationRequestEvent, MethodEnum } from './verification-request-event';
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { VerificationRequestEvent, VerificationResultEvent } from '../../../models';
import { VerificationCallbackEvent, VerificationRequestEvent, VerificationResultEvent } from '../../../models';
import { CallbackProcessor, SinchClientParameters, validateAuthenticationHeader } from '@sinch/sdk-client';
import { IncomingHttpHeaders } from 'http';

/** @deprecated - use Verification.VerificationCallback instead */
export type VerificationCallback = VerificationRequestEvent | VerificationResultEvent;

export class VerificationCallbackWebhooks implements CallbackProcessor<VerificationCallback>{
export class VerificationCallbackWebhooks implements CallbackProcessor<VerificationCallbackEvent>{

private readonly sinchClientParameters: SinchClientParameters;

Expand Down Expand Up @@ -39,9 +40,9 @@ export class VerificationCallbackWebhooks implements CallbackProcessor<Verificat
* Reviver for a Verification Event.
* This method ensures the object can be treated as a Verification Event and should be called before any action is taken to manipulate the object.
* @param {any} eventBody - The event body containing the verification event notification.
* @return {VerificationCallback} - The parsed verification event object.
* @return {VerificationCallbackEvent} - The parsed verification event object.
*/
public parseEvent(eventBody: any): VerificationCallback {
public parseEvent(eventBody: any): VerificationCallbackEvent {
if (eventBody.event) {
switch (eventBody.event) {
case 'VerificationRequestEvent':
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import { VerificationCallbackWebhooks, Verification } from '../../../../src';
import { Given, Then, When } from '@cucumber/cucumber';
import assert from 'assert';
import { IncomingHttpHeaders } from 'http';

let verificationCallbackWebhook: VerificationCallbackWebhooks;
let rawEvent: any;
let event: Verification.VerificationCallbackEvent;
let formattedHeaders: IncomingHttpHeaders;

const processEvent = async (response: Response) => {
formattedHeaders = {};
response.headers.forEach((value, name) => {
formattedHeaders[name.toLowerCase()] = value;
});
rawEvent = await response.text();
event = verificationCallbackWebhook.parseEvent(JSON.parse(rawEvent));
};

Given('the Verification Webhooks handler is available', () => {
verificationCallbackWebhook = new VerificationCallbackWebhooks({
applicationKey: 'appKey',
applicationSecret: 'appSecret',
});
});

When('I send a request to trigger a "Verification Request" event', async () => {
const response = await fetch('http://localhost:3018/webhooks/verification/verification-request-event');
await processEvent(response);
});

Then('the header of the Verification event "Verification Request" contains a valid authorization', () => {
assert.ok(verificationCallbackWebhook.validateAuthenticationHeader(
formattedHeaders,
rawEvent,
'/webhooks/verification',
'POST'));
});

Then('the Verification event describes a "Verification Request" event type', () => {
const verificationRequestEvent = event as Verification.VerificationRequestEvent;
assert.equal(verificationRequestEvent.id, '1ce0ffee-c0de-5eed-d00d-f00dfeed1337');
assert.equal(verificationRequestEvent.event, 'VerificationRequestEvent');
const smsVerificationMethod: Verification.MethodEnum = 'sms';
assert.equal(verificationRequestEvent.method, smsVerificationMethod);
const identity: Verification.Identity = {
type: 'number',
endpoint: '+33612345678',
};
assert.equal(verificationRequestEvent.identity.type, identity.type);
assert.equal(verificationRequestEvent.identity.endpoint, identity.endpoint);
const smsPrice: Verification.Price = {
currencyId: 'EUR',
amount: 0.0453,
};
assert.deepEqual(verificationRequestEvent.price, smsPrice);
const smsRate: Verification.Price = {
currencyId: 'EUR',
amount: 0,
};
assert.deepEqual(verificationRequestEvent.rate, smsRate);
});

When('I send a request to trigger a "Verification Result" event', async () => {
const response = await fetch('http://localhost:3018/webhooks/verification/verification-result-event');
await processEvent(response);
});

Then('the header of the Verification event "Verification Result" contains a valid authorization', () => {
assert.ok(verificationCallbackWebhook.validateAuthenticationHeader(
formattedHeaders,
rawEvent,
'/webhooks/verification',
'POST'));
});

Then('the Verification event describes a "Verification Result" event type', () => {
const verificationRequestEvent = event as Verification.VerificationResultEvent;
assert.equal(verificationRequestEvent.id, '1ce0ffee-c0de-5eed-d00d-f00dfeed1337');
assert.equal(verificationRequestEvent.event, 'VerificationResultEvent');
const smsVerificationMethod: Verification.MethodEnum = 'sms';
assert.equal(verificationRequestEvent.method, smsVerificationMethod);
const identity: Verification.Identity = {
type: 'number',
endpoint: '+33612345678',
};
assert.equal(verificationRequestEvent.identity.type, identity.type);
assert.equal(verificationRequestEvent.identity.endpoint, identity.endpoint);
});

0 comments on commit bc4cd2a

Please sign in to comment.