diff --git a/typescript/src/soft-opt-ins/processSubscription.ts b/typescript/src/soft-opt-ins/processSubscription.ts index e363bb27f..b8e5fdb77 100644 --- a/typescript/src/soft-opt-ins/processSubscription.ts +++ b/typescript/src/soft-opt-ins/processSubscription.ts @@ -1,10 +1,11 @@ -import {dynamoMapper, sendToSqs, sendToSqsComms, sendToSqsSoftOptIns, SoftOptInEvent} from "../utils/aws"; +import {dynamoMapper, sendToSqs, sendToSqsComms, sendToSqsSoftOptIns, SoftOptInEvent, SoftOptInEventProductName} from "../utils/aws"; import {ReadSubscription} from "../models/subscription"; import {Region, Stage} from "../utils/appIdentity"; import fetch from 'node-fetch'; import { Response } from 'node-fetch'; import {getIdentityApiKey, getIdentityUrl, getMembershipAccountId} from "../utils/guIdentityApi"; import {plusDays} from "../utils/dates"; +import { Platform } from "../models/platform"; export function isPostAcquisition(startTimestamp: string): boolean { const twoDaysInMilliseconds = 48 * 60 * 60 * 1000; @@ -52,11 +53,22 @@ async function getUserEmailAddress(identityId: string, identityApiKey: string): } } -async function sendSoftOptIns(identityId: string, subscriptionId: string, queueNamePrefix: string) { +const mapPlatformToSoftOptInProductName = (platform: string | undefined): SoftOptInEventProductName => { + switch (platform) { + case Platform.IosFeast: + return "FeastInAppPurchase"; + default: + return "InAppPurchase"; + } +}; + +async function sendSoftOptIns(identityId: string, subscriptionId: string, platform: string | undefined, queueNamePrefix: string) { + const productName = mapPlatformToSoftOptInProductName(platform); + const message: SoftOptInEvent = { identityId: identityId, eventType: "Acquisition", - productName: "InAppPurchase", + productName, subscriptionId: subscriptionId }; @@ -90,7 +102,7 @@ export async function processAcquisition(subscriptionRecord: ReadSubscription, i const queueNamePrefix = `https://sqs.${Region}.amazonaws.com/${membershipAccountId}`; try { - await sendSoftOptIns(identityId, subscriptionId, queueNamePrefix); + await sendSoftOptIns(identityId, subscriptionId, subscriptionRecord.platform, queueNamePrefix); } catch (e) { handleError(`Soft opt-in message send failed for subscriptionId: ${subscriptionId}. ${e}`) } @@ -118,4 +130,4 @@ export async function processAcquisition(subscriptionRecord: ReadSubscription, i } return true; -} \ No newline at end of file +} diff --git a/typescript/src/utils/aws.ts b/typescript/src/utils/aws.ts index 01d907369..8095616bd 100644 --- a/typescript/src/utils/aws.ts +++ b/typescript/src/utils/aws.ts @@ -136,10 +136,11 @@ export function sendToSqs(queueUrl: string, event: any, delaySeconds?: number): }).promise() } +export type SoftOptInEventProductName = "InAppPurchase" | "FeastInAppPurchase"; export interface SoftOptInEvent { identityId: string; eventType: "Acquisition" | "Cancellation" | "Switch"; - productName: "InAppPurchase"; + productName: SoftOptInEventProductName subscriptionId: string; } @@ -158,4 +159,4 @@ export async function sendToSqsComms(queueUrl: string, event: any, delaySeconds? MessageBody: JSON.stringify(event), DelaySeconds: delaySeconds }).promise(); -} \ No newline at end of file +} diff --git a/typescript/tests/soft-opt-ins/acquisition.test.ts b/typescript/tests/soft-opt-ins/acquisition.test.ts index eb2a48289..7892d1c89 100644 --- a/typescript/tests/soft-opt-ins/acquisition.test.ts +++ b/typescript/tests/soft-opt-ins/acquisition.test.ts @@ -2,6 +2,7 @@ import {isPostAcquisition} from "../../src/soft-opt-ins/processSubscription"; import {handler} from "../../src/soft-opt-ins/acquisitions"; import {DynamoDBStreamEvent} from "aws-lambda"; import {ReadSubscription} from "../../src/models/subscription"; +import { Platform } from "../../src/models/platform"; jest.mock('@aws/dynamodb-data-mapper', () => { const actualDataMapper = jest.requireActual('@aws/dynamodb-data-mapper'); @@ -165,6 +166,47 @@ describe('handler', () => { expect(mockSQS.sendMessage).toHaveBeenCalledWith(expectedSendMessageParams1); }); + it('processes Feast acquisitions correctly', async () => { + const subscriptionId = '11111'; + const identityId = '22222'; + const event: DynamoDBStreamEvent = { + Records: [ + { + eventName: 'INSERT', + dynamodb: { + NewImage: { + subscriptionId: { S: subscriptionId }, + userId: { S: identityId }, + }, + }, + }, + ] + }; + // get the mock instances + const mockDataMapper = new (require('@aws/dynamodb-data-mapper').DataMapper)(); + const mockSQS = new (require('aws-sdk/clients/sqs'))(); + const sub = new ReadSubscription(); + sub.subscriptionId = subscriptionId; + sub.startTimestamp = "2023-03-14 07:24:38 UTC"; + sub.endTimestamp = "2023-03-14 07:24:38 UTC"; + sub.platform = Platform.IosFeast; + setMockGet(() => sub); + + await handler(event); + + expect(mockDataMapper.get).toHaveBeenCalledTimes(1); + let expectedQuery = new ReadSubscription(); + expectedQuery.setSubscriptionId(subscriptionId) + expect(mockDataMapper.get).toHaveBeenCalledWith(expectedQuery); + + expect(mockSQS.sendMessage).toHaveBeenCalledTimes(1); + const expectedSendMessageParams1 = { + QueueUrl: `https://sqs.eu-west-1.amazonaws.com/mock-aws-account-id/soft-opt-in-consent-setter-queue-DEV`, + MessageBody: JSON.stringify({ identityId, eventType: 'Acquisition', productName: "FeastInAppPurchase", subscriptionId }), + }; + expect(mockSQS.sendMessage).toHaveBeenCalledWith(expectedSendMessageParams1); + }); + it('should process a post acquisition sign-in correctly', async () => { fetch.mockResolvedValue({ ok: true, @@ -229,4 +271,4 @@ describe('handler', () => { expect(mockSQS.sendMessage).toHaveBeenCalledWith(expectedSendMessageParams1); }); -}); \ No newline at end of file +});