diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 6161a01..d6ccf6e 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -36,7 +36,7 @@ jobs: "instanceArn": "placeholder", "securityKeyId": "placeholder", "securityKeyCertificateContent": "-----BEGIN CERTIFICATE-----\\n-----END CERTIFICATE-----\\n", - "workspaceApp": true, + "addAppsToWorkspace": true, "receiptQueueArn": "placeholder" }, "c3": { @@ -48,7 +48,8 @@ jobs: "agentAssistedIVR": true, "agentAssistedLink": true, "selfServiceIVR": true, - "subjectLookup": "required-editable" + "subjectLookup": "required-editable", + "receiptApp": true }, "options": { "codeSigning": true, diff --git a/.vscode/settings.json b/.vscode/settings.json index 69463db..6ed2a7d 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -9,6 +9,7 @@ "Popout", "Runtimes", "Softphone", + "SSML", "Tokenizes", "Visualforce", "Zift" diff --git a/bin/c3-amazon-connect.ts b/bin/c3-amazon-connect.ts index 085835d..19fb01e 100644 --- a/bin/c3-amazon-connect.ts +++ b/bin/c3-amazon-connect.ts @@ -32,7 +32,7 @@ async function getMostRecentGitTag(): Promise { return stdout.trim(); } catch (error) { console.error('Error fetching the most recent git tag:', error); - return 'v2.1.0'; + return 'v3.0.0'; } } diff --git a/cdk.context.json b/cdk.context.json index 6b0ef2c..edf7ff5 100644 --- a/cdk.context.json +++ b/cdk.context.json @@ -4,7 +4,7 @@ "instanceArn": "", "securityKeyId": "", "securityKeyCertificateContent": "", - "workspaceApp": true, + "addAppsToWorkspace": true, "receiptQueueArn": "" }, "c3": { @@ -16,7 +16,8 @@ "agentAssistedIVR": true, "agentAssistedLink": true, "selfServiceIVR": true, - "subjectLookup": "" + "subjectLookup": "", + "receiptApp": true }, "options": { "codeSigning": true, diff --git a/docs/ALTERNATIVE_IMPORT.md b/docs/ALTERNATIVE_IMPORT.md index 332a869..b32edcd 100644 --- a/docs/ALTERNATIVE_IMPORT.md +++ b/docs/ALTERNATIVE_IMPORT.md @@ -11,7 +11,7 @@ It might be necessary to use the alternative import method in the following inst - This prevents even your _root_ user from having ECR permissions and they cannot be added. > [!TIP] -> If you are using Salesforce Service Cloud Voice, ensure that the `amazonConnect.workspaceApp` and `options.codeSigning` values are set to `false` in your `cdk.context.json` file. Your account will not have the necessary permissions for these items. +> If you are using Salesforce Service Cloud Voice, ensure that the `amazonConnect.addAppsToWorkspace` and `options.codeSigning` values are set to `false` in your `cdk.context.json` file. Your account will not have the necessary permissions for these items. ## Initial Deployment diff --git a/docs/GETTING-STARTED.md b/docs/GETTING-STARTED.md index 0128bc1..06b93d3 100644 --- a/docs/GETTING-STARTED.md +++ b/docs/GETTING-STARTED.md @@ -7,6 +7,8 @@ Before getting started with C3 for Amazon Connect, please ensure the following: - You have a current C3 vendor account - You have an AWS account - You have an Amazon Connect instance +- You are able to run commands from a bash terminal + - If you are using Windows, you can use the [Windows Subsystem for Linux](https://docs.microsoft.com/en-us/windows/wsl/install) to run bash commands. - You have Node.js (v20+) and npm (v10+) installed on your machine - You have [installed and configured the AWS CDK](https://docs.aws.amazon.com/cdk/v2/guide/getting_started.html#getting_started_auth) on your machine @@ -53,7 +55,7 @@ In order to facilitate this process, you will need to provide some values to the | `instanceArn` | The full ARN of your Amazon Connect Instance. You can find this in the AWS console and it should look something like `"arn:aws:connect:us-west-2:815407490078:instance/5c1f1fba-d5f1-4155-9e09-496456e58912"`. | | `securityKeyId` | The ID of the security key that you configured for your Amazon Connect instance. You can find this in the AWS console. | | `securityKeyCertificateContent` | The full content of the certificate associated with your Amazon Connect security key. Begins with `-----BEGIN CERTIFICATE-----` and ends with`-----END CERTIFICATE-----`. **Note**: This must be contained within a single string with newlines denoted with `\\n`. | -| `workspaceApp` | Whether to create the C3 Payment Request app for the Amazon Connect agent workspace. Defaults to `true`. You may want to set this to `false` if you plan to use the workspace through another interface, like Salesforce. **Note**: This option does nothing if no agent-assisted features are enabled. | +| `addAppsToWorkspace` | Whether to add third-party apps to the Amazon Connect agent workspace. Defaults to `true`. You may want to set this to `false` if you plan to use the workspace apps through another interface, like Salesforce. | | `receiptQueueArn` | **Optional**. The full ARN of the Amazon Connect queue to transfer to when there is no email present for the customer and they would like a receipt. This is only valid for self-service payments. If not provided, the customer will not be asked to transfer to an agent and will simply not receive a receipt. | ##### C3 @@ -72,6 +74,7 @@ In order to facilitate this process, you will need to provide some values to the | `agentAssistedLink` | **Currently unsupported**. This feature will be coming soon. | | `selfServiceIVR` | Determines whether or not to deploy resources necessary to support a self-service payment IVR. Defaults to `true`. If set to `false`, some resources will not be deployed.

For more information, see the [self-service payment IVR](./features/SELF_SERVICE_PAYMENT_IVR.md) documentation. | | `subjectLookup` | **Optional**. Additional feature for agent-assisted IVR payments. If set, this will allow the agent to pull details about the subject to pre-fill information in the payment request (contact name, contact email, and amount due). Valid options are `"required-fixed"`, `"required-editable"`, and `"optional-editable"`. Leave blank if you don't want to support subject lookup.

For more information, see the [subject lookup](./features/SUBJECT_LOOKUP.md) documentation. | +| `receiptApp` | Determines whether or not to deploy resources to allow agents to send a receipt. Defaults to `true`. If set to `false`, some resources will not be deployed, and agents will not be able to send a receipt to a customer if the email was not already provided. | ##### Options diff --git a/docs/features/SALESFORCE_INTEGRATION.md b/docs/features/SALESFORCE_INTEGRATION.md index 1b52544..73796ac 100644 --- a/docs/features/SALESFORCE_INTEGRATION.md +++ b/docs/features/SALESFORCE_INTEGRATION.md @@ -19,13 +19,13 @@ C3 for Amazon connect can be used within Salesforce to provide agents with a sea When you deployed resources to your AWS account through this project, a unique URL was generated for your agent workspace. After running `npm run synth` or `npm run deploy`, you will see this URL output in the console. It will look something like: ```bash -๐ŸŒ Your C3 Payment Request app URL is: +๐Ÿ’ฐ Your C3 Payment Request app URL is: -https://some-vendor.call2action.link/agent-workspace?contactCenter=amazon&instanceId=some-guid®ion=some-region&externalRoleArn=${Token[TOKEN.261]}&subjectLookup=required-editable&customEmbed=true +๐ŸŒhttps://some-vendor.call2action.link/agent-workspace/payment-request?contactCenter=amazon&instanceId=some-guid®ion=some-region&externalRoleArn=${Token[TOKEN.261]}&subjectLookup=required-editable&customEmbed=true ``` > [!TIP] -> You can also find this URL at any time by looking at the `exports/C3WorkspaceAppUrl.txt` file. +> You can also find this URL at any time by looking at the `exports/C3PaymentRequestAppUrl.txt` file. Replace the `${Token[TOKEN.261]}` value with the ARN of the IAM role that was created when you deployed the stack. Look in IAM for a role named "AmazonConnectExternalRole", copy the ARN, and replace the placeholder in the URL. @@ -73,6 +73,21 @@ Optionally, you can repeat the same steps on the "Mobile Navigation" tab to add Your app page is now ready for use! Verify that your agents can see the new app page in their navigation items. +### Create Receipt App + +If you enabled the receipt app feature, you will need to create a second Visualforce page and app page for the receipt app. Follow the same steps as above, but use the receipt app URL instead of the payment request app URL. + +```bash +๐Ÿงพ Your C3 Receipt app URL is: + +๐ŸŒhttps://some-vendor.call2action.link/agent-workspace/receipt?contactCenter=amazon&instanceId=some-guid®ion=some-region&externalRoleArn=${Token[TOKEN.261]}&customEmbed=true +``` + +> [!TIP] +> You can also find this URL at any time by looking at the `exports/C3ReceiptAppUrl.txt` file. + +Replace the `${Token[TOKEN.261]}` value with the ARN of the IAM role that was created when you deployed the stack. Look in IAM for a role named "AmazonConnectExternalRole", copy the ARN, and replace the placeholder in the URL. + ### Configure Amazon Connect Integration This step will vary depending on how you have Amazon Connect integrated with Salesforce. Please follow the appropriate guide below: diff --git a/lib/c3-amazon-connect-stack.ts b/lib/c3-amazon-connect-stack.ts index 0d39328..d7b46a0 100644 --- a/lib/c3-amazon-connect-stack.ts +++ b/lib/c3-amazon-connect-stack.ts @@ -33,6 +33,7 @@ import { validateOptionsContext, } from './models'; import { writeFileToExports } from './helpers/file'; +import { ReceiptApp } from './features/receipt-app'; export class C3AmazonConnectStack extends Stack { private c3BaseUrl: string; @@ -142,9 +143,25 @@ export class C3AmazonConnectStack extends Stack { this.featuresContext.agentAssistedIVR || this.featuresContext.agentAssistedLink ) { - const appUrl = this.getAppUrl(!this.amazonConnectContext.workspaceApp); - if (this.amazonConnectContext.workspaceApp) { - this.create3rdPartyApp(appUrl); + const paymentRequestAppUrl = this.getPaymentRequestAppUrl( + !this.amazonConnectContext.addAppsToWorkspace, + ); + if (this.amazonConnectContext.addAppsToWorkspace) { + this.createPaymentRequestApp(paymentRequestAppUrl); + } + + // Create resources needed for agent-assisted receipt app. + if (this.featuresContext.receiptApp) { + new ReceiptApp( + this, + this.stackLabel, + this.amazonConnectContext, + this.sendReceiptFunction, + this.agentAssistedIVRResources?.sendAgentMessageFunction, + this.agentAssistedIVRResources?.hoursOfOperation, + this.agentAssistedIVRResources?.iamRole?.roleArn, + this.c3AppUrlFragment, + ); } } } @@ -471,8 +488,8 @@ export class C3AmazonConnectStack extends Stack { * This app is required in order for an agent to initiate a payment while on a call with a customer. Once created, it will show as * an app in the agent workspace. NOTE: You will also have to enable this app to viewed on the security profile for your agents. */ - private create3rdPartyApp(appUrl: string): void { - console.log('Creating 3rd party application...'); + private createPaymentRequestApp(appUrl: string): void { + console.log('Creating payment request application...'); // Create the app. const stackLabelTitleCase = @@ -480,7 +497,7 @@ export class C3AmazonConnectStack extends Stack { const appLabel = this.stackLabel ? ` - ${stackLabelTitleCase}` : ''; const application = new CfnApplication( this, - `C3ConnectApp${stackLabelTitleCase}`, + `C3ConnectPaymentRequestApp${stackLabelTitleCase}`, { name: 'Payment Request' + appLabel, // App name is unfortunately required to be unique to create. namespace: `c3-payment-${this.stackLabel}`, @@ -495,12 +512,24 @@ export class C3AmazonConnectStack extends Stack { }, ); + // Workaround to delete the existing associations. Necessary when the naming format changes. + const skipAssociations = + this.node.tryGetContext('options').skipAssociations; + if (skipAssociations) { + console.log('โš ๏ธ Skipping Amazon Connect associations! โš ๏ธ'); + return; + } + // Associate the app with the Amazon Connect instance. - new CfnIntegrationAssociation(this, `C3ConnectIntegrationApp`, { - instanceId: this.amazonConnectContext.instanceArn, - integrationType: 'APPLICATION', - integrationArn: application.attrApplicationArn, - }); + new CfnIntegrationAssociation( + this, + `C3ConnectPaymentRequestIntegrationApp`, + { + instanceId: this.amazonConnectContext.instanceArn, + integrationType: 'APPLICATION', + integrationArn: application.attrApplicationArn, + }, + ); } /** @@ -509,7 +538,7 @@ export class C3AmazonConnectStack extends Stack { * @param customEmbed Whether to use a custom embed URL for the app. * @returns The URL for the app. */ - private getAppUrl(customEmbed: boolean): string { + private getPaymentRequestAppUrl(customEmbed: boolean): string { const instanceId = this.amazonConnectContext.instanceArn.split('/')[1]; // Set params for IVR features. @@ -535,10 +564,10 @@ export class C3AmazonConnectStack extends Stack { configuredFeatureParams += '&customEmbed=true'; } - const appUrl = `https://${this.c3Context.vendorId}.${this.c3AppUrlFragment}/agent-workspace?contactCenter=amazon&instanceId=${instanceId}®ion=${region}${agentAssistedIVRParams}${configuredFeatureParams}`; + const appUrl = `https://${this.c3Context.vendorId}.${this.c3AppUrlFragment}/agent-workspace/payment-request?contactCenter=amazon&instanceId=${instanceId}®ion=${region}${agentAssistedIVRParams}${configuredFeatureParams}`; writeFileToExports( - 'C3WorkspaceAppUrl.txt', - `๐ŸŒ Your C3 Payment Request app URL is:\n\n${appUrl}\n`, + 'C3PaymentRequestAppUrl.txt', + `๐Ÿ’ฐ Your C3 Payment Request app URL is:\n\n๐ŸŒ ${appUrl}\n`, ); return appUrl; } diff --git a/lib/connect/content-transformations.ts b/lib/connect/content-transformations.ts index 6fe9731..9b29d3a 100644 --- a/lib/connect/content-transformations.ts +++ b/lib/connect/content-transformations.ts @@ -2,6 +2,7 @@ import { Function } from 'aws-cdk-lib/aws-lambda'; import * as flowModuleJson from './flows/modules/c3-payment-ivr-flow-module.json'; import * as agentAssistedPaymentIVRFlowJson from './flows/c3-agent-assisted-payment-ivr-flow.json'; import * as subjectLookupFlow from './flows/c3-subject-lookup-flow.json'; +import * as receiptFlow from './flows/c3-receipt-flow.json'; import { IvrSpeakingContext } from '../models'; /** @@ -73,7 +74,7 @@ export function getPaymentIVRFlowModuleContent( } transformedContent = transformedContent.replace( /<>/g, - queueId, + queueId ?? '', ); transformedContent = transformedContent.replace( @@ -186,3 +187,39 @@ export function getSubjectLookupFlowContent( ); return transformedContent; } + +/** + * Gets the content for the receipt flow. + * + * @param sendReceiptLambdaArn The Lambda function that sends a receipt. + * @param sendAgentMessageFunction The Lambda function that sends messages to the agent. + * @param ivrSpeakingContext The speaking context for the IVR. + * @returns A string representing the content for the receipt flow. + */ +export function getReceiptFlowContent( + sendReceiptLambdaFunction: Function, + sendAgentMessageFunction: Function, + ivrSpeakingContext: IvrSpeakingContext, +): string { + let transformedContent = JSON.stringify(receiptFlow); + + // Replace the placeholders with the actual values. + transformedContent = transformedContent.replace( + /<>/g, + sendReceiptLambdaFunction.functionArn, + ); + transformedContent = transformedContent.replace( + /<>/g, + sendAgentMessageFunction.functionArn, + ); + + transformedContent = transformedContent.replace( + /<>/g, + ivrSpeakingContext.rate, + ); + transformedContent = transformedContent.replace( + /<>/g, + ivrSpeakingContext.volume, + ); + return transformedContent; +} diff --git a/lib/connect/flows/c3-agent-assisted-payment-ivr-flow.json b/lib/connect/flows/c3-agent-assisted-payment-ivr-flow.json index aff9163..4bcdf7b 100644 --- a/lib/connect/flows/c3-agent-assisted-payment-ivr-flow.json +++ b/lib/connect/flows/c3-agent-assisted-payment-ivr-flow.json @@ -16,7 +16,7 @@ "conditions": [], "conditionMetadata": [ { - "id": "db8eee5c-dcb6-4a94-b381-2fa8700ea5cb", + "id": "a8dc521a-919a-49d9-930e-e7754386c958", "operator": { "name": "Is greater than", "value": "GreaterThan", @@ -53,12 +53,6 @@ "isFriendlyName": true, "dynamicParams": [] }, - "5a505241-be5a-4437-8d66-785eb1b0beca": { - "position": { - "x": 8133.6, - "y": 702.4 - } - }, "Record Token": { "position": { "x": 5218.4, @@ -67,55 +61,6 @@ "isFriendlyName": true, "dynamicParams": [] }, - "Report Payment Tokenized": { - "position": { - "x": 5439.2, - "y": 390.4 - }, - "isFriendlyName": true, - "parameters": { - "LambdaFunctionARN": { - "displayName": "<>" - } - }, - "dynamicMetadata": { - "EventText": false - } - }, - "Submit Payment": { - "position": { - "x": 5655.2, - "y": 391.2 - }, - "isFriendlyName": true, - "parameters": { - "LambdaFunctionARN": { - "displayName": "<>" - } - }, - "dynamicMetadata": {} - }, - "Record Transaction Attributes": { - "position": { - "x": 5896.8, - "y": 374.4 - }, - "isFriendlyName": true, - "dynamicParams": [] - }, - "Tokenize Transaction": { - "position": { - "x": 4746.4, - "y": 389.6 - }, - "isFriendlyName": true, - "parameters": { - "LambdaFunctionARN": { - "displayName": "<>" - } - }, - "dynamicMetadata": {} - }, "Report Routing Number Entered": { "position": { "x": 4280.8, @@ -238,36 +183,6 @@ }, "isFriendlyName": true }, - "Report Bank Account Selected Again": { - "position": { - "x": 285.6, - "y": -236.8 - }, - "isFriendlyName": true, - "parameters": { - "LambdaFunctionARN": { - "displayName": "<>" - } - }, - "dynamicMetadata": { - "EventText": false - } - }, - "Report Credit Card Selected Again": { - "position": { - "x": 218.4, - "y": -461.6 - }, - "isFriendlyName": true, - "parameters": { - "LambdaFunctionARN": { - "displayName": "<>" - } - }, - "dynamicMetadata": { - "EventText": false - } - }, "Use Payment Method Again Timeout": { "position": { "x": -345.6, @@ -299,11 +214,11 @@ "isFriendlyName": true, "conditionMetadata": [ { - "id": "65cd3d99-d8ea-4589-b55b-1606c11b5cc7", + "id": "b39478fb-425f-4dda-b9c9-9cb0180ee377", "value": "1" }, { - "id": "53267b11-ef0d-4a81-a3d9-6600b4548a16", + "id": "12c08af4-7076-45d0-9e6e-d1f9ece07a64", "value": "2" } ] @@ -317,7 +232,7 @@ "conditions": [], "conditionMetadata": [ { - "id": "7232cdbc-9879-4fdd-ae36-72ddb428b063", + "id": "aca1925c-e022-4f0e-b849-b301c5bd70e9", "operator": { "name": "Equals", "value": "Equals", @@ -326,7 +241,7 @@ "value": "Card" }, { - "id": "200fe3b0-c4c7-4e6e-90e2-e031ba90eabd", + "id": "d88ad7e3-4d08-420e-89ff-6e444826fd44", "operator": { "name": "Equals", "value": "Equals", @@ -344,11 +259,11 @@ "isFriendlyName": true, "conditionMetadata": [ { - "id": "f3c91d2d-b454-4d83-9dfe-0279f2e3eca6", + "id": "2aa62622-3935-4a10-ac54-5df21368753d", "value": "1" }, { - "id": "7a216324-6b62-4bb9-97af-9b2a0dae09e5", + "id": "92b6a0cb-ebbb-429a-acd8-d1d8e9b972a2", "value": "2" } ] @@ -368,11 +283,11 @@ "isFriendlyName": true, "conditionMetadata": [ { - "id": "437a4d0c-a272-42cf-9b7e-c54b51991817", + "id": "896f3848-8106-4b97-992b-d2f17d61306c", "value": "1" }, { - "id": "b3360b4f-3749-44ed-ab86-29d43c4ef35a", + "id": "b1fc4fa2-42b3-4222-a64e-e4d2b98f5fe7", "value": "2" } ] @@ -544,10 +459,10 @@ "conditionMetadata": [], "countryCodePrefix": "+1" }, - "Report Payment Submission Error": { + "Report Card Number Entered": { "position": { - "x": 5888, - "y": 629.6 + "x": 2480.8, + "y": -180 }, "isFriendlyName": true, "parameters": { @@ -559,254 +474,207 @@ "EventText": false } }, - "Payment Submission Error": { + "Try Expiration Date Again": { "position": { - "x": 6128, - "y": 625.6 + "x": 3320.8, + "y": 62.4 }, "isFriendlyName": true }, - "Report Tokenization Error": { + "Store Encrypted Card Number": { "position": { - "x": 5882.4, - "y": 879.2 + "x": 2243.2, + "y": -180 }, "isFriendlyName": true, "parameters": { - "LambdaFunctionARN": { - "displayName": "<>" + "Attributes": { + "EncryptedCardNumber": { + "useDynamic": true + } } }, - "dynamicMetadata": { - "EventText": false - } - }, - "Remove Failed Payment Token and Method": { - "position": { - "x": 6423.2, - "y": 841.6 - }, - "isFriendlyName": true, - "dynamicParams": [] + "dynamicParams": ["EncryptedCardNumber"] }, - "Payment Validation Error": { + "Card Number Validation Error": { "position": { - "x": 6126.4, - "y": 888 + "x": 1890.4, + "y": 44 }, "isFriendlyName": true }, - "Report Payment Processed": { + "Card Number Timeout Check": { "position": { - "x": 6115.2, - "y": 373.6 + "x": 1680, + "y": -376.8 }, "isFriendlyName": true, - "parameters": { - "LambdaFunctionARN": { - "displayName": "<>" + "conditions": [], + "conditionMetadata": [ + { + "id": "fe3b7783-5612-4ead-8b0c-f20d17886cf3", + "operator": { + "name": "Equals", + "value": "Equals", + "shortDisplay": "=" + }, + "value": "Timeout" } - }, - "dynamicMetadata": { - "EventText": false - } + ] }, - "Check for Customer Email": { + "Check for Card Number Validation Error": { "position": { - "x": 6561.6, - "y": 478.4 + "x": 1996, + "y": -250.4 }, "isFriendlyName": true, "conditions": [], "conditionMetadata": [ { - "id": "2bd9ad21-8178-4669-9b7d-7e5c449ca492", + "id": "9fd01f49-b179-49c6-94a8-14481378e12d", "operator": { - "name": "Contains", - "value": "Contains", - "shortDisplay": "contains" + "name": "Equals", + "value": "Equals", + "shortDisplay": "=" }, - "value": "@" + "value": "NULL" } ] }, - "Payment Success": { - "position": { - "x": 6340, - "y": 476.8 - }, - "isFriendlyName": true - }, - "Report Card Number Entered": { + "Validate Card Number": { "position": { - "x": 2480.8, - "y": -180 + "x": 1776.8, + "y": -175.2 }, "isFriendlyName": true, "parameters": { "LambdaFunctionARN": { - "displayName": "<>" + "displayName": "<>" + }, + "LambdaInvocationAttributes": { + "CustomerEntry": { + "useDynamic": true + } } }, "dynamicMetadata": { - "EventText": false + "ValidationType": false, + "CustomerEntry": true } }, - "Try Expiration Date Again": { - "position": { - "x": 3320.8, - "y": 62.4 - }, - "isFriendlyName": true - }, - "Report Validation Error": { + "Store Encrypted Account Number": { "position": { - "x": 5470.4, - "y": 707.2 + "x": 2291.2, + "y": 635.2 }, "isFriendlyName": true, "parameters": { - "LambdaFunctionARN": { - "displayName": "<>" - }, - "LambdaInvocationAttributes": { - "EventText": { + "Attributes": { + "EncryptedAccountNumber": { "useDynamic": true } } }, - "dynamicMetadata": { - "EventText": true - } + "dynamicParams": ["EncryptedAccountNumber"] }, - "Check for Tokenize Error": { + "Account Number Validation Error": { "position": { - "x": 4988.8, - "y": 379.2 + "x": 1960.8, + "y": 840 + }, + "isFriendlyName": true + }, + "Account Number Timeout Check": { + "position": { + "x": 1828.8, + "y": 430.4 }, "isFriendlyName": true, "conditions": [], "conditionMetadata": [ { - "id": "362fe29d-1f68-4fe4-a69e-5a050e627ba5", + "id": "eb198fe9-4132-45d4-8525-e11815e864e9", "operator": { "name": "Equals", "value": "Equals", "shortDisplay": "=" }, - "value": "NULL" + "value": "Timeout" } ] }, - "Speak Validation Error": { - "position": { - "x": 5225.6, - "y": 702.4 - }, - "isFriendlyName": true - }, - "Send Receipt": { + "Check for Account Number Validation Error": { "position": { - "x": 6803.2, - "y": 478.4 + "x": 2076, + "y": 545.6 }, "isFriendlyName": true, - "parameters": { - "LambdaFunctionARN": { - "displayName": "<>" + "conditions": [], + "conditionMetadata": [ + { + "id": "9c6008be-55df-4959-ba9f-0809f9ceea76", + "operator": { + "name": "Equals", + "value": "Equals", + "shortDisplay": "=" + }, + "value": "NULL" } - }, - "dynamicMetadata": {} - }, - "Receipt Success": { - "position": { - "x": 7021.6, - "y": 391.2 - }, - "isFriendlyName": true + ] }, - "Report Receipt Email Error": { + "Validate Account Number": { "position": { - "x": 7033.6, - "y": 576 + "x": 1860.8, + "y": 631.2 }, "isFriendlyName": true, "parameters": { "LambdaFunctionARN": { - "displayName": "<>" + "displayName": "<>" + }, + "LambdaInvocationAttributes": { + "CustomerEntry": { + "useDynamic": true + } } }, "dynamicMetadata": { - "EventText": false + "ValidationType": false, + "CustomerEntry": true } }, - "Receipt Error": { + "Store Routing Number": { "position": { - "x": 7245.6, - "y": 578.4 - }, - "isFriendlyName": true - }, - "90dc6a63-2ae9-4c5f-b65f-75348779d0c6": { - "position": { - "x": 7914.4, - "y": 696 - } - }, - "Internal Error": { - "position": { - "x": 1320, - "y": 1038.4 - }, - "isFriendlyName": true - }, - "Redact Sensitive Contact Attributes": { - "position": { - "x": 7479.2, - "y": 705.6 - }, - "isFriendlyName": true, - "dynamicParams": [] - }, - "Returning To Agent": { - "position": { - "x": 7698.4, - "y": 701.6 - }, - "isFriendlyName": true - }, - "Store Encrypted Card Number": { - "position": { - "x": 2243.2, - "y": -180 + "x": 4047.2, + "y": 632 }, "isFriendlyName": true, "parameters": { "Attributes": { - "EncryptedCardNumber": { + "RoutingNumber": { "useDynamic": true } } }, - "dynamicParams": ["EncryptedCardNumber"] + "dynamicParams": ["RoutingNumber"] }, - "Card Number Validation Error": { + "Routing Number Validation Error": { "position": { - "x": 1890.4, - "y": 44 + "x": 3604, + "y": 886.4 }, "isFriendlyName": true }, - "Card Number Timeout Check": { + "Routing Number Timeout Check": { "position": { - "x": 1680, - "y": -376.8 + "x": 3396, + "y": 447.2 }, "isFriendlyName": true, "conditions": [], "conditionMetadata": [ { - "id": "f9511ba6-b778-4760-be2a-0f15683fbc91", + "id": "60803e6c-c1ed-494c-b629-0b9f96df765b", "operator": { "name": "Equals", "value": "Equals", @@ -816,16 +684,16 @@ } ] }, - "Check for Card Number Validation Error": { + "Check for Routing Number Validation Error": { "position": { - "x": 1996, - "y": -250.4 + "x": 3719.2, + "y": 595.2 }, "isFriendlyName": true, "conditions": [], "conditionMetadata": [ { - "id": "ebd07eeb-7f27-41bf-9280-de9c2c3fdf01", + "id": "1c837d4e-4985-414b-8222-f87b65fd6eef", "operator": { "name": "Equals", "value": "Equals", @@ -835,10 +703,10 @@ } ] }, - "Validate Card Number": { + "Validate Routing Number": { "position": { - "x": 1776.8, - "y": -175.2 + "x": 3471.2, + "y": 652.8 }, "isFriendlyName": true, "parameters": { @@ -856,38 +724,54 @@ "CustomerEntry": true } }, - "Store Encrypted Account Number": { + "Expiration Date Timeout": { "position": { - "x": 2291.2, - "y": 635.2 + "x": 3223.2, + "y": -557.6 + }, + "isFriendlyName": true + }, + "Get Expiration Date": { + "position": { + "x": 3256, + "y": -155.2 + }, + "isFriendlyName": true, + "conditionMetadata": [], + "countryCodePrefix": "+1" + }, + "Store Expiration Date": { + "position": { + "x": 4054.4, + "y": -175.2 }, "isFriendlyName": true, "parameters": { "Attributes": { - "EncryptedAccountNumber": { + "ExpirationDate": { "useDynamic": true } } }, - "dynamicParams": ["EncryptedAccountNumber"] + "dynamicParams": ["ExpirationDate"] }, - "Account Number Validation Error": { + "Expiration Date Validation Error": { "position": { - "x": 1960.8, - "y": 840 + "x": 3649.6, + "y": 50.4 }, "isFriendlyName": true }, - "Account Number Timeout Check": { + "Expiration Date Timeout Check": { "position": { - "x": 1828.8, - "y": 430.4 + "x": 3315.2, + "y": -353.6 }, "isFriendlyName": true, "conditions": [], "conditionMetadata": [ { - "id": "3daff475-825f-40de-aeb1-39066a975f55", + "id": "057289d9-e708-4161-8677-2f0cc94f8cee", "operator": { "name": "Equals", "value": "Equals", @@ -897,16 +781,16 @@ } ] }, - "Check for Account Number Validation Error": { + "Check for Expiration Date Validation Error": { "position": { - "x": 2076, - "y": 545.6 + "x": 3753.6, + "y": -271.2 }, "isFriendlyName": true, "conditions": [], "conditionMetadata": [ { - "id": "fbdc393c-2df1-443a-b10b-e6427aa300d2", + "id": "b724e0ed-9435-45d3-841e-c22c687b3237", "operator": { "name": "Equals", "value": "Equals", @@ -916,10 +800,10 @@ } ] }, - "Validate Account Number": { + "Validate Expiration Date": { "position": { - "x": 1860.8, - "y": 631.2 + "x": 3512.8, + "y": -155.2 }, "isFriendlyName": true, "parameters": { @@ -937,182 +821,344 @@ "CustomerEntry": true } }, - "Store Routing Number": { - "position": { - "x": 4047.2, - "y": 632 - }, - "isFriendlyName": true, - "parameters": { - "Attributes": { - "RoutingNumber": { - "useDynamic": true - } - } - }, - "dynamicParams": ["RoutingNumber"] - }, - "Routing Number Validation Error": { - "position": { - "x": 3604, - "y": 886.4 - }, - "isFriendlyName": true - }, - "Routing Number Timeout Check": { + "Check for Tokenize Error": { "position": { - "x": 3396, - "y": 447.2 + "x": 4988.8, + "y": 379.2 }, "isFriendlyName": true, "conditions": [], "conditionMetadata": [ { - "id": "978332d8-9023-43e0-9ceb-afc454bd108e", + "id": "9d6984ae-e96d-4b6b-9604-18f1272ea629", "operator": { "name": "Equals", "value": "Equals", "shortDisplay": "=" }, - "value": "Timeout" + "value": "NULL" } ] }, - "Check for Routing Number Validation Error": { + "Send Receipt": { "position": { - "x": 3719.2, - "y": 595.2 + "x": 7141.6, + "y": 472 }, "isFriendlyName": true, - "conditions": [], - "conditionMetadata": [ - { - "id": "e07fc5d6-7eae-4080-b874-fb5fadac823a", - "operator": { - "name": "Equals", - "value": "Equals", - "shortDisplay": "=" - }, - "value": "NULL" + "parameters": { + "LambdaFunctionARN": { + "displayName": "<>" } - ] + }, + "dynamicMetadata": {} }, - "Validate Routing Number": { + "Report Receipt Email Error": { "position": { - "x": 3471.2, - "y": 652.8 + "x": 7372, + "y": 569.6 }, "isFriendlyName": true, "parameters": { "LambdaFunctionARN": { - "displayName": "<>" - }, - "LambdaInvocationAttributes": { - "CustomerEntry": { - "useDynamic": true - } + "displayName": "<>" } }, "dynamicMetadata": { - "ValidationType": false, - "CustomerEntry": true + "EventText": false } }, - "Expiration Date Timeout": { + "5a505241-be5a-4437-8d66-785eb1b0beca": { "position": { - "x": 3223.2, - "y": -557.6 + "x": 8472, + "y": 696 + } + }, + "Internal Error": { + "position": { + "x": 1320, + "y": 1038.4 }, "isFriendlyName": true }, - "Get Expiration Date": { + "90dc6a63-2ae9-4c5f-b65f-75348779d0c6": { "position": { - "x": 3256, - "y": -155.2 + "x": 8252.8, + "y": 689.6 + } + }, + "Payment Success": { + "position": { + "x": 6678.4, + "y": 470.4 }, - "isFriendlyName": true, - "conditionMetadata": [], - "countryCodePrefix": "+1" + "isFriendlyName": true }, - "Store Expiration Date": { + "Receipt Success": { "position": { - "x": 4054.4, - "y": -175.2 + "x": 7360, + "y": 384.8 }, - "isFriendlyName": true, - "parameters": { - "Attributes": { - "ExpirationDate": { - "useDynamic": true - } - } + "isFriendlyName": true + }, + "Receipt Error": { + "position": { + "x": 7584, + "y": 572 }, - "dynamicParams": ["ExpirationDate"] + "isFriendlyName": true }, - "Expiration Date Validation Error": { + "Returning To Agent": { "position": { - "x": 3649.6, - "y": 50.4 + "x": 8036.8, + "y": 695.2 }, "isFriendlyName": true }, - "Expiration Date Timeout Check": { + "Check for Customer Email": { "position": { - "x": 3315.2, - "y": -353.6 + "x": 6900, + "y": 472 }, "isFriendlyName": true, "conditions": [], "conditionMetadata": [ { - "id": "a036f1bf-2754-46e7-aaf4-57bdc3463110", + "id": "694a6664-879d-4f49-afec-27575259b69d", "operator": { - "name": "Equals", - "value": "Equals", - "shortDisplay": "=" + "name": "Contains", + "value": "Contains", + "shortDisplay": "contains" }, - "value": "Timeout" + "value": "@" } ] }, - "Check for Expiration Date Validation Error": { + "Redact Sensitive Contact Attributes": { "position": { - "x": 3753.6, - "y": -271.2 + "x": 7817.6, + "y": 699.2 }, "isFriendlyName": true, - "conditions": [], - "conditionMetadata": [ - { - "id": "5a8c6d0e-e326-462c-a814-c02f04d275d5", - "operator": { - "name": "Equals", - "value": "Equals", - "shortDisplay": "=" - }, - "value": "NULL" - } - ] + "dynamicParams": [] }, - "Validate Expiration Date": { + "Report Payment Processed": { "position": { - "x": 3512.8, - "y": -155.2 + "x": 6453.6, + "y": 367.2 }, "isFriendlyName": true, "parameters": { "LambdaFunctionARN": { - "displayName": "<>" - }, - "LambdaInvocationAttributes": { - "CustomerEntry": { - "useDynamic": true - } + "displayName": "<>" } }, "dynamicMetadata": { - "ValidationType": false, - "CustomerEntry": true + "EventText": false + } + }, + "Report Payment Tokenized": { + "position": { + "x": 5439.2, + "y": 390.4 + }, + "isFriendlyName": true, + "parameters": { + "LambdaFunctionARN": { + "displayName": "<>" + } + }, + "dynamicMetadata": { + "EventText": false + } + }, + "Report Bank Account Selected Again": { + "position": { + "x": 285.6, + "y": -236.8 + }, + "isFriendlyName": true, + "parameters": { + "LambdaFunctionARN": { + "displayName": "<>" + } + }, + "dynamicMetadata": { + "EventText": false + } + }, + "Report Credit Card Selected Again": { + "position": { + "x": 218.4, + "y": -461.6 + }, + "isFriendlyName": true, + "parameters": { + "LambdaFunctionARN": { + "displayName": "<>" + } + }, + "dynamicMetadata": { + "EventText": false + } + }, + "Tokenize Transaction": { + "position": { + "x": 4746.4, + "y": 389.6 + }, + "isFriendlyName": true, + "parameters": { + "LambdaFunctionARN": { + "displayName": "<>" + } + }, + "dynamicMetadata": {} + }, + "Report Tokenization Error": { + "position": { + "x": 5056, + "y": 927.2 + }, + "isFriendlyName": true, + "parameters": { + "LambdaFunctionARN": { + "displayName": "<>" + } + }, + "dynamicMetadata": { + "EventText": false + } + }, + "Payment Validation Error": { + "position": { + "x": 5294.4, + "y": 934.4 + }, + "isFriendlyName": true + }, + "Record Transaction Attributes": { + "position": { + "x": 6172.8, + "y": 377.6 + }, + "isFriendlyName": true, + "dynamicParams": [] + }, + "Check for Submit Payment Error": { + "position": { + "x": 5896.8, + "y": 386.4 + }, + "isFriendlyName": true, + "conditions": [], + "conditionMetadata": [ + { + "id": "a21b3261-d9d2-4b46-a6e1-bf56502aa73d", + "operator": { + "name": "Equals", + "value": "Equals", + "shortDisplay": "=" + }, + "value": "NULL" + } + ] + }, + "Speak Payment Submission Error": { + "position": { + "x": 6177.6, + "y": 569.6 + }, + "isFriendlyName": true + }, + "Report Payment Submission Error": { + "position": { + "x": 6418.4, + "y": 578.4 + }, + "isFriendlyName": true, + "parameters": { + "LambdaFunctionARN": { + "displayName": "<>" + }, + "LambdaInvocationAttributes": { + "EventText": { + "useDynamic": true + } + } + }, + "dynamicMetadata": { + "EventText": true + } + }, + "Speak Paymen Submission Unknown Error": { + "position": { + "x": 5920.8, + "y": 620.8 + }, + "isFriendlyName": true + }, + "Submit Payment": { + "position": { + "x": 5655.2, + "y": 391.2 + }, + "isFriendlyName": true, + "parameters": { + "LambdaFunctionARN": { + "displayName": "<>" + } + }, + "dynamicMetadata": {} + }, + "Report Payment Submission Unknown Error": { + "position": { + "x": 5708.8, + "y": 626.4 + }, + "isFriendlyName": true, + "parameters": { + "LambdaFunctionARN": { + "displayName": "<>" + } + }, + "dynamicMetadata": { + "EventText": false + } + }, + "Speak Validation Error": { + "position": { + "x": 5225.6, + "y": 702.4 + }, + "isFriendlyName": true + }, + "Remove Failed Payment Token and Method": { + "position": { + "x": 6761.6, + "y": 835.2 + }, + "isFriendlyName": true, + "dynamicParams": [] + }, + "Report Validation Error": { + "position": { + "x": 5470.4, + "y": 707.2 + }, + "isFriendlyName": true, + "parameters": { + "LambdaFunctionARN": { + "displayName": "<>" + }, + "LambdaInvocationAttributes": { + "EventText": { + "useDynamic": true + } + } + }, + "dynamicMetadata": { + "EventText": true } } }, @@ -1259,12 +1305,6 @@ ] } }, - { - "Parameters": {}, - "Identifier": "5a505241-be5a-4437-8d66-785eb1b0beca", - "Type": "DisconnectParticipant", - "Transitions": {} - }, { "Parameters": { "Attributes": { @@ -1289,19 +1329,19 @@ "LambdaFunctionARN": "<>", "InvocationTimeLimitSeconds": "8", "LambdaInvocationAttributes": { - "EventText": "PaymentTokenized" + "EventText": "RoutingNumberEntered" }, "ResponseValidation": { "ResponseType": "JSON" } }, - "Identifier": "Report Payment Tokenized", + "Identifier": "Report Routing Number Entered", "Type": "InvokeLambdaFunction", "Transitions": { - "NextAction": "Submit Payment", + "NextAction": "Tokenize Transaction", "Errors": [ { - "NextAction": "Submit Payment", + "NextAction": "Tokenize Transaction", "ErrorType": "NoMatchingError" } ] @@ -1309,19 +1349,22 @@ }, { "Parameters": { - "LambdaFunctionARN": "<>", + "LambdaFunctionARN": "<>", "InvocationTimeLimitSeconds": "8", + "LambdaInvocationAttributes": { + "EventText": "ExpirationDateEntered" + }, "ResponseValidation": { "ResponseType": "JSON" } }, - "Identifier": "Submit Payment", + "Identifier": "Report Expiration Entered", "Type": "InvokeLambdaFunction", "Transitions": { - "NextAction": "Record Transaction Attributes", + "NextAction": "Tokenize Transaction", "Errors": [ { - "NextAction": "Report Payment Submission Error", + "NextAction": "Tokenize Transaction", "ErrorType": "NoMatchingError" } ] @@ -1329,19 +1372,22 @@ }, { "Parameters": { - "Attributes": { - "TransactionId": "$.External.TransactionId", - "PaymentMethodEndingDigits": "$.External.PaymentMethodEndingDigits" + "LambdaFunctionARN": "<>", + "InvocationTimeLimitSeconds": "8", + "LambdaInvocationAttributes": { + "EventText": "PaymentRequestError" }, - "TargetContact": "Current" + "ResponseValidation": { + "ResponseType": "JSON" + } }, - "Identifier": "Record Transaction Attributes", - "Type": "UpdateContactAttributes", + "Identifier": "Report Payment Request Error", + "Type": "InvokeLambdaFunction", "Transitions": { - "NextAction": "Report Payment Processed", + "NextAction": "Payment Request Error", "Errors": [ { - "NextAction": "Report Payment Processed", + "NextAction": "Payment Request Error", "ErrorType": "NoMatchingError" } ] @@ -1349,19 +1395,15 @@ }, { "Parameters": { - "LambdaFunctionARN": "<>", - "InvocationTimeLimitSeconds": "8", - "ResponseValidation": { - "ResponseType": "JSON" - } + "Text": "\n>\" rate=\"<>\">\nThere was an error creating the payment request.\n\n" }, - "Identifier": "Tokenize Transaction", - "Type": "InvokeLambdaFunction", + "Identifier": "Payment Request Error", + "Type": "MessageParticipant", "Transitions": { - "NextAction": "Check for Tokenize Error", + "NextAction": "33d2c563-289f-4358-9500-fc1552cc9523", "Errors": [ { - "NextAction": "Report Tokenization Error", + "NextAction": "33d2c563-289f-4358-9500-fc1552cc9523", "ErrorType": "NoMatchingError" } ] @@ -1372,104 +1414,19 @@ "LambdaFunctionARN": "<>", "InvocationTimeLimitSeconds": "8", "LambdaInvocationAttributes": { - "EventText": "RoutingNumberEntered" + "EventText": "NoPaymentInfoError" }, "ResponseValidation": { "ResponseType": "JSON" } }, - "Identifier": "Report Routing Number Entered", + "Identifier": "Report No Payment Info Error", "Type": "InvokeLambdaFunction", "Transitions": { - "NextAction": "Tokenize Transaction", + "NextAction": "No Payment Information", "Errors": [ { - "NextAction": "Tokenize Transaction", - "ErrorType": "NoMatchingError" - } - ] - } - }, - { - "Parameters": { - "LambdaFunctionARN": "<>", - "InvocationTimeLimitSeconds": "8", - "LambdaInvocationAttributes": { - "EventText": "ExpirationDateEntered" - }, - "ResponseValidation": { - "ResponseType": "JSON" - } - }, - "Identifier": "Report Expiration Entered", - "Type": "InvokeLambdaFunction", - "Transitions": { - "NextAction": "Tokenize Transaction", - "Errors": [ - { - "NextAction": "Tokenize Transaction", - "ErrorType": "NoMatchingError" - } - ] - } - }, - { - "Parameters": { - "LambdaFunctionARN": "<>", - "InvocationTimeLimitSeconds": "8", - "LambdaInvocationAttributes": { - "EventText": "PaymentRequestError" - }, - "ResponseValidation": { - "ResponseType": "JSON" - } - }, - "Identifier": "Report Payment Request Error", - "Type": "InvokeLambdaFunction", - "Transitions": { - "NextAction": "Payment Request Error", - "Errors": [ - { - "NextAction": "Payment Request Error", - "ErrorType": "NoMatchingError" - } - ] - } - }, - { - "Parameters": { - "Text": "\n>\" rate=\"<>\">\nThere was an error creating the payment request.\n\n" - }, - "Identifier": "Payment Request Error", - "Type": "MessageParticipant", - "Transitions": { - "NextAction": "33d2c563-289f-4358-9500-fc1552cc9523", - "Errors": [ - { - "NextAction": "33d2c563-289f-4358-9500-fc1552cc9523", - "ErrorType": "NoMatchingError" - } - ] - } - }, - { - "Parameters": { - "LambdaFunctionARN": "<>", - "InvocationTimeLimitSeconds": "8", - "LambdaInvocationAttributes": { - "EventText": "NoPaymentInfoError" - }, - "ResponseValidation": { - "ResponseType": "JSON" - } - }, - "Identifier": "Report No Payment Info Error", - "Type": "InvokeLambdaFunction", - "Transitions": { - "NextAction": "No Payment Information", - "Errors": [ - { - "NextAction": "No Payment Information", + "NextAction": "No Payment Information", "ErrorType": "NoMatchingError" } ] @@ -1584,52 +1541,6 @@ ] } }, - { - "Parameters": { - "LambdaFunctionARN": "<>", - "InvocationTimeLimitSeconds": "8", - "LambdaInvocationAttributes": { - "EventText": "BankAccountSelected" - }, - "ResponseValidation": { - "ResponseType": "JSON" - } - }, - "Identifier": "Report Bank Account Selected Again", - "Type": "InvokeLambdaFunction", - "Transitions": { - "NextAction": "Submit Payment", - "Errors": [ - { - "NextAction": "Submit Payment", - "ErrorType": "NoMatchingError" - } - ] - } - }, - { - "Parameters": { - "LambdaFunctionARN": "<>", - "InvocationTimeLimitSeconds": "8", - "LambdaInvocationAttributes": { - "EventText": "CreditCardSelected" - }, - "ResponseValidation": { - "ResponseType": "JSON" - } - }, - "Identifier": "Report Credit Card Selected Again", - "Type": "InvokeLambdaFunction", - "Transitions": { - "NextAction": "Submit Payment", - "Errors": [ - { - "NextAction": "Submit Payment", - "ErrorType": "NoMatchingError" - } - ] - } - }, { "Parameters": { "Text": "\n>\" rate=\"<>\">\nAre you still there?\n\n" @@ -2193,19 +2104,19 @@ "LambdaFunctionARN": "<>", "InvocationTimeLimitSeconds": "8", "LambdaInvocationAttributes": { - "EventText": "PaymentSubmissionError" + "EventText": "CardNumberEntered" }, "ResponseValidation": { "ResponseType": "JSON" } }, - "Identifier": "Report Payment Submission Error", + "Identifier": "Report Card Number Entered", "Type": "InvokeLambdaFunction", "Transitions": { - "NextAction": "Payment Submission Error", + "NextAction": "Get Expiration Date", "Errors": [ { - "NextAction": "Payment Submission Error", + "NextAction": "Get Expiration Date", "ErrorType": "NoMatchingError" } ] @@ -2213,15 +2124,15 @@ }, { "Parameters": { - "Text": "\n>\" rate=\"<>\">\nWe're sorry, an error has occured preventing us from submitting your payment. You have not been charged.\n\n" + "Text": "\n>\" rate=\"<>\">\nThere was a problem with your expiration date. Please check your entry and try again.\n\n" }, - "Identifier": "Payment Submission Error", + "Identifier": "Try Expiration Date Again", "Type": "MessageParticipant", "Transitions": { - "NextAction": "Remove Failed Payment Token and Method", + "NextAction": "Get Expiration Date", "Errors": [ { - "NextAction": "Remove Failed Payment Token and Method", + "NextAction": "Get Expiration Date", "ErrorType": "NoMatchingError" } ] @@ -2229,22 +2140,108 @@ }, { "Parameters": { - "LambdaFunctionARN": "<>", + "Attributes": { + "EncryptedCardNumber": "$.StoredCustomerInput" + }, + "TargetContact": "Current" + }, + "Identifier": "Store Encrypted Card Number", + "Type": "UpdateContactAttributes", + "Transitions": { + "NextAction": "Report Card Number Entered", + "Errors": [ + { + "NextAction": "Report Card Number Encryption Error", + "ErrorType": "NoMatchingError" + } + ] + } + }, + { + "Parameters": { + "Text": "\n>\" rate=\"<>\">\n$.External.ValidationError\n\nPlease check your entry and try again.\n\n" + }, + "Identifier": "Card Number Validation Error", + "Type": "MessageParticipant", + "Transitions": { + "NextAction": "Get & Encrypt Card Number", + "Errors": [ + { + "NextAction": "Get & Encrypt Card Number", + "ErrorType": "NoMatchingError" + } + ] + } + }, + { + "Parameters": { + "ComparisonValue": "$.StoredCustomerInput" + }, + "Identifier": "Card Number Timeout Check", + "Type": "Compare", + "Transitions": { + "NextAction": "Validate Card Number", + "Conditions": [ + { + "NextAction": "Card Number Timeout", + "Condition": { + "Operator": "Equals", + "Operands": ["Timeout"] + } + } + ], + "Errors": [ + { + "NextAction": "Validate Card Number", + "ErrorType": "NoMatchingCondition" + } + ] + } + }, + { + "Parameters": { + "ComparisonValue": "$.External.ValidationError" + }, + "Identifier": "Check for Card Number Validation Error", + "Type": "Compare", + "Transitions": { + "NextAction": "Card Number Validation Error", + "Conditions": [ + { + "NextAction": "Store Encrypted Card Number", + "Condition": { + "Operator": "Equals", + "Operands": ["NULL"] + } + } + ], + "Errors": [ + { + "NextAction": "Card Number Validation Error", + "ErrorType": "NoMatchingCondition" + } + ] + } + }, + { + "Parameters": { + "LambdaFunctionARN": "<>", "InvocationTimeLimitSeconds": "8", "LambdaInvocationAttributes": { - "EventText": "TokenizationError" + "ValidationType": "CardNumber", + "CustomerEntry": "$.StoredCustomerInput" }, "ResponseValidation": { "ResponseType": "JSON" } }, - "Identifier": "Report Tokenization Error", + "Identifier": "Validate Card Number", "Type": "InvokeLambdaFunction", "Transitions": { - "NextAction": "Payment Validation Error", + "NextAction": "Check for Card Number Validation Error", "Errors": [ { - "NextAction": "Payment Validation Error", + "NextAction": "Store Encrypted Card Number", "ErrorType": "NoMatchingError" } ] @@ -2253,18 +2250,17 @@ { "Parameters": { "Attributes": { - "PaymentToken": "NULL", - "PaymentMethod": "NULL" + "EncryptedAccountNumber": "$.StoredCustomerInput" }, "TargetContact": "Current" }, - "Identifier": "Remove Failed Payment Token and Method", + "Identifier": "Store Encrypted Account Number", "Type": "UpdateContactAttributes", "Transitions": { - "NextAction": "Redact Sensitive Contact Attributes", + "NextAction": "Report Account Number Entered", "Errors": [ { - "NextAction": "Redact Sensitive Contact Attributes", + "NextAction": "Report Account Number Encryption Error", "ErrorType": "NoMatchingError" } ] @@ -2272,15 +2268,15 @@ }, { "Parameters": { - "Text": "\n>\" rate=\"<>\">\nThere was a problem validating your $.Attributes.PaymentMethod information.\n\n" + "Text": "\n>\" rate=\"<>\">\n$.External.ValidationError\n\nPlease check your entry and try again.\n\n" }, - "Identifier": "Payment Validation Error", + "Identifier": "Account Number Validation Error", "Type": "MessageParticipant", "Transitions": { - "NextAction": "Remove Failed Payment Token and Method", + "NextAction": "Get & Encrypt Account Number", "Errors": [ { - "NextAction": "Remove Failed Payment Token and Method", + "NextAction": "Get & Encrypt Account Number", "ErrorType": "NoMatchingError" } ] @@ -2288,22 +2284,73 @@ }, { "Parameters": { - "LambdaFunctionARN": "<>", + "ComparisonValue": "$.StoredCustomerInput" + }, + "Identifier": "Account Number Timeout Check", + "Type": "Compare", + "Transitions": { + "NextAction": "Validate Account Number", + "Conditions": [ + { + "NextAction": "Account Number Timeout", + "Condition": { + "Operator": "Equals", + "Operands": ["Timeout"] + } + } + ], + "Errors": [ + { + "NextAction": "Validate Account Number", + "ErrorType": "NoMatchingCondition" + } + ] + } + }, + { + "Parameters": { + "ComparisonValue": "$.External.ValidationError" + }, + "Identifier": "Check for Account Number Validation Error", + "Type": "Compare", + "Transitions": { + "NextAction": "Account Number Validation Error", + "Conditions": [ + { + "NextAction": "Store Encrypted Account Number", + "Condition": { + "Operator": "Equals", + "Operands": ["NULL"] + } + } + ], + "Errors": [ + { + "NextAction": "Account Number Validation Error", + "ErrorType": "NoMatchingCondition" + } + ] + } + }, + { + "Parameters": { + "LambdaFunctionARN": "<>", "InvocationTimeLimitSeconds": "8", "LambdaInvocationAttributes": { - "EventText": "PaymentProcessed" + "ValidationType": "AccountNumber", + "CustomerEntry": "$.StoredCustomerInput" }, "ResponseValidation": { "ResponseType": "JSON" } }, - "Identifier": "Report Payment Processed", + "Identifier": "Validate Account Number", "Type": "InvokeLambdaFunction", "Transitions": { - "NextAction": "Payment Success", + "NextAction": "Check for Account Number Validation Error", "Errors": [ { - "NextAction": "Payment Success", + "NextAction": "Store Encrypted Account Number", "ErrorType": "NoMatchingError" } ] @@ -2311,40 +2358,186 @@ }, { "Parameters": { - "ComparisonValue": "$.Attributes.Email" + "Attributes": { + "RoutingNumber": "$.StoredCustomerInput" + }, + "TargetContact": "Current" }, - "Identifier": "Check for Customer Email", + "Identifier": "Store Routing Number", + "Type": "UpdateContactAttributes", + "Transitions": { + "NextAction": "Report Routing Number Entered", + "Errors": [ + { + "NextAction": "Report Routing Number Error", + "ErrorType": "NoMatchingError" + } + ] + } + }, + { + "Parameters": { + "Text": "\n>\" rate=\"<>\">\n$.External.ValidationError\n\nPlease check your entry and try again.\n\n" + }, + "Identifier": "Routing Number Validation Error", + "Type": "MessageParticipant", + "Transitions": { + "NextAction": "Get Routing Number", + "Errors": [ + { + "NextAction": "Get Routing Number", + "ErrorType": "NoMatchingError" + } + ] + } + }, + { + "Parameters": { + "ComparisonValue": "$.StoredCustomerInput" + }, + "Identifier": "Routing Number Timeout Check", "Type": "Compare", "Transitions": { - "NextAction": "Redact Sensitive Contact Attributes", - "Conditions": [ - { - "NextAction": "Send Receipt", - "Condition": { - "Operator": "TextContains", - "Operands": ["@"] - } - } - ], + "NextAction": "Validate Routing Number", + "Conditions": [ + { + "NextAction": "Routing Number Timeout", + "Condition": { + "Operator": "Equals", + "Operands": ["Timeout"] + } + } + ], + "Errors": [ + { + "NextAction": "Validate Routing Number", + "ErrorType": "NoMatchingCondition" + } + ] + } + }, + { + "Parameters": { + "ComparisonValue": "$.External.ValidationError" + }, + "Identifier": "Check for Routing Number Validation Error", + "Type": "Compare", + "Transitions": { + "NextAction": "Routing Number Validation Error", + "Conditions": [ + { + "NextAction": "Store Routing Number", + "Condition": { + "Operator": "Equals", + "Operands": ["NULL"] + } + } + ], + "Errors": [ + { + "NextAction": "Routing Number Validation Error", + "ErrorType": "NoMatchingCondition" + } + ] + } + }, + { + "Parameters": { + "LambdaFunctionARN": "<>", + "InvocationTimeLimitSeconds": "8", + "LambdaInvocationAttributes": { + "ValidationType": "RoutingNumber", + "CustomerEntry": "$.StoredCustomerInput" + }, + "ResponseValidation": { + "ResponseType": "JSON" + } + }, + "Identifier": "Validate Routing Number", + "Type": "InvokeLambdaFunction", + "Transitions": { + "NextAction": "Check for Routing Number Validation Error", + "Errors": [ + { + "NextAction": "Store Routing Number", + "ErrorType": "NoMatchingError" + } + ] + } + }, + { + "Parameters": { + "Text": "\n>\" rate=\"<>\">\nAre you still there?\n\n" + }, + "Identifier": "Expiration Date Timeout", + "Type": "MessageParticipant", + "Transitions": { + "NextAction": "Get Expiration Date", + "Errors": [ + { + "NextAction": "Get Expiration Date", + "ErrorType": "NoMatchingError" + } + ] + } + }, + { + "Parameters": { + "StoreInput": "True", + "InputTimeLimitSeconds": "5", + "Text": "\n>\" rate=\"<>\">\nPlease enter your card's expiration date in the format month-month-year-year, followed by the pound key when complete.\n\n", + "DTMFConfiguration": { + "DisableCancelKey": "False", + "InputTerminationSequence": "#" + }, + "InputValidation": { + "CustomValidation": { + "MaximumLength": "4" + } + } + }, + "Identifier": "Get Expiration Date", + "Type": "GetParticipantInput", + "Transitions": { + "NextAction": "Expiration Date Timeout Check", + "Errors": [ + { + "NextAction": "Try Expiration Date Again", + "ErrorType": "NoMatchingError" + } + ] + } + }, + { + "Parameters": { + "Attributes": { + "ExpirationDate": "$.StoredCustomerInput" + }, + "TargetContact": "Current" + }, + "Identifier": "Store Expiration Date", + "Type": "UpdateContactAttributes", + "Transitions": { + "NextAction": "Report Expiration Entered", "Errors": [ { - "NextAction": "Redact Sensitive Contact Attributes", - "ErrorType": "NoMatchingCondition" + "NextAction": "Report Expiration Date Error", + "ErrorType": "NoMatchingError" } ] } }, { "Parameters": { - "Text": "\n>\" rate=\"<>\">\nYour payment was processed successfully.\n\n" + "Text": "\n>\" rate=\"<>\">\n$.External.ValidationError\n\nPlease check your entry and try again.\n\n" }, - "Identifier": "Payment Success", + "Identifier": "Expiration Date Validation Error", "Type": "MessageParticipant", "Transitions": { - "NextAction": "Check for Customer Email", + "NextAction": "Get Expiration Date", "Errors": [ { - "NextAction": "Check for Customer Email", + "NextAction": "Get Expiration Date", "ErrorType": "NoMatchingError" } ] @@ -2352,61 +2545,73 @@ }, { "Parameters": { - "LambdaFunctionARN": "<>", - "InvocationTimeLimitSeconds": "8", - "LambdaInvocationAttributes": { - "EventText": "CardNumberEntered" - }, - "ResponseValidation": { - "ResponseType": "JSON" - } + "ComparisonValue": "$.StoredCustomerInput" }, - "Identifier": "Report Card Number Entered", - "Type": "InvokeLambdaFunction", + "Identifier": "Expiration Date Timeout Check", + "Type": "Compare", "Transitions": { - "NextAction": "Get Expiration Date", + "NextAction": "Validate Expiration Date", + "Conditions": [ + { + "NextAction": "Expiration Date Timeout", + "Condition": { + "Operator": "Equals", + "Operands": ["Timeout"] + } + } + ], "Errors": [ { - "NextAction": "Get Expiration Date", - "ErrorType": "NoMatchingError" + "NextAction": "Validate Expiration Date", + "ErrorType": "NoMatchingCondition" } ] } }, { "Parameters": { - "Text": "\n>\" rate=\"<>\">\nThere was a problem with your expiration date. Please check your entry and try again.\n\n" + "ComparisonValue": "$.External.ValidationError" }, - "Identifier": "Try Expiration Date Again", - "Type": "MessageParticipant", + "Identifier": "Check for Expiration Date Validation Error", + "Type": "Compare", "Transitions": { - "NextAction": "Get Expiration Date", + "NextAction": "Expiration Date Validation Error", + "Conditions": [ + { + "NextAction": "Store Expiration Date", + "Condition": { + "Operator": "Equals", + "Operands": ["NULL"] + } + } + ], "Errors": [ { - "NextAction": "Get Expiration Date", - "ErrorType": "NoMatchingError" + "NextAction": "Expiration Date Validation Error", + "ErrorType": "NoMatchingCondition" } ] } }, { "Parameters": { - "LambdaFunctionARN": "<>", + "LambdaFunctionARN": "<>", "InvocationTimeLimitSeconds": "8", "LambdaInvocationAttributes": { - "EventText": "$.External.Error" + "ValidationType": "ExpirationDate", + "CustomerEntry": "$.StoredCustomerInput" }, "ResponseValidation": { "ResponseType": "JSON" } }, - "Identifier": "Report Validation Error", + "Identifier": "Validate Expiration Date", "Type": "InvokeLambdaFunction", "Transitions": { - "NextAction": "Remove Failed Payment Token and Method", + "NextAction": "Check for Expiration Date Validation Error", "Errors": [ { - "NextAction": "Remove Failed Payment Token and Method", + "NextAction": "Store Expiration Date", "ErrorType": "NoMatchingError" } ] @@ -2437,22 +2642,6 @@ ] } }, - { - "Parameters": { - "Text": "\n>\" rate=\"<>\">\nThe payment failed because of the following error:\n\n$.External.Error\n\n" - }, - "Identifier": "Speak Validation Error", - "Type": "MessageParticipant", - "Transitions": { - "NextAction": "Report Validation Error", - "Errors": [ - { - "NextAction": "Report Validation Error", - "ErrorType": "NoMatchingError" - } - ] - } - }, { "Parameters": { "LambdaFunctionARN": "<>", @@ -2473,22 +2662,6 @@ ] } }, - { - "Parameters": { - "Text": "\n>\" rate=\"<>\">\nA receipt has been sent to your email address, $.Attributes.['Email'].\n\n" - }, - "Identifier": "Receipt Success", - "Type": "MessageParticipant", - "Transitions": { - "NextAction": "Redact Sensitive Contact Attributes", - "Errors": [ - { - "NextAction": "Redact Sensitive Contact Attributes", - "ErrorType": "NoMatchingError" - } - ] - } - }, { "Parameters": { "LambdaFunctionARN": "<>", @@ -2512,17 +2685,23 @@ ] } }, + { + "Parameters": {}, + "Identifier": "5a505241-be5a-4437-8d66-785eb1b0beca", + "Type": "DisconnectParticipant", + "Transitions": {} + }, { "Parameters": { - "Text": "\n>\" rate=\"<>\">\nThere was an error sending the receipt to your email address, $.Attributes.['Email']. Please contact customer support to receive a receipt for this transaction.\n\n" + "Text": "\n>\" rate=\"<>\">\nWe're sorry, an error has occurred that prevents us from collecting the payment.\n\n" }, - "Identifier": "Receipt Error", + "Identifier": "Internal Error", "Type": "MessageParticipant", "Transitions": { - "NextAction": "Redact Sensitive Contact Attributes", + "NextAction": "Returning To Agent", "Errors": [ { - "NextAction": "Redact Sensitive Contact Attributes", + "NextAction": "Returning To Agent", "ErrorType": "NoMatchingError" } ] @@ -2546,36 +2725,15 @@ }, { "Parameters": { - "Text": "\n>\" rate=\"<>\">\nWe're sorry, an error has occurred that prevents us from collecting the payment.\n\n" + "Text": "\n>\" rate=\"<>\">\nYour payment was processed successfully.\n\n" }, - "Identifier": "Internal Error", + "Identifier": "Payment Success", "Type": "MessageParticipant", "Transitions": { - "NextAction": "Returning To Agent", - "Errors": [ - { - "NextAction": "Returning To Agent", - "ErrorType": "NoMatchingError" - } - ] - } - }, - { - "Parameters": { - "Attributes": { - "EncryptedCardNumber": "REDACTED", - "ExpirationDate": "REDACTED", - "EncryptedAccountNumber": "REDACTED" - }, - "TargetContact": "Current" - }, - "Identifier": "Redact Sensitive Contact Attributes", - "Type": "UpdateContactAttributes", - "Transitions": { - "NextAction": "Returning To Agent", + "NextAction": "Check for Customer Email", "Errors": [ { - "NextAction": "Returning To Agent", + "NextAction": "Check for Customer Email", "ErrorType": "NoMatchingError" } ] @@ -2583,15 +2741,15 @@ }, { "Parameters": { - "Text": "\n>\" rate=\"<>\">\nReturning you to the agent...\n\n" + "Text": "\n>\" rate=\"<>\">\nA receipt has been sent to your email address, $.Attributes.['Email'].\n\n" }, - "Identifier": "Returning To Agent", + "Identifier": "Receipt Success", "Type": "MessageParticipant", "Transitions": { - "NextAction": "90dc6a63-2ae9-4c5f-b65f-75348779d0c6", + "NextAction": "Redact Sensitive Contact Attributes", "Errors": [ { - "NextAction": "90dc6a63-2ae9-4c5f-b65f-75348779d0c6", + "NextAction": "Redact Sensitive Contact Attributes", "ErrorType": "NoMatchingError" } ] @@ -2599,18 +2757,15 @@ }, { "Parameters": { - "Attributes": { - "EncryptedCardNumber": "$.StoredCustomerInput" - }, - "TargetContact": "Current" + "Text": "\n>\" rate=\"<>\">\nThere was an error sending the receipt to your email address, $.Attributes.['Email']. Please contact customer support to receive a receipt for this transaction.\n\n" }, - "Identifier": "Store Encrypted Card Number", - "Type": "UpdateContactAttributes", + "Identifier": "Receipt Error", + "Type": "MessageParticipant", "Transitions": { - "NextAction": "Report Card Number Entered", + "NextAction": "Redact Sensitive Contact Attributes", "Errors": [ { - "NextAction": "Report Card Number Encryption Error", + "NextAction": "Redact Sensitive Contact Attributes", "ErrorType": "NoMatchingError" } ] @@ -2618,15 +2773,15 @@ }, { "Parameters": { - "Text": "\n>\" rate=\"<>\">\n$.External.ValidationError\n\nPlease check your entry and try again.\n\n" + "Text": "\n>\" rate=\"<>\">\nReturning you to the agent...\n\n" }, - "Identifier": "Card Number Validation Error", + "Identifier": "Returning To Agent", "Type": "MessageParticipant", "Transitions": { - "NextAction": "Get & Encrypt Card Number", + "NextAction": "90dc6a63-2ae9-4c5f-b65f-75348779d0c6", "Errors": [ { - "NextAction": "Get & Encrypt Card Number", + "NextAction": "90dc6a63-2ae9-4c5f-b65f-75348779d0c6", "ErrorType": "NoMatchingError" } ] @@ -2634,24 +2789,24 @@ }, { "Parameters": { - "ComparisonValue": "$.StoredCustomerInput" + "ComparisonValue": "$.Attributes.Email" }, - "Identifier": "Card Number Timeout Check", + "Identifier": "Check for Customer Email", "Type": "Compare", "Transitions": { - "NextAction": "Validate Card Number", + "NextAction": "Redact Sensitive Contact Attributes", "Conditions": [ { - "NextAction": "Card Number Timeout", + "NextAction": "Send Receipt", "Condition": { - "Operator": "Equals", - "Operands": ["Timeout"] + "Operator": "TextContains", + "Operands": ["@"] } } ], "Errors": [ { - "NextAction": "Validate Card Number", + "NextAction": "Redact Sensitive Contact Attributes", "ErrorType": "NoMatchingCondition" } ] @@ -2659,48 +2814,43 @@ }, { "Parameters": { - "ComparisonValue": "$.External.ValidationError" + "Attributes": { + "EncryptedCardNumber": "REDACTED", + "ExpirationDate": "REDACTED", + "EncryptedAccountNumber": "REDACTED" + }, + "TargetContact": "Current" }, - "Identifier": "Check for Card Number Validation Error", - "Type": "Compare", + "Identifier": "Redact Sensitive Contact Attributes", + "Type": "UpdateContactAttributes", "Transitions": { - "NextAction": "Card Number Validation Error", - "Conditions": [ - { - "NextAction": "Store Encrypted Card Number", - "Condition": { - "Operator": "Equals", - "Operands": ["NULL"] - } - } - ], + "NextAction": "Returning To Agent", "Errors": [ { - "NextAction": "Card Number Validation Error", - "ErrorType": "NoMatchingCondition" + "NextAction": "Returning To Agent", + "ErrorType": "NoMatchingError" } ] } }, { "Parameters": { - "LambdaFunctionARN": "<>", + "LambdaFunctionARN": "<>", "InvocationTimeLimitSeconds": "8", "LambdaInvocationAttributes": { - "ValidationType": "CardNumber", - "CustomerEntry": "$.StoredCustomerInput" + "EventText": "PaymentProcessed" }, "ResponseValidation": { "ResponseType": "JSON" } }, - "Identifier": "Validate Card Number", + "Identifier": "Report Payment Processed", "Type": "InvokeLambdaFunction", "Transitions": { - "NextAction": "Check for Card Number Validation Error", + "NextAction": "Payment Success", "Errors": [ { - "NextAction": "Store Encrypted Card Number", + "NextAction": "Payment Success", "ErrorType": "NoMatchingError" } ] @@ -2708,18 +2858,22 @@ }, { "Parameters": { - "Attributes": { - "EncryptedAccountNumber": "$.StoredCustomerInput" + "LambdaFunctionARN": "<>", + "InvocationTimeLimitSeconds": "8", + "LambdaInvocationAttributes": { + "EventText": "PaymentTokenized" }, - "TargetContact": "Current" + "ResponseValidation": { + "ResponseType": "JSON" + } }, - "Identifier": "Store Encrypted Account Number", - "Type": "UpdateContactAttributes", + "Identifier": "Report Payment Tokenized", + "Type": "InvokeLambdaFunction", "Transitions": { - "NextAction": "Report Account Number Entered", + "NextAction": "Submit Payment", "Errors": [ { - "NextAction": "Report Account Number Encryption Error", + "NextAction": "Submit Payment", "ErrorType": "NoMatchingError" } ] @@ -2727,15 +2881,22 @@ }, { "Parameters": { - "Text": "\n>\" rate=\"<>\">\n$.External.ValidationError\n\nPlease check your entry and try again.\n\n" + "LambdaFunctionARN": "<>", + "InvocationTimeLimitSeconds": "8", + "LambdaInvocationAttributes": { + "EventText": "BankAccountSelected" + }, + "ResponseValidation": { + "ResponseType": "JSON" + } }, - "Identifier": "Account Number Validation Error", - "Type": "MessageParticipant", + "Identifier": "Report Bank Account Selected Again", + "Type": "InvokeLambdaFunction", "Transitions": { - "NextAction": "Get & Encrypt Account Number", + "NextAction": "Submit Payment", "Errors": [ { - "NextAction": "Get & Encrypt Account Number", + "NextAction": "Submit Payment", "ErrorType": "NoMatchingError" } ] @@ -2743,73 +2904,65 @@ }, { "Parameters": { - "ComparisonValue": "$.StoredCustomerInput" + "LambdaFunctionARN": "<>", + "InvocationTimeLimitSeconds": "8", + "LambdaInvocationAttributes": { + "EventText": "CreditCardSelected" + }, + "ResponseValidation": { + "ResponseType": "JSON" + } }, - "Identifier": "Account Number Timeout Check", - "Type": "Compare", + "Identifier": "Report Credit Card Selected Again", + "Type": "InvokeLambdaFunction", "Transitions": { - "NextAction": "Validate Account Number", - "Conditions": [ - { - "NextAction": "Account Number Timeout", - "Condition": { - "Operator": "Equals", - "Operands": ["Timeout"] - } - } - ], + "NextAction": "Submit Payment", "Errors": [ { - "NextAction": "Validate Account Number", - "ErrorType": "NoMatchingCondition" + "NextAction": "Submit Payment", + "ErrorType": "NoMatchingError" } ] } }, { "Parameters": { - "ComparisonValue": "$.External.ValidationError" + "LambdaFunctionARN": "<>", + "InvocationTimeLimitSeconds": "8", + "ResponseValidation": { + "ResponseType": "JSON" + } }, - "Identifier": "Check for Account Number Validation Error", - "Type": "Compare", + "Identifier": "Tokenize Transaction", + "Type": "InvokeLambdaFunction", "Transitions": { - "NextAction": "Account Number Validation Error", - "Conditions": [ - { - "NextAction": "Store Encrypted Account Number", - "Condition": { - "Operator": "Equals", - "Operands": ["NULL"] - } - } - ], + "NextAction": "Check for Tokenize Error", "Errors": [ { - "NextAction": "Account Number Validation Error", - "ErrorType": "NoMatchingCondition" + "NextAction": "Report Tokenization Error", + "ErrorType": "NoMatchingError" } ] } }, { "Parameters": { - "LambdaFunctionARN": "<>", + "LambdaFunctionARN": "<>", "InvocationTimeLimitSeconds": "8", "LambdaInvocationAttributes": { - "ValidationType": "AccountNumber", - "CustomerEntry": "$.StoredCustomerInput" + "EventText": "TokenizationError" }, "ResponseValidation": { "ResponseType": "JSON" } }, - "Identifier": "Validate Account Number", + "Identifier": "Report Tokenization Error", "Type": "InvokeLambdaFunction", "Transitions": { - "NextAction": "Check for Account Number Validation Error", + "NextAction": "Payment Validation Error", "Errors": [ { - "NextAction": "Store Encrypted Account Number", + "NextAction": "Payment Validation Error", "ErrorType": "NoMatchingError" } ] @@ -2817,18 +2970,15 @@ }, { "Parameters": { - "Attributes": { - "RoutingNumber": "$.StoredCustomerInput" - }, - "TargetContact": "Current" + "Text": "\n>\" rate=\"<>\">\nThere was a problem validating your $.Attributes.PaymentMethod information.\n\n" }, - "Identifier": "Store Routing Number", - "Type": "UpdateContactAttributes", + "Identifier": "Payment Validation Error", + "Type": "MessageParticipant", "Transitions": { - "NextAction": "Report Routing Number Entered", + "NextAction": "Remove Failed Payment Token and Method", "Errors": [ { - "NextAction": "Report Routing Number Error", + "NextAction": "Remove Failed Payment Token and Method", "ErrorType": "NoMatchingError" } ] @@ -2836,15 +2986,20 @@ }, { "Parameters": { - "Text": "\n>\" rate=\"<>\">\n$.External.ValidationError\n\nPlease check your entry and try again.\n\n" + "Attributes": { + "TransactionId": "$.External.TransactionId", + "PaymentMethodEndingDigits": "$.External.PaymentMethodEndingDigits", + "TransactionIds": "$.External.TransactionId" + }, + "TargetContact": "Current" }, - "Identifier": "Routing Number Validation Error", - "Type": "MessageParticipant", + "Identifier": "Record Transaction Attributes", + "Type": "UpdateContactAttributes", "Transitions": { - "NextAction": "Get Routing Number", + "NextAction": "Report Payment Processed", "Errors": [ { - "NextAction": "Get Routing Number", + "NextAction": "Report Payment Processed", "ErrorType": "NoMatchingError" } ] @@ -2852,24 +3007,24 @@ }, { "Parameters": { - "ComparisonValue": "$.StoredCustomerInput" + "ComparisonValue": "$.External.Error" }, - "Identifier": "Routing Number Timeout Check", + "Identifier": "Check for Submit Payment Error", "Type": "Compare", "Transitions": { - "NextAction": "Validate Routing Number", + "NextAction": "Speak Payment Submission Error", "Conditions": [ { - "NextAction": "Routing Number Timeout", + "NextAction": "Record Transaction Attributes", "Condition": { "Operator": "Equals", - "Operands": ["Timeout"] + "Operands": ["NULL"] } } ], "Errors": [ { - "NextAction": "Validate Routing Number", + "NextAction": "Speak Payment Submission Error", "ErrorType": "NoMatchingCondition" } ] @@ -2877,48 +3032,38 @@ }, { "Parameters": { - "ComparisonValue": "$.External.ValidationError" + "Text": "\n>\" rate=\"<>\">\nThe payment failed to submit because of the following error:\n\n$.External.Error\n\nYou have not been charged.\n\n" }, - "Identifier": "Check for Routing Number Validation Error", - "Type": "Compare", + "Identifier": "Speak Payment Submission Error", + "Type": "MessageParticipant", "Transitions": { - "NextAction": "Routing Number Validation Error", - "Conditions": [ - { - "NextAction": "Store Routing Number", - "Condition": { - "Operator": "Equals", - "Operands": ["NULL"] - } - } - ], + "NextAction": "Report Payment Submission Error", "Errors": [ { - "NextAction": "Routing Number Validation Error", - "ErrorType": "NoMatchingCondition" + "NextAction": "Report Payment Submission Error", + "ErrorType": "NoMatchingError" } ] } }, { "Parameters": { - "LambdaFunctionARN": "<>", + "LambdaFunctionARN": "<>", "InvocationTimeLimitSeconds": "8", "LambdaInvocationAttributes": { - "ValidationType": "RoutingNumber", - "CustomerEntry": "$.StoredCustomerInput" + "EventText": "$.External.Error" }, "ResponseValidation": { "ResponseType": "JSON" } }, - "Identifier": "Validate Routing Number", + "Identifier": "Report Payment Submission Error", "Type": "InvokeLambdaFunction", "Transitions": { - "NextAction": "Check for Routing Number Validation Error", + "NextAction": "Remove Failed Payment Token and Method", "Errors": [ { - "NextAction": "Store Routing Number", + "NextAction": "Remove Failed Payment Token and Method", "ErrorType": "NoMatchingError" } ] @@ -2926,15 +3071,15 @@ }, { "Parameters": { - "Text": "\n>\" rate=\"<>\">\nAre you still there?\n\n" + "Text": "\n>\" rate=\"<>\">\nThe payment failed to submit because of an unknown error. You have not been charged.\n\n" }, - "Identifier": "Expiration Date Timeout", + "Identifier": "Speak Paymen Submission Unknown Error", "Type": "MessageParticipant", "Transitions": { - "NextAction": "Get Expiration Date", + "NextAction": "Remove Failed Payment Token and Method", "Errors": [ { - "NextAction": "Get Expiration Date", + "NextAction": "Remove Failed Payment Token and Method", "ErrorType": "NoMatchingError" } ] @@ -2942,26 +3087,19 @@ }, { "Parameters": { - "StoreInput": "True", - "InputTimeLimitSeconds": "5", - "Text": "\n>\" rate=\"<>\">\nPlease enter your card's expiration date in the format month-month-year-year, followed by the pound key when complete.\n\n", - "DTMFConfiguration": { - "DisableCancelKey": "False", - "InputTerminationSequence": "#" - }, - "InputValidation": { - "CustomValidation": { - "MaximumLength": "4" - } + "LambdaFunctionARN": "<>", + "InvocationTimeLimitSeconds": "8", + "ResponseValidation": { + "ResponseType": "JSON" } }, - "Identifier": "Get Expiration Date", - "Type": "GetParticipantInput", + "Identifier": "Submit Payment", + "Type": "InvokeLambdaFunction", "Transitions": { - "NextAction": "Expiration Date Timeout Check", + "NextAction": "Check for Submit Payment Error", "Errors": [ { - "NextAction": "Try Expiration Date Again", + "NextAction": "Report Payment Submission Unknown Error", "ErrorType": "NoMatchingError" } ] @@ -2969,18 +3107,22 @@ }, { "Parameters": { - "Attributes": { - "ExpirationDate": "$.StoredCustomerInput" + "LambdaFunctionARN": "<>", + "InvocationTimeLimitSeconds": "8", + "LambdaInvocationAttributes": { + "EventText": "PaymentSubmissionError" }, - "TargetContact": "Current" + "ResponseValidation": { + "ResponseType": "JSON" + } }, - "Identifier": "Store Expiration Date", - "Type": "UpdateContactAttributes", + "Identifier": "Report Payment Submission Unknown Error", + "Type": "InvokeLambdaFunction", "Transitions": { - "NextAction": "Report Expiration Entered", + "NextAction": "Speak Paymen Submission Unknown Error", "Errors": [ { - "NextAction": "Report Expiration Date Error", + "NextAction": "Speak Paymen Submission Unknown Error", "ErrorType": "NoMatchingError" } ] @@ -2988,15 +3130,15 @@ }, { "Parameters": { - "Text": "\n>\" rate=\"<>\">\n$.External.ValidationError\n\nPlease check your entry and try again.\n\n" + "Text": "\n>\" rate=\"<>\">\nThe payment failed because of the following error:\n\n$.External.Error\n\n" }, - "Identifier": "Expiration Date Validation Error", + "Identifier": "Speak Validation Error", "Type": "MessageParticipant", "Transitions": { - "NextAction": "Get Expiration Date", + "NextAction": "Report Validation Error", "Errors": [ { - "NextAction": "Get Expiration Date", + "NextAction": "Report Validation Error", "ErrorType": "NoMatchingError" } ] @@ -3004,73 +3146,42 @@ }, { "Parameters": { - "ComparisonValue": "$.StoredCustomerInput" - }, - "Identifier": "Expiration Date Timeout Check", - "Type": "Compare", - "Transitions": { - "NextAction": "Validate Expiration Date", - "Conditions": [ - { - "NextAction": "Expiration Date Timeout", - "Condition": { - "Operator": "Equals", - "Operands": ["Timeout"] - } - } - ], - "Errors": [ - { - "NextAction": "Validate Expiration Date", - "ErrorType": "NoMatchingCondition" - } - ] - } - }, - { - "Parameters": { - "ComparisonValue": "$.External.ValidationError" + "Attributes": { + "PaymentToken": "NULL", + "PaymentMethod": "NULL" + }, + "TargetContact": "Current" }, - "Identifier": "Check for Expiration Date Validation Error", - "Type": "Compare", + "Identifier": "Remove Failed Payment Token and Method", + "Type": "UpdateContactAttributes", "Transitions": { - "NextAction": "Expiration Date Validation Error", - "Conditions": [ - { - "NextAction": "Store Expiration Date", - "Condition": { - "Operator": "Equals", - "Operands": ["NULL"] - } - } - ], + "NextAction": "Redact Sensitive Contact Attributes", "Errors": [ { - "NextAction": "Expiration Date Validation Error", - "ErrorType": "NoMatchingCondition" + "NextAction": "Redact Sensitive Contact Attributes", + "ErrorType": "NoMatchingError" } ] } }, { "Parameters": { - "LambdaFunctionARN": "<>", + "LambdaFunctionARN": "<>", "InvocationTimeLimitSeconds": "8", "LambdaInvocationAttributes": { - "ValidationType": "ExpirationDate", - "CustomerEntry": "$.StoredCustomerInput" + "EventText": "$.External.Error" }, "ResponseValidation": { "ResponseType": "JSON" } }, - "Identifier": "Validate Expiration Date", + "Identifier": "Report Validation Error", "Type": "InvokeLambdaFunction", "Transitions": { - "NextAction": "Check for Expiration Date Validation Error", + "NextAction": "Remove Failed Payment Token and Method", "Errors": [ { - "NextAction": "Store Expiration Date", + "NextAction": "Remove Failed Payment Token and Method", "ErrorType": "NoMatchingError" } ] diff --git a/lib/connect/flows/c3-receipt-flow.json b/lib/connect/flows/c3-receipt-flow.json new file mode 100644 index 0000000..786eb7b --- /dev/null +++ b/lib/connect/flows/c3-receipt-flow.json @@ -0,0 +1,471 @@ +{ + "Version": "2019-10-30", + "StartAction": "f50d211b-96c7-43f0-9f4f-2204e1301fad", + "Metadata": { + "entryPointPosition": { + "x": -868, + "y": -75.2 + }, + "ActionMetadata": { + "Report Transactions Found": { + "position": { + "x": -260, + "y": -80.8 + }, + "isFriendlyName": true, + "parameters": { + "LambdaFunctionARN": { + "displayName": "<>" + } + }, + "dynamicMetadata": { + "EventText": false + } + }, + "Report No Transactions Error": { + "position": { + "x": -259.2, + "y": 128.8 + }, + "isFriendlyName": true, + "parameters": { + "LambdaFunctionARN": { + "displayName": "<>" + } + }, + "dynamicMetadata": { + "EventText": false + } + }, + "No Transactions": { + "position": { + "x": -37.6, + "y": 119.2 + }, + "isFriendlyName": true + }, + "13e17aab-f89b-4dc8-8040-4b8e2e4555df": { + "position": { + "x": 937.6, + "y": 180 + } + }, + "Check for Email Address": { + "position": { + "x": -36, + "y": -83.2 + }, + "isFriendlyName": true, + "conditions": [], + "conditionMetadata": [ + { + "id": "7c231476-858b-4909-b603-85f88b6cd074", + "operator": { + "name": "Contains", + "value": "Contains", + "shortDisplay": "contains" + }, + "value": "@" + } + ] + }, + "No Email Address": { + "position": { + "x": 416.8, + "y": 27.2 + }, + "isFriendlyName": true + }, + "Report No Email Address Error": { + "position": { + "x": 193.6, + "y": 28.8 + }, + "isFriendlyName": true, + "parameters": { + "LambdaFunctionARN": { + "displayName": "<>" + } + }, + "dynamicMetadata": { + "EventText": false + } + }, + "Check for Transactions": { + "position": { + "x": -492, + "y": -83.2 + }, + "isFriendlyName": true, + "conditions": [], + "conditionMetadata": [ + { + "id": "aa288c83-76ec-4cfe-a5cd-b06e70578a93", + "operator": { + "name": "Contains", + "value": "Contains", + "shortDisplay": "contains" + }, + "value": "\"" + } + ] + }, + "Conference All": { + "position": { + "x": -724.8, + "y": -94.4 + }, + "isFriendlyName": true + }, + "f50d211b-96c7-43f0-9f4f-2204e1301fad": { + "position": { + "x": -870.4, + "y": 105.6 + } + }, + "Report Receipt Error": { + "position": { + "x": 631.2, + "y": -84 + }, + "isFriendlyName": true, + "parameters": { + "LambdaFunctionARN": { + "displayName": "<>" + } + }, + "dynamicMetadata": { + "EventText": false + } + }, + "Report Receipts Sent": { + "position": { + "x": 632, + "y": -267.2 + }, + "isFriendlyName": true, + "parameters": { + "LambdaFunctionARN": { + "displayName": "<>" + } + }, + "dynamicMetadata": { + "EventText": false + } + }, + "Report Sending Receipts": { + "position": { + "x": 178.4, + "y": -218.4 + }, + "isFriendlyName": true, + "parameters": { + "LambdaFunctionARN": { + "displayName": "<>" + } + }, + "dynamicMetadata": { + "EventText": false + } + }, + "Send Receipts": { + "position": { + "x": 400.8, + "y": -221.6 + }, + "isFriendlyName": true, + "parameters": { + "LambdaFunctionARN": { + "displayName": "<>" + } + }, + "dynamicMetadata": { + "SendAll": false + } + } + }, + "Annotations": [], + "name": "C3 Receipt Flow", + "description": "Flow to send payment receipts in the agent workspace.", + "type": "queueTransfer", + "status": "PUBLISHED", + "hash": {} + }, + "Actions": [ + { + "Parameters": { + "LambdaFunctionARN": "<>", + "InvocationTimeLimitSeconds": "8", + "LambdaInvocationAttributes": { + "EventText": "TransactionsFound" + }, + "ResponseValidation": { + "ResponseType": "JSON" + } + }, + "Identifier": "Report Transactions Found", + "Type": "InvokeLambdaFunction", + "Transitions": { + "NextAction": "Check for Email Address", + "Errors": [ + { + "NextAction": "Check for Email Address", + "ErrorType": "NoMatchingError" + } + ] + } + }, + { + "Parameters": { + "LambdaFunctionARN": "<>", + "InvocationTimeLimitSeconds": "8", + "LambdaInvocationAttributes": { + "EventText": "NoTransactionsError" + }, + "ResponseValidation": { + "ResponseType": "JSON" + } + }, + "Identifier": "Report No Transactions Error", + "Type": "InvokeLambdaFunction", + "Transitions": { + "NextAction": "No Transactions", + "Errors": [ + { + "NextAction": "No Transactions", + "ErrorType": "NoMatchingError" + } + ] + } + }, + { + "Parameters": { + "Text": "\n>\" rate=\"<>\">\nThere are no completed transactions for this customer. Please check that the customer has made a payment on this same call.\n\n" + }, + "Identifier": "No Transactions", + "Type": "MessageParticipant", + "Transitions": { + "NextAction": "13e17aab-f89b-4dc8-8040-4b8e2e4555df", + "Errors": [ + { + "NextAction": "13e17aab-f89b-4dc8-8040-4b8e2e4555df", + "ErrorType": "NoMatchingError" + } + ] + } + }, + { + "Parameters": {}, + "Identifier": "13e17aab-f89b-4dc8-8040-4b8e2e4555df", + "Type": "DisconnectParticipant", + "Transitions": {} + }, + { + "Parameters": { + "ComparisonValue": "$.Attributes.Email" + }, + "Identifier": "Check for Email Address", + "Type": "Compare", + "Transitions": { + "NextAction": "Report No Email Address Error", + "Conditions": [ + { + "NextAction": "Report Sending Receipts", + "Condition": { + "Operator": "TextContains", + "Operands": ["@"] + } + } + ], + "Errors": [ + { + "NextAction": "Report No Email Address Error", + "ErrorType": "NoMatchingCondition" + } + ] + } + }, + { + "Parameters": { + "Text": "\n>\" rate=\"<>\">\nThere is no email address for this customer. Please provide one in the C3 Receipt app and try again.\n\n" + }, + "Identifier": "No Email Address", + "Type": "MessageParticipant", + "Transitions": { + "NextAction": "13e17aab-f89b-4dc8-8040-4b8e2e4555df", + "Errors": [ + { + "NextAction": "13e17aab-f89b-4dc8-8040-4b8e2e4555df", + "ErrorType": "NoMatchingError" + } + ] + } + }, + { + "Parameters": { + "LambdaFunctionARN": "<>", + "InvocationTimeLimitSeconds": "8", + "LambdaInvocationAttributes": { + "EventText": "NoEmailAddressError" + }, + "ResponseValidation": { + "ResponseType": "JSON" + } + }, + "Identifier": "Report No Email Address Error", + "Type": "InvokeLambdaFunction", + "Transitions": { + "NextAction": "No Email Address", + "Errors": [ + { + "NextAction": "No Email Address", + "ErrorType": "NoMatchingError" + } + ] + } + }, + { + "Parameters": { + "ComparisonValue": "$.Attributes.TransactionIds" + }, + "Identifier": "Check for Transactions", + "Type": "Compare", + "Transitions": { + "NextAction": "Report No Transactions Error", + "Conditions": [ + { + "NextAction": "Report Transactions Found", + "Condition": { + "Operator": "TextContains", + "Operands": ["\""] + } + } + ], + "Errors": [ + { + "NextAction": "Report No Transactions Error", + "ErrorType": "NoMatchingCondition" + } + ] + } + }, + { + "Parameters": { + "PreviousContactParticipantState": "OffHold" + }, + "Identifier": "Conference All", + "Type": "UpdatePreviousContactParticipantState", + "Transitions": { + "NextAction": "Check for Transactions", + "Errors": [ + { + "NextAction": "Check for Transactions", + "ErrorType": "NoMatchingError" + } + ] + } + }, + { + "Parameters": { + "FlowLoggingBehavior": "Enabled" + }, + "Identifier": "f50d211b-96c7-43f0-9f4f-2204e1301fad", + "Type": "UpdateFlowLoggingBehavior", + "Transitions": { + "NextAction": "Conference All" + } + }, + { + "Parameters": { + "LambdaFunctionARN": "<>", + "InvocationTimeLimitSeconds": "8", + "LambdaInvocationAttributes": { + "EventText": "SendReceiptError" + }, + "ResponseValidation": { + "ResponseType": "JSON" + } + }, + "Identifier": "Report Receipt Error", + "Type": "InvokeLambdaFunction", + "Transitions": { + "NextAction": "13e17aab-f89b-4dc8-8040-4b8e2e4555df", + "Errors": [ + { + "NextAction": "13e17aab-f89b-4dc8-8040-4b8e2e4555df", + "ErrorType": "NoMatchingError" + } + ] + } + }, + { + "Parameters": { + "LambdaFunctionARN": "<>", + "InvocationTimeLimitSeconds": "8", + "LambdaInvocationAttributes": { + "EventText": "ReceiptsSent" + }, + "ResponseValidation": { + "ResponseType": "JSON" + } + }, + "Identifier": "Report Receipts Sent", + "Type": "InvokeLambdaFunction", + "Transitions": { + "NextAction": "13e17aab-f89b-4dc8-8040-4b8e2e4555df", + "Errors": [ + { + "NextAction": "13e17aab-f89b-4dc8-8040-4b8e2e4555df", + "ErrorType": "NoMatchingError" + } + ] + } + }, + { + "Parameters": { + "LambdaFunctionARN": "<>", + "InvocationTimeLimitSeconds": "8", + "LambdaInvocationAttributes": { + "EventText": "SendingReceipts" + }, + "ResponseValidation": { + "ResponseType": "JSON" + } + }, + "Identifier": "Report Sending Receipts", + "Type": "InvokeLambdaFunction", + "Transitions": { + "NextAction": "Send Receipts", + "Errors": [ + { + "NextAction": "Send Receipts", + "ErrorType": "NoMatchingError" + } + ] + } + }, + { + "Parameters": { + "LambdaFunctionARN": "<>", + "InvocationTimeLimitSeconds": "8", + "LambdaInvocationAttributes": { + "SendAll": "true" + }, + "ResponseValidation": { + "ResponseType": "JSON" + } + }, + "Identifier": "Send Receipts", + "Type": "InvokeLambdaFunction", + "Transitions": { + "NextAction": "Report Receipts Sent", + "Errors": [ + { + "NextAction": "Report Receipt Error", + "ErrorType": "NoMatchingError" + } + ] + } + } + ] +} diff --git a/lib/connect/flows/modules/c3-payment-ivr-flow-module.json b/lib/connect/flows/modules/c3-payment-ivr-flow-module.json index 5e6eff5..3d81df8 100644 --- a/lib/connect/flows/modules/c3-payment-ivr-flow-module.json +++ b/lib/connect/flows/modules/c3-payment-ivr-flow-module.json @@ -7,14 +7,6 @@ "y": 231.2 }, "ActionMetadata": { - "Record Token": { - "position": { - "x": 5877.6, - "y": -299.2 - }, - "isFriendlyName": true, - "dynamicParams": [] - }, "b2786200-e897-45bd-b888-0f53246f72ed": { "position": { "x": -748.8, @@ -87,7 +79,7 @@ "conditions": [], "conditionMetadata": [ { - "id": "fbb7b741-79e8-4bbf-80c6-f637db1187eb", + "id": "b3c87725-e30d-4f80-b5c5-b7787691a94b", "operator": { "name": "Equals", "value": "Equals", @@ -96,7 +88,7 @@ "value": "Timeout" }, { - "id": "e800a29f-47a5-439c-a1ba-3518abca5dd6", + "id": "0fb4b498-807b-4071-ab9f-21c90348b3a7", "operator": { "name": "Is greater than", "value": "GreaterThan", @@ -105,7 +97,7 @@ "value": "$.Attributes.PaymentAmountDue" }, { - "id": "d5ba66bb-6326-4524-b61d-f6166be11a6c", + "id": "0832b707-bc38-4d83-bf93-f81c3a5ac86b", "operator": { "name": "Is less than", "value": "LessThan", @@ -115,47 +107,6 @@ } ] }, - "Get Payment Amount": { - "position": { - "x": 60.8, - "y": -46.4 - }, - "isFriendlyName": true, - "conditionMetadata": [], - "countryCodePrefix": "+1" - }, - "Use Card Again?": { - "position": { - "x": 1289.6, - "y": -720 - }, - "isFriendlyName": true, - "conditionMetadata": [ - { - "id": "2672653b-67d6-4be2-8417-3ca598c7b68d", - "value": "1" - }, - { - "id": "e3075be3-bafa-4dd7-8015-61175164dde0", - "value": "2" - } - ] - }, - "Set Payment Amount to Entered Amount": { - "position": { - "x": 452, - "y": -34.4 - }, - "isFriendlyName": true, - "parameters": { - "Attributes": { - "PaymentAmount": { - "useDynamic": true - } - } - }, - "dynamicParams": ["PaymentAmount"] - }, "Use Payment Method Again Timeout": { "position": { "x": 1083.2, @@ -171,28 +122,11 @@ "isFriendlyName": true, "conditionMetadata": [ { - "id": "fc508a3c-975c-45dd-921f-ec913ac5559b", - "value": "1" - }, - { - "id": "a5c6ac9f-eaac-426e-bc19-c3603d63cc0c", - "value": "2" - } - ] - }, - "Use Bank Account Again?": { - "position": { - "x": 1410.4, - "y": -397.6 - }, - "isFriendlyName": true, - "conditionMetadata": [ - { - "id": "19f7fe11-d51f-4898-a7bd-7840fc909cdf", + "id": "ad270a42-6cd6-45d8-b2c8-fc8025488f8d", "value": "1" }, { - "id": "12db631d-2765-4086-a1c8-f64e27bac035", + "id": "113d4f98-c51b-45a5-9d10-b856d88c64da", "value": "2" } ] @@ -206,7 +140,7 @@ "conditions": [], "conditionMetadata": [ { - "id": "91f6a266-31b3-4053-a7b5-7e89b96ae6a0", + "id": "c43f713d-ec23-4ea5-b604-141384782cb6", "operator": { "name": "Equals", "value": "Equals", @@ -215,7 +149,7 @@ "value": "Card" }, { - "id": "7335bbf0-7873-4eb6-bf30-d6d2b502133a", + "id": "35e1e947-808f-42a0-9972-900aad9c0608", "operator": { "name": "Equals", "value": "Equals", @@ -248,7 +182,7 @@ "conditions": [], "conditionMetadata": [ { - "id": "838f3cf4-de91-4a72-ae32-ce0062f6ca38", + "id": "ce83234a-df4c-4018-b71d-3d0cdc4589eb", "operator": { "name": "Equals", "value": "Equals", @@ -257,7 +191,7 @@ "value": "PaymentAmountDue" }, { - "id": "68ff0418-d7a7-4462-a6ca-57070b7b0f4f", + "id": "89538b6b-474a-4194-bbaa-70a37deeb71e", "operator": { "name": "Is greater than", "value": "GreaterThan", @@ -274,21 +208,6 @@ }, "isFriendlyName": true }, - "Set Payment Amount to Full Amount": { - "position": { - "x": 468, - "y": 447.2 - }, - "isFriendlyName": true, - "parameters": { - "Attributes": { - "PaymentAmount": { - "useDynamic": true - } - } - }, - "dynamicParams": ["PaymentAmount"] - }, "Prompt for Payment Amount Choice": { "position": { "x": -479.2, @@ -297,11 +216,11 @@ "isFriendlyName": true, "conditionMetadata": [ { - "id": "d310b2e2-b48f-45eb-8d91-f60e260cbe07", + "id": "f30e307e-1d61-4425-b90b-886c1074c059", "value": "1" }, { - "id": "4ce16c76-b545-43f7-9011-4e3c8427f18f", + "id": "378c3ae5-b61a-4d75-81bb-9e976bbf307d", "value": "2" } ] @@ -321,15 +240,6 @@ }, "isFriendlyName": true }, - "Get & Encrypt Account Number": { - "position": { - "x": 2915.2, - "y": 106.4 - }, - "isFriendlyName": true, - "conditionMetadata": [], - "countryCodePrefix": "+1" - }, "Set Payment Method to Card": { "position": { "x": 2685.6, @@ -345,15 +255,6 @@ }, "isFriendlyName": true }, - "Get & Encrypt Card Number": { - "position": { - "x": 2907.2, - "y": -807.2 - }, - "isFriendlyName": true, - "conditionMetadata": [], - "countryCodePrefix": "+1" - }, "Routing Number Timeout": { "position": { "x": 4033.6, @@ -391,88 +292,6 @@ "conditionMetadata": [], "countryCodePrefix": "+1" }, - "Check for Tokenize Error": { - "position": { - "x": 5646.4, - "y": -300 - }, - "isFriendlyName": true, - "conditions": [], - "conditionMetadata": [ - { - "id": "3549ffbd-5bb2-4c96-8538-133bb1f04a02", - "operator": { - "name": "Equals", - "value": "Equals", - "shortDisplay": "=" - }, - "value": "NULL" - } - ] - }, - "Speak Validation Error": { - "position": { - "x": 5847.2, - "y": 235.2 - }, - "isFriendlyName": true - }, - "Tokenize Transaction": { - "position": { - "x": 5397.6, - "y": -304.8 - }, - "isFriendlyName": true, - "parameters": { - "LambdaFunctionARN": { - "displayName": "<>" - } - }, - "dynamicMetadata": {} - }, - "Payment Validation Error": { - "position": { - "x": 6692.8, - "y": 472 - }, - "isFriendlyName": true - }, - "Submit Payment": { - "position": { - "x": 6360.8, - "y": -295.2 - }, - "isFriendlyName": true, - "parameters": { - "LambdaFunctionARN": { - "displayName": "<>" - } - }, - "dynamicMetadata": {} - }, - "Remove Failed Payment Token and Method": { - "position": { - "x": 6968.8, - "y": 382.4 - }, - "isFriendlyName": true, - "dynamicParams": [] - }, - "Payment Submission Error": { - "position": { - "x": 6683.2, - "y": 229.6 - }, - "isFriendlyName": true - }, - "Record Transaction Attributes": { - "position": { - "x": 6600.8, - "y": -296.8 - }, - "isFriendlyName": true, - "dynamicParams": [] - }, "Check for Customer Email": { "position": { "x": 7265.6, @@ -482,7 +301,7 @@ "conditions": [], "conditionMetadata": [ { - "id": "ee2d8bda-581a-4f47-9f97-891b4c74f2b3", + "id": "8fe0b2de-1f8a-4b03-9ca5-144b94f7360a", "operator": { "name": "Contains", "value": "Contains", @@ -492,13 +311,6 @@ } ] }, - "Payment Success": { - "position": { - "x": 7044, - "y": -211.2 - }, - "isFriendlyName": true - }, "Redact Sensitive Contact Attributes Copy": { "position": { "x": 8241.6, @@ -516,7 +328,7 @@ "conditions": [], "conditionMetadata": [ { - "id": "32d9fe15-7110-4fcb-864c-61cdddd67f7d", + "id": "9d9bdb40-a7e8-4266-92c7-612e75cf47c4", "operator": { "name": "Equals", "value": "Equals", @@ -548,11 +360,11 @@ "isFriendlyName": true, "conditionMetadata": [ { - "id": "9fb530c0-45f4-4b9c-8e4e-6a3ab0e7b3e3", + "id": "879c99ba-1774-4fef-b530-d0c81c7b4ba9", "value": "1" }, { - "id": "b388dbec-8ef6-4090-a10f-9fec43d97016", + "id": "d1b69330-c104-4fed-85d9-324d9559e1a4", "value": "2" } ] @@ -577,14 +389,6 @@ }, "dynamicMetadata": {} }, - "Redact Sensitive Contact Attributes": { - "position": { - "x": 8200, - "y": 86.4 - }, - "isFriendlyName": true, - "dynamicParams": [] - }, "Receipt Error": { "position": { "x": 7777.6, @@ -660,7 +464,7 @@ "conditions": [], "conditionMetadata": [ { - "id": "096a7918-993a-48ec-a206-95f2e325f217", + "id": "3240b95a-17f3-4030-a58d-75701333329b", "operator": { "name": "Equals", "value": "Equals", @@ -677,21 +481,6 @@ }, "isFriendlyName": true }, - "Store Encrypted Card Number": { - "position": { - "x": 3570.4, - "y": -817.6 - }, - "isFriendlyName": true, - "parameters": { - "Attributes": { - "EncryptedCardNumber": { - "useDynamic": true - } - } - }, - "dynamicParams": ["EncryptedCardNumber"] - }, "Validate Card Number": { "position": { "x": 3139.2, @@ -722,7 +511,7 @@ "conditions": [], "conditionMetadata": [ { - "id": "4079afa6-5af7-451c-b7de-21a6dcfec9cc", + "id": "388108e8-644a-4969-9ebc-37ddeb457bbc", "operator": { "name": "Equals", "value": "Equals", @@ -741,7 +530,7 @@ "conditions": [], "conditionMetadata": [ { - "id": "835afd0a-3a9b-42f7-8da1-5c7b0217983b", + "id": "dddf5257-9e8f-4019-9b75-50ded0538188", "operator": { "name": "Equals", "value": "Equals", @@ -758,13 +547,6 @@ }, "isFriendlyName": true }, - "Internal Error": { - "position": { - "x": 2711.2, - "y": 773.6 - }, - "isFriendlyName": true - }, "Get Routing Number": { "position": { "x": 4123.2, @@ -804,7 +586,7 @@ "conditions": [], "conditionMetadata": [ { - "id": "caff22e3-dc17-46d8-8c9c-4fbc87bbf60f", + "id": "a5d93225-0213-41a9-b347-80f11dd4b5d3", "operator": { "name": "Equals", "value": "Equals", @@ -814,36 +596,6 @@ } ] }, - "Store Encrypted Account Number": { - "position": { - "x": 3565.6, - "y": 100.8 - }, - "isFriendlyName": true, - "parameters": { - "Attributes": { - "EncryptedAccountNumber": { - "useDynamic": true - } - } - }, - "dynamicParams": ["EncryptedAccountNumber"] - }, - "Store Routing Number": { - "position": { - "x": 4786.4, - "y": 88 - }, - "isFriendlyName": true, - "parameters": { - "Attributes": { - "RoutingNumber": { - "useDynamic": true - } - } - }, - "dynamicParams": ["RoutingNumber"] - }, "Routing Number Validation Error": { "position": { "x": 4427.2, @@ -860,7 +612,7 @@ "conditions": [], "conditionMetadata": [ { - "id": "63497af9-b1d6-4e68-8fdc-f52f1bbd423d", + "id": "6eeffb2a-60a1-430a-8de7-ced59432d3ac", "operator": { "name": "Equals", "value": "Equals", @@ -879,7 +631,7 @@ "conditions": [], "conditionMetadata": [ { - "id": "dcea6e50-4c52-4a27-b07b-d8e05a25d9c1", + "id": "d1e1810c-e9aa-45cd-a4e9-03c007955350", "operator": { "name": "Equals", "value": "Equals", @@ -910,21 +662,6 @@ "CustomerEntry": true } }, - "Store Expiration Date": { - "position": { - "x": 4842.4, - "y": -732.8 - }, - "isFriendlyName": true, - "parameters": { - "Attributes": { - "ExpirationDate": { - "useDynamic": true - } - } - }, - "dynamicParams": ["ExpirationDate"] - }, "Expiration Date Validation Error": { "position": { "x": 4470.4, @@ -941,7 +678,7 @@ "conditions": [], "conditionMetadata": [ { - "id": "2f922546-5cd7-405c-9a55-af3ed8b5957a", + "id": "db6441c0-f2b2-4cde-b0f8-27559c14b33a", "operator": { "name": "Equals", "value": "Equals", @@ -960,7 +697,7 @@ "conditions": [], "conditionMetadata": [ { - "id": "1c91b217-46a0-4ee6-be8e-f0418c4b9c6c", + "id": "9016c485-d4d3-47a2-8d36-88fd710631fa", "operator": { "name": "Equals", "value": "Equals", @@ -990,13 +727,301 @@ "ValidationType": false, "CustomerEntry": true } - } - }, - "Annotations": [ - { - "type": "default", - "id": "3488450f-b48c-41aa-a37e-e3b430d5f199", - "content": "This needs to be done because a user-defined value for the Set Working Queue block type doesn't seem to work?", + }, + "Get Payment Amount": { + "position": { + "x": 60.8, + "y": -46.4 + }, + "isFriendlyName": true, + "conditionMetadata": [], + "countryCodePrefix": "+1" + }, + "Set Payment Amount to Entered Amount": { + "position": { + "x": 452, + "y": -34.4 + }, + "isFriendlyName": true, + "parameters": { + "Attributes": { + "PaymentAmount": { + "useDynamic": true + } + } + }, + "dynamicParams": ["PaymentAmount"] + }, + "Set Payment Amount to Full Amount": { + "position": { + "x": 468, + "y": 447.2 + }, + "isFriendlyName": true, + "parameters": { + "Attributes": { + "PaymentAmount": { + "useDynamic": true + } + } + }, + "dynamicParams": ["PaymentAmount"] + }, + "Get & Encrypt Account Number": { + "position": { + "x": 2915.2, + "y": 106.4 + }, + "isFriendlyName": true, + "conditionMetadata": [], + "countryCodePrefix": "+1" + }, + "Get & Encrypt Card Number": { + "position": { + "x": 2907.2, + "y": -807.2 + }, + "isFriendlyName": true, + "conditionMetadata": [], + "countryCodePrefix": "+1" + }, + "Redact Sensitive Contact Attributes": { + "position": { + "x": 8200, + "y": 86.4 + }, + "isFriendlyName": true, + "dynamicParams": [] + }, + "Store Encrypted Card Number": { + "position": { + "x": 3570.4, + "y": -817.6 + }, + "isFriendlyName": true, + "parameters": { + "Attributes": { + "EncryptedCardNumber": { + "useDynamic": true + } + } + }, + "dynamicParams": ["EncryptedCardNumber"] + }, + "Store Encrypted Account Number": { + "position": { + "x": 3565.6, + "y": 100.8 + }, + "isFriendlyName": true, + "parameters": { + "Attributes": { + "EncryptedAccountNumber": { + "useDynamic": true + } + } + }, + "dynamicParams": ["EncryptedAccountNumber"] + }, + "Store Routing Number": { + "position": { + "x": 4786.4, + "y": 88 + }, + "isFriendlyName": true, + "parameters": { + "Attributes": { + "RoutingNumber": { + "useDynamic": true + } + } + }, + "dynamicParams": ["RoutingNumber"] + }, + "Store Expiration Date": { + "position": { + "x": 4842.4, + "y": -732.8 + }, + "isFriendlyName": true, + "parameters": { + "Attributes": { + "ExpirationDate": { + "useDynamic": true + } + } + }, + "dynamicParams": ["ExpirationDate"] + }, + "Internal Error": { + "position": { + "x": 2711.2, + "y": 773.6 + }, + "isFriendlyName": true + }, + "Speak Validation Error": { + "position": { + "x": 5846.4, + "y": 234.4 + }, + "isFriendlyName": true + }, + "Check for Tokenize Error": { + "position": { + "x": 5646.4, + "y": -300 + }, + "isFriendlyName": true, + "conditions": [], + "conditionMetadata": [ + { + "id": "cf1b4038-9fdf-4271-8bb4-8b086887722d", + "operator": { + "name": "Equals", + "value": "Equals", + "shortDisplay": "=" + }, + "value": "NULL" + } + ] + }, + "Payment Success": { + "position": { + "x": 7044, + "y": -211.2 + }, + "isFriendlyName": true + }, + "Tokenize Transaction": { + "position": { + "x": 5397.6, + "y": -304.8 + }, + "isFriendlyName": true, + "parameters": { + "LambdaFunctionARN": { + "displayName": "<>" + } + }, + "dynamicMetadata": {} + }, + "Payment Validation Error": { + "position": { + "x": 6692.8, + "y": 472 + }, + "isFriendlyName": true + }, + "Use Card Again?": { + "position": { + "x": 1289.6, + "y": -720 + }, + "isFriendlyName": true, + "conditionMetadata": [ + { + "id": "d3dc0c90-0eff-4056-95c9-0b1825d94e2f", + "value": "1" + }, + { + "id": "ab6bf500-8ca4-4a98-b8dc-3ac9801e4cdf", + "value": "2" + } + ] + }, + "Use Bank Account Again?": { + "position": { + "x": 1410.4, + "y": -397.6 + }, + "isFriendlyName": true, + "conditionMetadata": [ + { + "id": "f7d270e1-4380-42e4-8790-4b9ed943c0f5", + "value": "1" + }, + { + "id": "8d691fe2-8388-49f0-8262-df69cca9a5d4", + "value": "2" + } + ] + }, + "Record Token": { + "position": { + "x": 5877.6, + "y": -299.2 + }, + "isFriendlyName": true, + "dynamicParams": [] + }, + "Record Transaction Attributes": { + "position": { + "x": 6752, + "y": -297.6 + }, + "isFriendlyName": true, + "dynamicParams": [] + }, + "Submit Payment": { + "position": { + "x": 6295.2, + "y": -303.2 + }, + "isFriendlyName": true, + "parameters": { + "LambdaFunctionARN": { + "displayName": "<>" + } + }, + "dynamicMetadata": {} + }, + "Speak Payment Submission Unknown Error": { + "position": { + "x": 6431.2, + "y": 13.6 + }, + "isFriendlyName": true + }, + "Check for Submit Payment Error": { + "position": { + "x": 6531.2, + "y": -299.2 + }, + "isFriendlyName": true, + "conditionMetadata": [ + { + "id": "c958368f-9f65-4dcc-9415-c4ddb97042ce", + "operator": { + "name": "Equals", + "value": "Equals", + "shortDisplay": "=" + }, + "value": "NULL" + } + ] + }, + "Remove Failed Payment Token and Method": { + "position": { + "x": 6968.8, + "y": 382.4 + }, + "isFriendlyName": true, + "dynamicParams": [] + }, + "Speak Payment Submission Error": { + "position": { + "x": 6681.6, + "y": 228 + }, + "isFriendlyName": true + } + }, + "Annotations": [ + { + "type": "default", + "id": "3488450f-b48c-41aa-a37e-e3b430d5f199", + "content": "This needs to be done because a user-defined value for the Set Working Queue block type doesn't seem to work?", "actionId": "Set Receipt Queue ID", "isFolded": true, "position": { @@ -1075,25 +1100,6 @@ "hash": {} }, "Actions": [ - { - "Parameters": { - "Attributes": { - "PaymentToken": "$.External.PaymentToken" - }, - "TargetContact": "Current" - }, - "Identifier": "Record Token", - "Type": "UpdateContactAttributes", - "Transitions": { - "NextAction": "Submit Payment", - "Errors": [ - { - "NextAction": "Submit Payment", - "ErrorType": "NoMatchingError" - } - ] - } - }, { "Parameters": {}, "Identifier": "b2786200-e897-45bd-b888-0f53246f72ed", @@ -1201,158 +1207,15 @@ }, { "Parameters": { - "Text": "\n>\" rate=\"<>\">\nAre you still there?\n\n" - }, - "Identifier": "Payment Method Timeout", - "Type": "MessageParticipant", - "Transitions": { - "NextAction": "Ask for Payment Method", - "Errors": [ - { - "NextAction": "Ask for Payment Method", - "ErrorType": "NoMatchingError" - } - ] - } - }, - { - "Parameters": { - "Text": "\n>\" rate=\"<>\">\nYour entry was not recognized. Please try again.\n\n" - }, - "Identifier": "Method Input Not Recognized", - "Type": "MessageParticipant", - "Transitions": { - "NextAction": "Ask for Payment Method", - "Errors": [ - { - "NextAction": "Ask for Payment Method", - "ErrorType": "NoMatchingError" - } - ] - } - }, - { - "Parameters": { - "ComparisonValue": "$.StoredCustomerInput" - }, - "Identifier": "Check Payment Amount", - "Type": "Compare", - "Transitions": { - "NextAction": "Set Payment Amount to Entered Amount", - "Conditions": [ - { - "NextAction": "Payment Amount Timeout", - "Condition": { - "Operator": "Equals", - "Operands": ["Timeout"] - } - }, - { - "NextAction": "Payment Too Large", - "Condition": { - "Operator": "NumberGreaterThan", - "Operands": ["$.Attributes.PaymentAmountDue"] - } - }, - { - "NextAction": "Payment Too Small", - "Condition": { - "Operator": "NumberLessThan", - "Operands": ["$.Attributes.PaymentMinimumPayment"] - } - } - ], - "Errors": [ - { - "NextAction": "Set Payment Amount to Entered Amount", - "ErrorType": "NoMatchingCondition" - } - ] - } - }, - { - "Parameters": { - "StoreInput": "True", - "InputTimeLimitSeconds": "5", - "Text": "\n>\" rate=\"<>\">\nPlease enter the amount you would like to pay in whole dollars, followed by the pound key.\n\n", - "DTMFConfiguration": { - "DisableCancelKey": "False", - "InputTerminationSequence": "#" - }, - "InputValidation": { - "CustomValidation": { - "MaximumLength": "20" - } - } - }, - "Identifier": "Get Payment Amount", - "Type": "GetParticipantInput", - "Transitions": { - "NextAction": "Check Payment Amount", - "Errors": [ - { - "NextAction": "Internal Error", - "ErrorType": "NoMatchingError" - } - ] - } - }, - { - "Parameters": { - "StoreInput": "False", - "InputTimeLimitSeconds": "5", - "Text": "\n>\" rate=\"<>\">\nYou previously paid with a credit or debit card ending in $.Attributes.PaymentMethodEndingDigits.\n\nIf you would like to use this card again for this payment, press 1.\nTo use a different payment method, press 2.\n\n" - }, - "Identifier": "Use Card Again?", - "Type": "GetParticipantInput", - "Transitions": { - "NextAction": "Ask for Payment Method", - "Conditions": [ - { - "NextAction": "Submit Payment", - "Condition": { - "Operator": "Equals", - "Operands": ["1"] - } - }, - { - "NextAction": "Ask for Payment Method", - "Condition": { - "Operator": "Equals", - "Operands": ["2"] - } - } - ], - "Errors": [ - { - "NextAction": "Use Payment Method Again Timeout", - "ErrorType": "InputTimeLimitExceeded" - }, - { - "NextAction": "Ask for Payment Method", - "ErrorType": "NoMatchingCondition" - }, - { - "NextAction": "Ask for Payment Method", - "ErrorType": "NoMatchingError" - } - ] - } - }, - { - "Parameters": { - "Attributes": { - "PaymentAmount": "$.StoredCustomerInput" - }, - "TargetContact": "Current" + "Text": "\n>\" rate=\"<>\">\nAre you still there?\n\n" }, - "Identifier": "Set Payment Amount to Entered Amount", - "Type": "UpdateContactAttributes", + "Identifier": "Payment Method Timeout", + "Type": "MessageParticipant", "Transitions": { - "NextAction": "Check Last Payment Method", + "NextAction": "Ask for Payment Method", "Errors": [ { - "NextAction": "Internal Error", + "NextAction": "Ask for Payment Method", "ErrorType": "NoMatchingError" } ] @@ -1360,15 +1223,15 @@ }, { "Parameters": { - "Text": "\n>\" rate=\"<>\">\nAre you still there?\n\n" + "Text": "\n>\" rate=\"<>\">\nYour entry was not recognized. Please try again.\n\n" }, - "Identifier": "Use Payment Method Again Timeout", + "Identifier": "Method Input Not Recognized", "Type": "MessageParticipant", "Transitions": { - "NextAction": "Check Last Payment Method", + "NextAction": "Ask for Payment Method", "Errors": [ { - "NextAction": "Check Last Payment Method", + "NextAction": "Ask for Payment Method", "ErrorType": "NoMatchingError" } ] @@ -1376,41 +1239,54 @@ }, { "Parameters": { - "StoreInput": "False", - "InputTimeLimitSeconds": "5", - "Text": "\n>\" rate=\"<>\">\nTo pay with a credit or debit card, press 1.\nTo pay directly with your bank account, press 2.\n\n" + "ComparisonValue": "$.StoredCustomerInput" }, - "Identifier": "Ask for Payment Method", - "Type": "GetParticipantInput", + "Identifier": "Check Payment Amount", + "Type": "Compare", "Transitions": { - "NextAction": "Method Input Not Recognized", + "NextAction": "Set Payment Amount to Entered Amount", "Conditions": [ { - "NextAction": "Set Payment Method to Card", + "NextAction": "Payment Amount Timeout", "Condition": { "Operator": "Equals", - "Operands": ["1"] + "Operands": ["Timeout"] } }, { - "NextAction": "Set Payment Method to Bank", + "NextAction": "Payment Too Large", "Condition": { - "Operator": "Equals", - "Operands": ["2"] + "Operator": "NumberGreaterThan", + "Operands": ["$.Attributes.PaymentAmountDue"] + } + }, + { + "NextAction": "Payment Too Small", + "Condition": { + "Operator": "NumberLessThan", + "Operands": ["$.Attributes.PaymentMinimumPayment"] } } ], "Errors": [ { - "NextAction": "Payment Method Timeout", - "ErrorType": "InputTimeLimitExceeded" - }, - { - "NextAction": "Method Input Not Recognized", + "NextAction": "Set Payment Amount to Entered Amount", "ErrorType": "NoMatchingCondition" - }, + } + ] + } + }, + { + "Parameters": { + "Text": "\n>\" rate=\"<>\">\nAre you still there?\n\n" + }, + "Identifier": "Use Payment Method Again Timeout", + "Type": "MessageParticipant", + "Transitions": { + "NextAction": "Check Last Payment Method", + "Errors": [ { - "NextAction": "Method Input Not Recognized", + "NextAction": "Check Last Payment Method", "ErrorType": "NoMatchingError" } ] @@ -1420,22 +1296,22 @@ "Parameters": { "StoreInput": "False", "InputTimeLimitSeconds": "5", - "Text": "\n>\" rate=\"<>\">\nYou previously paid with a bank account ending in $.Attributes.PaymentMethodEndingDigits.\n\nIf you would like to use this account again for this payment, press 1.\nTo use a different payment method, press 2.\n\n" + "Text": "\n>\" rate=\"<>\">\nTo pay with a credit or debit card, press 1.\nTo pay directly with your bank account, press 2.\n\n" }, - "Identifier": "Use Bank Account Again?", + "Identifier": "Ask for Payment Method", "Type": "GetParticipantInput", "Transitions": { - "NextAction": "Ask for Payment Method", + "NextAction": "Method Input Not Recognized", "Conditions": [ { - "NextAction": "Submit Payment", + "NextAction": "Set Payment Method to Card", "Condition": { "Operator": "Equals", "Operands": ["1"] } }, { - "NextAction": "Ask for Payment Method", + "NextAction": "Set Payment Method to Bank", "Condition": { "Operator": "Equals", "Operands": ["2"] @@ -1444,15 +1320,15 @@ ], "Errors": [ { - "NextAction": "Use Payment Method Again Timeout", + "NextAction": "Payment Method Timeout", "ErrorType": "InputTimeLimitExceeded" }, { - "NextAction": "Ask for Payment Method", + "NextAction": "Method Input Not Recognized", "ErrorType": "NoMatchingCondition" }, { - "NextAction": "Ask for Payment Method", + "NextAction": "Method Input Not Recognized", "ErrorType": "NoMatchingError" } ] @@ -1570,25 +1446,6 @@ ] } }, - { - "Parameters": { - "Attributes": { - "PaymentAmount": "$.Customer.Attributes.PaymentAmountDue" - }, - "TargetContact": "Current" - }, - "Identifier": "Set Payment Amount to Full Amount", - "Type": "UpdateContactAttributes", - "Transitions": { - "NextAction": "Check Last Payment Method", - "Errors": [ - { - "NextAction": "Internal Error", - "ErrorType": "NoMatchingError" - } - ] - } - }, { "Parameters": { "StoreInput": "False", @@ -1666,11 +1523,110 @@ ] } }, + { + "Parameters": { + "Attributes": { + "PaymentMethod": "Card" + }, + "TargetContact": "Current" + }, + "Identifier": "Set Payment Method to Card", + "Type": "UpdateContactAttributes", + "Transitions": { + "NextAction": "Get & Encrypt Card Number", + "Errors": [ + { + "NextAction": "Get & Encrypt Card Number", + "ErrorType": "NoMatchingError" + } + ] + } + }, + { + "Parameters": { + "Text": "\n>\" rate=\"<>\">\nAre you still there?\n\n" + }, + "Identifier": "Card Number Timeout", + "Type": "MessageParticipant", + "Transitions": { + "NextAction": "Get & Encrypt Card Number", + "Errors": [ + { + "NextAction": "Get & Encrypt Card Number", + "ErrorType": "NoMatchingError" + } + ] + } + }, + { + "Parameters": { + "Text": "\n>\" rate=\"<>\">\nAre you still there?\n\n" + }, + "Identifier": "Routing Number Timeout", + "Type": "MessageParticipant", + "Transitions": { + "NextAction": "Get Routing Number", + "Errors": [ + { + "NextAction": "Get Routing Number", + "ErrorType": "NoMatchingError" + } + ] + } + }, + { + "Parameters": { + "Text": "\n>\" rate=\"<>\">\nThere was a problem with your bank routing number. Please check your entry and try again.\n\n" + }, + "Identifier": "Try Routing Number Again", + "Type": "MessageParticipant", + "Transitions": { + "NextAction": "Get Routing Number", + "Errors": [ + { + "NextAction": "Get Routing Number", + "ErrorType": "NoMatchingError" + } + ] + } + }, + { + "Parameters": { + "Text": "\n>\" rate=\"<>\">\nAre you still there?\n\n" + }, + "Identifier": "Expiration Date Timeout", + "Type": "MessageParticipant", + "Transitions": { + "NextAction": "Get Expiration Date", + "Errors": [ + { + "NextAction": "Get Expiration Date", + "ErrorType": "NoMatchingError" + } + ] + } + }, + { + "Parameters": { + "Text": "\n>\" rate=\"<>\">\nThere was a problem with your expiration date. Please check your entry and try again.\n\n" + }, + "Identifier": "Try Expiration Date Again", + "Type": "MessageParticipant", + "Transitions": { + "NextAction": "Get Expiration Date", + "Errors": [ + { + "NextAction": "Get Expiration Date", + "ErrorType": "NoMatchingError" + } + ] + } + }, { "Parameters": { "StoreInput": "True", - "InputTimeLimitSeconds": "10", - "Text": "\n>\" rate=\"<>\">\nPlease enter your bank account number followed by the pound key when complete.\n\n", + "InputTimeLimitSeconds": "5", + "Text": "\n>\" rate=\"<>\">\nPlease enter your card's expiration date in the format month-month-year-year, followed by the pound key when complete.\n\n", "DTMFConfiguration": { "DisableCancelKey": "False", "InputTerminationSequence": "#" @@ -1679,19 +1635,61 @@ "CustomValidation": { "MaximumLength": "25" } - }, - "InputEncryption": { - "EncryptionKeyId": "<>", - "Key": "<>" } }, - "Identifier": "Get & Encrypt Account Number", + "Identifier": "Get Expiration Date", "Type": "GetParticipantInput", "Transitions": { - "NextAction": "Account Number Timeout Check", + "NextAction": "Expiration Date Timeout Check", + "Errors": [ + { + "NextAction": "Try Expiration Date Again", + "ErrorType": "NoMatchingError" + } + ] + } + }, + { + "Parameters": { + "ComparisonValue": "$.Attributes.Email" + }, + "Identifier": "Check for Customer Email", + "Type": "Compare", + "Transitions": { + "NextAction": "Has Specified Receipt Queue", + "Conditions": [ + { + "NextAction": "Send Receipt", + "Condition": { + "Operator": "TextContains", + "Operands": ["@"] + } + } + ], + "Errors": [ + { + "NextAction": "Has Specified Receipt Queue", + "ErrorType": "NoMatchingCondition" + } + ] + } + }, + { + "Parameters": { + "Attributes": { + "EncryptedCardNumber": "REDACTED", + "EncryptedAccountNumber": "REDACTED", + "ExpirationDate": "REDACTED" + }, + "TargetContact": "Current" + }, + "Identifier": "Redact Sensitive Contact Attributes Copy", + "Type": "UpdateContactAttributes", + "Transitions": { + "NextAction": "Set Queue", "Errors": [ { - "NextAction": "Internal Error", + "NextAction": "Set Queue", "ErrorType": "NoMatchingError" } ] @@ -1699,19 +1697,25 @@ }, { "Parameters": { - "Attributes": { - "PaymentMethod": "Card" - }, - "TargetContact": "Current" + "ComparisonValue": "$.FlowAttributes.ReceiptQueueId" }, - "Identifier": "Set Payment Method to Card", - "Type": "UpdateContactAttributes", + "Identifier": "Has Specified Receipt Queue", + "Type": "Compare", "Transitions": { - "NextAction": "Get & Encrypt Card Number", + "NextAction": "Ask to Transfer for Receipt", + "Conditions": [ + { + "NextAction": "Redact Sensitive Contact Attributes", + "Condition": { + "Operator": "Equals", + "Operands": ["NULL"] + } + } + ], "Errors": [ { - "NextAction": "Get & Encrypt Card Number", - "ErrorType": "NoMatchingError" + "NextAction": "Ask to Transfer for Receipt", + "ErrorType": "NoMatchingCondition" } ] } @@ -1720,13 +1724,13 @@ "Parameters": { "Text": "\n>\" rate=\"<>\">\nAre you still there?\n\n" }, - "Identifier": "Card Number Timeout", + "Identifier": "Receipt Timeout", "Type": "MessageParticipant", "Transitions": { - "NextAction": "Get & Encrypt Card Number", + "NextAction": "Ask to Transfer for Receipt", "Errors": [ { - "NextAction": "Get & Encrypt Card Number", + "NextAction": "Ask to Transfer for Receipt", "ErrorType": "NoMatchingError" } ] @@ -1734,30 +1738,15 @@ }, { "Parameters": { - "StoreInput": "True", - "InputTimeLimitSeconds": "10", - "Text": "\n>\" rate=\"<>\">\nPlease enter your card number followed by the pound key when complete.\n\n", - "DTMFConfiguration": { - "DisableCancelKey": "False", - "InputTerminationSequence": "#" - }, - "InputValidation": { - "CustomValidation": { - "MaximumLength": "25" - } - }, - "InputEncryption": { - "EncryptionKeyId": "<>", - "Key": "<>" - } + "Text": "\n>\" rate=\"<>\">\nYour entry was not recognized. Please try again.\n\n" }, - "Identifier": "Get & Encrypt Card Number", - "Type": "GetParticipantInput", + "Identifier": "Receipt Entry Not Recognized", + "Type": "MessageParticipant", "Transitions": { - "NextAction": "Card Number Timeout Check", + "NextAction": "Ask to Transfer for Receipt", "Errors": [ { - "NextAction": "Internal Error", + "NextAction": "Ask to Transfer for Receipt", "ErrorType": "NoMatchingError" } ] @@ -1765,15 +1754,41 @@ }, { "Parameters": { - "Text": "\n>\" rate=\"<>\">\nAre you still there?\n\n" + "StoreInput": "False", + "InputTimeLimitSeconds": "5", + "Text": "\n>\" rate=\"<>\">\nTo transfer to a representative and receive a receipt for your payment, press 1.\nTo continue without a receipt, press 2.\n\n" }, - "Identifier": "Routing Number Timeout", - "Type": "MessageParticipant", + "Identifier": "Ask to Transfer for Receipt", + "Type": "GetParticipantInput", "Transitions": { - "NextAction": "Get Routing Number", + "NextAction": "Receipt Entry Not Recognized", + "Conditions": [ + { + "NextAction": "Redact Sensitive Contact Attributes Copy", + "Condition": { + "Operator": "Equals", + "Operands": ["1"] + } + }, + { + "NextAction": "Redact Sensitive Contact Attributes", + "Condition": { + "Operator": "Equals", + "Operands": ["2"] + } + } + ], "Errors": [ { - "NextAction": "Get Routing Number", + "NextAction": "Receipt Timeout", + "ErrorType": "InputTimeLimitExceeded" + }, + { + "NextAction": "Receipt Entry Not Recognized", + "ErrorType": "NoMatchingCondition" + }, + { + "NextAction": "Receipt Entry Not Recognized", "ErrorType": "NoMatchingError" } ] @@ -1781,15 +1796,15 @@ }, { "Parameters": { - "Text": "\n>\" rate=\"<>\">\nThere was a problem with your bank routing number. Please check your entry and try again.\n\n" + "Text": "\n>\" rate=\"<>\">\nA receipt has been sent to your email address, $.Attributes.['Email'].\n\n" }, - "Identifier": "Try Routing Number Again", + "Identifier": "Receipt Success", "Type": "MessageParticipant", "Transitions": { - "NextAction": "Get Routing Number", + "NextAction": "Redact Sensitive Contact Attributes", "Errors": [ { - "NextAction": "Get Routing Number", + "NextAction": "Redact Sensitive Contact Attributes", "ErrorType": "NoMatchingError" } ] @@ -1797,15 +1812,19 @@ }, { "Parameters": { - "Text": "\n>\" rate=\"<>\">\nAre you still there?\n\n" + "LambdaFunctionARN": "<>", + "InvocationTimeLimitSeconds": "8", + "ResponseValidation": { + "ResponseType": "JSON" + } }, - "Identifier": "Expiration Date Timeout", - "Type": "MessageParticipant", + "Identifier": "Send Receipt", + "Type": "InvokeLambdaFunction", "Transitions": { - "NextAction": "Get Expiration Date", + "NextAction": "Receipt Success", "Errors": [ { - "NextAction": "Get Expiration Date", + "NextAction": "Receipt Error", "ErrorType": "NoMatchingError" } ] @@ -1813,42 +1832,39 @@ }, { "Parameters": { - "Text": "\n>\" rate=\"<>\">\nThere was a problem with your expiration date. Please check your entry and try again.\n\n" + "Text": "\n>\" rate=\"<>\">\nThere was an error sending the receipt to your email address, $.Attributes.['Email']. Please contact customer support to receive a receipt for this transaction.\n\n" }, - "Identifier": "Try Expiration Date Again", + "Identifier": "Receipt Error", "Type": "MessageParticipant", "Transitions": { - "NextAction": "Get Expiration Date", + "NextAction": "Redact Sensitive Contact Attributes", "Errors": [ { - "NextAction": "Get Expiration Date", + "NextAction": "Redact Sensitive Contact Attributes", "ErrorType": "NoMatchingError" } ] } }, { - "Parameters": { - "StoreInput": "True", - "InputTimeLimitSeconds": "5", - "Text": "\n>\" rate=\"<>\">\nPlease enter your card's expiration date in the format month-month-year-year, followed by the pound key when complete.\n\n", - "DTMFConfiguration": { - "DisableCancelKey": "False", - "InputTerminationSequence": "#" - }, - "InputValidation": { - "CustomValidation": { - "MaximumLength": "25" - } - } - }, - "Identifier": "Get Expiration Date", - "Type": "GetParticipantInput", + "Parameters": {}, + "Identifier": "a3ea896e-4f43-4677-8edd-159f677dc41e", + "Type": "EndFlowModuleExecution", + "Transitions": {} + }, + { + "Parameters": {}, + "Identifier": "Transfer to Representative", + "Type": "TransferContactToQueue", "Transitions": { - "NextAction": "Expiration Date Timeout Check", + "NextAction": "Transfer Error", "Errors": [ { - "NextAction": "Try Expiration Date Again", + "NextAction": "Transfer Error", + "ErrorType": "QueueAtCapacity" + }, + { + "NextAction": "Transfer Error", "ErrorType": "NoMatchingError" } ] @@ -1856,40 +1872,31 @@ }, { "Parameters": { - "ComparisonValue": "$.External.Error" + "QueueId": "$.FlowAttributes.ReceiptQueueId" }, - "Identifier": "Check for Tokenize Error", - "Type": "Compare", + "Identifier": "Set Queue", + "Type": "UpdateContactTargetQueue", "Transitions": { - "NextAction": "Speak Validation Error", - "Conditions": [ - { - "NextAction": "Record Token", - "Condition": { - "Operator": "Equals", - "Operands": ["NULL"] - } - } - ], + "NextAction": "Transfer to Representative", "Errors": [ { - "NextAction": "Speak Validation Error", - "ErrorType": "NoMatchingCondition" + "NextAction": "Transfer Error", + "ErrorType": "NoMatchingError" } ] } }, { "Parameters": { - "Text": "\n>\" rate=\"<>\">\nThe payment failed because of the following error:\n\n$.External.Error\n\n" + "Text": "\n>\" rate=\"<>\">\nAn error prevented us from connecting you to a representative. Please try calling the customer service number directly in order to receive a receipt.\n\n" }, - "Identifier": "Speak Validation Error", + "Identifier": "Transfer Error", "Type": "MessageParticipant", "Transitions": { - "NextAction": "Remove Failed Payment Token and Method", + "NextAction": "a3ea896e-4f43-4677-8edd-159f677dc41e", "Errors": [ { - "NextAction": "Remove Failed Payment Token and Method", + "NextAction": "a3ea896e-4f43-4677-8edd-159f677dc41e", "ErrorType": "NoMatchingError" } ] @@ -1897,19 +1904,29 @@ }, { "Parameters": { - "LambdaFunctionARN": "<>", + "FlowLoggingBehavior": "Disabled" + }, + "Identifier": "87859db2-400d-410b-8818-05c8ae4869aa", + "Type": "UpdateFlowLoggingBehavior", + "Transitions": { + "NextAction": "Set Receipt Queue ID" + } + }, + { + "Parameters": { + "LambdaFunctionARN": "<>", "InvocationTimeLimitSeconds": "8", "ResponseValidation": { "ResponseType": "JSON" } }, - "Identifier": "Tokenize Transaction", + "Identifier": "Create Payment Request", "Type": "InvokeLambdaFunction", "Transitions": { - "NextAction": "Check for Tokenize Error", + "NextAction": "Record Payment Request ID", "Errors": [ { - "NextAction": "Payment Validation Error", + "NextAction": "Payment Request Error", "ErrorType": "NoMatchingError" } ] @@ -1917,15 +1934,19 @@ }, { "Parameters": { - "Text": "\n>\" rate=\"<>\">\nThere was a problem validating your $.Attributes.PaymentMethod information.\n\n" + "FlowAttributes": { + "ReceiptQueueId": { + "Value": "<>" + } + } }, - "Identifier": "Payment Validation Error", - "Type": "MessageParticipant", + "Identifier": "Set Receipt Queue ID", + "Type": "UpdateFlowAttributes", "Transitions": { - "NextAction": "Remove Failed Payment Token and Method", + "NextAction": "Create Payment Request", "Errors": [ { - "NextAction": "Remove Failed Payment Token and Method", + "NextAction": "Create Payment Request", "ErrorType": "NoMatchingError" } ] @@ -1933,39 +1954,40 @@ }, { "Parameters": { - "LambdaFunctionARN": "<>", - "InvocationTimeLimitSeconds": "8", - "ResponseValidation": { - "ResponseType": "JSON" - } + "ComparisonValue": "$.StoredCustomerInput" }, - "Identifier": "Submit Payment", - "Type": "InvokeLambdaFunction", + "Identifier": "Card Number Timeout Check", + "Type": "Compare", "Transitions": { - "NextAction": "Record Transaction Attributes", + "NextAction": "Validate Card Number", + "Conditions": [ + { + "NextAction": "Card Number Timeout", + "Condition": { + "Operator": "Equals", + "Operands": ["Timeout"] + } + } + ], "Errors": [ { - "NextAction": "Payment Submission Error", - "ErrorType": "NoMatchingError" + "NextAction": "Validate Card Number", + "ErrorType": "NoMatchingCondition" } ] } }, { "Parameters": { - "Attributes": { - "PaymentToken": "NULL", - "PaymentMethod": "NULL" - }, - "TargetContact": "Current" + "Text": "\n>\" rate=\"<>\">\n$.External.ValidationError\n\nPlease check your entry and try again.\n\n" }, - "Identifier": "Remove Failed Payment Token and Method", - "Type": "UpdateContactAttributes", + "Identifier": "Card Number Validation Error", + "Type": "MessageParticipant", "Transitions": { - "NextAction": "Redact Sensitive Contact Attributes", + "NextAction": "Get & Encrypt Card Number", "Errors": [ { - "NextAction": "Redact Sensitive Contact Attributes", + "NextAction": "Get & Encrypt Card Number", "ErrorType": "NoMatchingError" } ] @@ -1973,15 +1995,23 @@ }, { "Parameters": { - "Text": "\n>\" rate=\"<>\">\nWe're sorry, an error has occured preventing us from submitting your payment. You have not been charged.\n\n" + "LambdaFunctionARN": "<>", + "InvocationTimeLimitSeconds": "8", + "LambdaInvocationAttributes": { + "ValidationType": "CardNumber", + "CustomerEntry": "$.StoredCustomerInput" + }, + "ResponseValidation": { + "ResponseType": "JSON" + } }, - "Identifier": "Payment Submission Error", - "Type": "MessageParticipant", + "Identifier": "Validate Card Number", + "Type": "InvokeLambdaFunction", "Transitions": { - "NextAction": "Remove Failed Payment Token and Method", + "NextAction": "Check for Card Number Validation Error", "Errors": [ { - "NextAction": "Remove Failed Payment Token and Method", + "NextAction": "Store Encrypted Card Number", "ErrorType": "NoMatchingError" } ] @@ -1989,44 +2019,49 @@ }, { "Parameters": { - "Attributes": { - "TransactionId": "$.External.TransactionId", - "PaymentMethodEndingDigits": "$.External.PaymentMethodEndingDigits" - }, - "TargetContact": "Current" + "ComparisonValue": "$.External.ValidationError" }, - "Identifier": "Record Transaction Attributes", - "Type": "UpdateContactAttributes", + "Identifier": "Check for Card Number Validation Error", + "Type": "Compare", "Transitions": { - "NextAction": "Payment Success", + "NextAction": "Card Number Validation Error", + "Conditions": [ + { + "NextAction": "Store Encrypted Card Number", + "Condition": { + "Operator": "Equals", + "Operands": ["NULL"] + } + } + ], "Errors": [ { - "NextAction": "Payment Success", - "ErrorType": "NoMatchingError" + "NextAction": "Card Number Validation Error", + "ErrorType": "NoMatchingCondition" } ] } }, { "Parameters": { - "ComparisonValue": "$.Attributes.Email" + "ComparisonValue": "$.StoredCustomerInput" }, - "Identifier": "Check for Customer Email", + "Identifier": "Account Number Timeout Check", "Type": "Compare", "Transitions": { - "NextAction": "Has Specified Receipt Queue", + "NextAction": "Validate Account Number", "Conditions": [ { - "NextAction": "Send Receipt", + "NextAction": "Account Number Timeout", "Condition": { - "Operator": "TextContains", - "Operands": ["@"] + "Operator": "Equals", + "Operands": ["Timeout"] } } ], "Errors": [ { - "NextAction": "Has Specified Receipt Queue", + "NextAction": "Validate Account Number", "ErrorType": "NoMatchingCondition" } ] @@ -2034,15 +2069,15 @@ }, { "Parameters": { - "Text": "\n>\" rate=\"<>\">\nYour payment was processed successfully.\n\n" + "Text": "\n>\" rate=\"<>\">\n$.External.ValidationError\n\nPlease check your entry and try again.\n\n" }, - "Identifier": "Payment Success", + "Identifier": "Account Number Validation Error", "Type": "MessageParticipant", "Transitions": { - "NextAction": "Check for Customer Email", + "NextAction": "Get & Encrypt Account Number", "Errors": [ { - "NextAction": "Check for Customer Email", + "NextAction": "Get & Encrypt Account Number", "ErrorType": "NoMatchingError" } ] @@ -2050,20 +2085,26 @@ }, { "Parameters": { - "Attributes": { - "EncryptedCardNumber": "REDACTED", - "EncryptedAccountNumber": "REDACTED", - "ExpirationDate": "REDACTED" + "StoreInput": "True", + "InputTimeLimitSeconds": "10", + "Text": "\n>\" rate=\"<>\">\nPlease enter your bank's routing number, followed by the pound key when complete.\n\n", + "DTMFConfiguration": { + "DisableCancelKey": "False", + "InputTerminationSequence": "#" }, - "TargetContact": "Current" + "InputValidation": { + "CustomValidation": { + "MaximumLength": "25" + } + } }, - "Identifier": "Redact Sensitive Contact Attributes Copy", - "Type": "UpdateContactAttributes", + "Identifier": "Get Routing Number", + "Type": "GetParticipantInput", "Transitions": { - "NextAction": "Set Queue", + "NextAction": "Routing Number Timeout Check", "Errors": [ { - "NextAction": "Set Queue", + "NextAction": "Try Routing Number Again", "ErrorType": "NoMatchingError" } ] @@ -2071,56 +2112,64 @@ }, { "Parameters": { - "ComparisonValue": "$.FlowAttributes.ReceiptQueueId" + "LambdaFunctionARN": "<>", + "InvocationTimeLimitSeconds": "8", + "LambdaInvocationAttributes": { + "ValidationType": "AccountNumber", + "CustomerEntry": "$.StoredCustomerInput" + }, + "ResponseValidation": { + "ResponseType": "JSON" + } }, - "Identifier": "Has Specified Receipt Queue", - "Type": "Compare", + "Identifier": "Validate Account Number", + "Type": "InvokeLambdaFunction", "Transitions": { - "NextAction": "Ask to Transfer for Receipt", - "Conditions": [ - { - "NextAction": "Redact Sensitive Contact Attributes", - "Condition": { - "Operator": "Equals", - "Operands": ["NULL"] - } - } - ], + "NextAction": "Check for Account Number Validation Error", "Errors": [ { - "NextAction": "Ask to Transfer for Receipt", - "ErrorType": "NoMatchingCondition" + "NextAction": "Store Encrypted Account Number", + "ErrorType": "NoMatchingError" } ] } }, { "Parameters": { - "Text": "\n>\" rate=\"<>\">\nAre you still there?\n\n" + "ComparisonValue": "$.External.ValidationError" }, - "Identifier": "Receipt Timeout", - "Type": "MessageParticipant", + "Identifier": "Check for Account Number Validation Error", + "Type": "Compare", "Transitions": { - "NextAction": "Ask to Transfer for Receipt", + "NextAction": "Account Number Validation Error", + "Conditions": [ + { + "NextAction": "Store Encrypted Account Number", + "Condition": { + "Operator": "Equals", + "Operands": ["NULL"] + } + } + ], "Errors": [ { - "NextAction": "Ask to Transfer for Receipt", - "ErrorType": "NoMatchingError" + "NextAction": "Account Number Validation Error", + "ErrorType": "NoMatchingCondition" } ] } }, { "Parameters": { - "Text": "\n>\" rate=\"<>\">\nYour entry was not recognized. Please try again.\n\n" + "Text": "\n>\" rate=\"<>\">\n$.External.ValidationError\n\nPlease check your entry and try again.\n\n" }, - "Identifier": "Receipt Entry Not Recognized", + "Identifier": "Routing Number Validation Error", "Type": "MessageParticipant", "Transitions": { - "NextAction": "Ask to Transfer for Receipt", + "NextAction": "Get Routing Number", "Errors": [ { - "NextAction": "Ask to Transfer for Receipt", + "NextAction": "Get Routing Number", "ErrorType": "NoMatchingError" } ] @@ -2128,77 +2177,73 @@ }, { "Parameters": { - "StoreInput": "False", - "InputTimeLimitSeconds": "5", - "Text": "\n>\" rate=\"<>\">\nTo transfer to a representative and receive a receipt for your payment, press 1.\nTo continue without a receipt, press 2.\n\n" + "ComparisonValue": "$.StoredCustomerInput" }, - "Identifier": "Ask to Transfer for Receipt", - "Type": "GetParticipantInput", + "Identifier": "Routing Number Timeout Check", + "Type": "Compare", "Transitions": { - "NextAction": "Receipt Entry Not Recognized", + "NextAction": "Validate Routing Number", "Conditions": [ { - "NextAction": "Redact Sensitive Contact Attributes Copy", - "Condition": { - "Operator": "Equals", - "Operands": ["1"] - } - }, - { - "NextAction": "Redact Sensitive Contact Attributes", + "NextAction": "Routing Number Timeout", "Condition": { "Operator": "Equals", - "Operands": ["2"] + "Operands": ["Timeout"] } } ], "Errors": [ { - "NextAction": "Receipt Timeout", - "ErrorType": "InputTimeLimitExceeded" - }, - { - "NextAction": "Receipt Entry Not Recognized", + "NextAction": "Validate Routing Number", "ErrorType": "NoMatchingCondition" - }, - { - "NextAction": "Receipt Entry Not Recognized", - "ErrorType": "NoMatchingError" } ] } }, { "Parameters": { - "Text": "\n>\" rate=\"<>\">\nA receipt has been sent to your email address, $.Attributes.['Email'].\n\n" + "ComparisonValue": "$.External.ValidationError" }, - "Identifier": "Receipt Success", - "Type": "MessageParticipant", + "Identifier": "Check for Routing Number Validation Error", + "Type": "Compare", "Transitions": { - "NextAction": "Redact Sensitive Contact Attributes", + "NextAction": "Routing Number Validation Error", + "Conditions": [ + { + "NextAction": "Store Routing Number", + "Condition": { + "Operator": "Equals", + "Operands": ["NULL"] + } + } + ], "Errors": [ { - "NextAction": "Redact Sensitive Contact Attributes", - "ErrorType": "NoMatchingError" + "NextAction": "Routing Number Validation Error", + "ErrorType": "NoMatchingCondition" } ] } }, { "Parameters": { - "LambdaFunctionARN": "<>", + "LambdaFunctionARN": "<>", "InvocationTimeLimitSeconds": "8", + "LambdaInvocationAttributes": { + "ValidationType": "RoutingNumber", + "CustomerEntry": "$.StoredCustomerInput" + }, "ResponseValidation": { "ResponseType": "JSON" } }, - "Identifier": "Send Receipt", + "Identifier": "Validate Routing Number", "Type": "InvokeLambdaFunction", "Transitions": { - "NextAction": "Receipt Success", + "NextAction": "Check for Routing Number Validation Error", "Errors": [ { - "NextAction": "Receipt Error", + "NextAction": "Store Routing Number", "ErrorType": "NoMatchingError" } ] @@ -2206,20 +2251,15 @@ }, { "Parameters": { - "Attributes": { - "EncryptedCardNumber": "REDACTED", - "EncryptedAccountNumber": "REDACTED", - "ExpirationDate": "REDACTED" - }, - "TargetContact": "Current" + "Text": "\n>\" rate=\"<>\">\n$.External.ValidationError\n\nPlease check your entry and try again.\n\n" }, - "Identifier": "Redact Sensitive Contact Attributes", - "Type": "UpdateContactAttributes", + "Identifier": "Expiration Date Validation Error", + "Type": "MessageParticipant", "Transitions": { - "NextAction": "a3ea896e-4f43-4677-8edd-159f677dc41e", + "NextAction": "Get Expiration Date", "Errors": [ { - "NextAction": "a3ea896e-4f43-4677-8edd-159f677dc41e", + "NextAction": "Get Expiration Date", "ErrorType": "NoMatchingError" } ] @@ -2227,71 +2267,73 @@ }, { "Parameters": { - "Text": "\n>\" rate=\"<>\">\nThere was an error sending the receipt to your email address, $.Attributes.['Email']. Please contact customer support to receive a receipt for this transaction.\n\n" + "ComparisonValue": "$.StoredCustomerInput" }, - "Identifier": "Receipt Error", - "Type": "MessageParticipant", + "Identifier": "Expiration Date Timeout Check", + "Type": "Compare", "Transitions": { - "NextAction": "Redact Sensitive Contact Attributes", - "Errors": [ + "NextAction": "Validate Expiration Date", + "Conditions": [ { - "NextAction": "Redact Sensitive Contact Attributes", - "ErrorType": "NoMatchingError" - } - ] - } - }, - { - "Parameters": {}, - "Identifier": "a3ea896e-4f43-4677-8edd-159f677dc41e", - "Type": "EndFlowModuleExecution", - "Transitions": {} - }, - { - "Parameters": {}, - "Identifier": "Transfer to Representative", - "Type": "TransferContactToQueue", - "Transitions": { - "NextAction": "Transfer Error", + "NextAction": "Expiration Date Timeout", + "Condition": { + "Operator": "Equals", + "Operands": ["Timeout"] + } + } + ], "Errors": [ { - "NextAction": "Transfer Error", - "ErrorType": "QueueAtCapacity" - }, - { - "NextAction": "Transfer Error", - "ErrorType": "NoMatchingError" + "NextAction": "Validate Expiration Date", + "ErrorType": "NoMatchingCondition" } ] } }, { "Parameters": { - "QueueId": "$.FlowAttributes.ReceiptQueueId" + "ComparisonValue": "$.External.ValidationError" }, - "Identifier": "Set Queue", - "Type": "UpdateContactTargetQueue", + "Identifier": "Check for Expiration Date Validation Error", + "Type": "Compare", "Transitions": { - "NextAction": "Transfer to Representative", + "NextAction": "Expiration Date Validation Error", + "Conditions": [ + { + "NextAction": "Store Expiration Date", + "Condition": { + "Operator": "Equals", + "Operands": ["NULL"] + } + } + ], "Errors": [ { - "NextAction": "Transfer Error", - "ErrorType": "NoMatchingError" + "NextAction": "Expiration Date Validation Error", + "ErrorType": "NoMatchingCondition" } ] } }, { "Parameters": { - "Text": "\n>\" rate=\"<>\">\nAn error prevented us from connecting you to a representative. Please try calling the customer service number directly in order to receive a receipt.\n\n" + "LambdaFunctionARN": "<>", + "InvocationTimeLimitSeconds": "8", + "LambdaInvocationAttributes": { + "ValidationType": "ExpirationDate", + "CustomerEntry": "$.StoredCustomerInput" + }, + "ResponseValidation": { + "ResponseType": "JSON" + } }, - "Identifier": "Transfer Error", - "Type": "MessageParticipant", + "Identifier": "Validate Expiration Date", + "Type": "InvokeLambdaFunction", "Transitions": { - "NextAction": "a3ea896e-4f43-4677-8edd-159f677dc41e", + "NextAction": "Check for Expiration Date Validation Error", "Errors": [ { - "NextAction": "a3ea896e-4f43-4677-8edd-159f677dc41e", + "NextAction": "Store Expiration Date", "ErrorType": "NoMatchingError" } ] @@ -2299,29 +2341,45 @@ }, { "Parameters": { - "FlowLoggingBehavior": "Disabled" + "StoreInput": "True", + "InputTimeLimitSeconds": "5", + "Text": "\n>\" rate=\"<>\">\nPlease enter the amount you would like to pay in whole dollars, followed by the pound key.\n\n", + "DTMFConfiguration": { + "DisableCancelKey": "False", + "InputTerminationSequence": "#" + }, + "InputValidation": { + "CustomValidation": { + "MaximumLength": "20" + } + } }, - "Identifier": "87859db2-400d-410b-8818-05c8ae4869aa", - "Type": "UpdateFlowLoggingBehavior", + "Identifier": "Get Payment Amount", + "Type": "GetParticipantInput", "Transitions": { - "NextAction": "Set Receipt Queue ID" + "NextAction": "Check Payment Amount", + "Errors": [ + { + "NextAction": "Internal Error", + "ErrorType": "NoMatchingError" + } + ] } }, { "Parameters": { - "LambdaFunctionARN": "<>", - "InvocationTimeLimitSeconds": "8", - "ResponseValidation": { - "ResponseType": "JSON" - } + "Attributes": { + "PaymentAmount": "$.StoredCustomerInput" + }, + "TargetContact": "Current" }, - "Identifier": "Create Payment Request", - "Type": "InvokeLambdaFunction", + "Identifier": "Set Payment Amount to Entered Amount", + "Type": "UpdateContactAttributes", "Transitions": { - "NextAction": "Record Payment Request ID", + "NextAction": "Check Last Payment Method", "Errors": [ { - "NextAction": "Payment Request Error", + "NextAction": "Internal Error", "ErrorType": "NoMatchingError" } ] @@ -2329,19 +2387,18 @@ }, { "Parameters": { - "FlowAttributes": { - "ReceiptQueueId": { - "Value": "<>" - } - } + "Attributes": { + "PaymentAmount": "$.Customer.Attributes.PaymentAmountDue" + }, + "TargetContact": "Current" }, - "Identifier": "Set Receipt Queue ID", - "Type": "UpdateFlowAttributes", + "Identifier": "Set Payment Amount to Full Amount", + "Type": "UpdateContactAttributes", "Transitions": { - "NextAction": "Create Payment Request", + "NextAction": "Check Last Payment Method", "Errors": [ { - "NextAction": "Create Payment Request", + "NextAction": "Internal Error", "ErrorType": "NoMatchingError" } ] @@ -2349,40 +2406,61 @@ }, { "Parameters": { - "ComparisonValue": "$.StoredCustomerInput" + "StoreInput": "True", + "InputTimeLimitSeconds": "10", + "Text": "\n>\" rate=\"<>\">\nPlease enter your bank account number followed by the pound key when complete.\n\n", + "DTMFConfiguration": { + "DisableCancelKey": "False", + "InputTerminationSequence": "#" + }, + "InputValidation": { + "CustomValidation": { + "MaximumLength": "25" + } + }, + "InputEncryption": { + "EncryptionKeyId": "<>", + "Key": "<>" + } }, - "Identifier": "Card Number Timeout Check", - "Type": "Compare", + "Identifier": "Get & Encrypt Account Number", + "Type": "GetParticipantInput", "Transitions": { - "NextAction": "Validate Card Number", - "Conditions": [ - { - "NextAction": "Card Number Timeout", - "Condition": { - "Operator": "Equals", - "Operands": ["Timeout"] - } - } - ], + "NextAction": "Account Number Timeout Check", "Errors": [ { - "NextAction": "Validate Card Number", - "ErrorType": "NoMatchingCondition" + "NextAction": "Internal Error", + "ErrorType": "NoMatchingError" } ] } }, { "Parameters": { - "Text": "\n>\" rate=\"<>\">\n$.External.ValidationError\n\nPlease check your entry and try again.\n\n" + "StoreInput": "True", + "InputTimeLimitSeconds": "10", + "Text": "\n>\" rate=\"<>\">\nPlease enter your card number followed by the pound key when complete.\n\n", + "DTMFConfiguration": { + "DisableCancelKey": "False", + "InputTerminationSequence": "#" + }, + "InputValidation": { + "CustomValidation": { + "MaximumLength": "25" + } + }, + "InputEncryption": { + "EncryptionKeyId": "<>", + "Key": "<>" + } }, - "Identifier": "Card Number Validation Error", - "Type": "MessageParticipant", + "Identifier": "Get & Encrypt Card Number", + "Type": "GetParticipantInput", "Transitions": { - "NextAction": "Get & Encrypt Card Number", + "NextAction": "Card Number Timeout Check", "Errors": [ { - "NextAction": "Get & Encrypt Card Number", + "NextAction": "Internal Error", "ErrorType": "NoMatchingError" } ] @@ -2391,17 +2469,19 @@ { "Parameters": { "Attributes": { - "EncryptedCardNumber": "$.StoredCustomerInput" + "EncryptedCardNumber": "REDACTED", + "EncryptedAccountNumber": "REDACTED", + "ExpirationDate": "REDACTED" }, "TargetContact": "Current" }, - "Identifier": "Store Encrypted Card Number", + "Identifier": "Redact Sensitive Contact Attributes", "Type": "UpdateContactAttributes", "Transitions": { - "NextAction": "Get Expiration Date", + "NextAction": "a3ea896e-4f43-4677-8edd-159f677dc41e", "Errors": [ { - "NextAction": "Internal Error", + "NextAction": "a3ea896e-4f43-4677-8edd-159f677dc41e", "ErrorType": "NoMatchingError" } ] @@ -2409,23 +2489,18 @@ }, { "Parameters": { - "LambdaFunctionARN": "<>", - "InvocationTimeLimitSeconds": "8", - "LambdaInvocationAttributes": { - "ValidationType": "CardNumber", - "CustomerEntry": "$.StoredCustomerInput" + "Attributes": { + "EncryptedCardNumber": "$.StoredCustomerInput" }, - "ResponseValidation": { - "ResponseType": "JSON" - } + "TargetContact": "Current" }, - "Identifier": "Validate Card Number", - "Type": "InvokeLambdaFunction", + "Identifier": "Store Encrypted Card Number", + "Type": "UpdateContactAttributes", "Transitions": { - "NextAction": "Check for Card Number Validation Error", + "NextAction": "Get Expiration Date", "Errors": [ { - "NextAction": "Store Encrypted Card Number", + "NextAction": "Internal Error", "ErrorType": "NoMatchingError" } ] @@ -2433,65 +2508,56 @@ }, { "Parameters": { - "ComparisonValue": "$.External.ValidationError" + "Attributes": { + "EncryptedAccountNumber": "$.StoredCustomerInput" + }, + "TargetContact": "Current" }, - "Identifier": "Check for Card Number Validation Error", - "Type": "Compare", + "Identifier": "Store Encrypted Account Number", + "Type": "UpdateContactAttributes", "Transitions": { - "NextAction": "Card Number Validation Error", - "Conditions": [ - { - "NextAction": "Store Encrypted Card Number", - "Condition": { - "Operator": "Equals", - "Operands": ["NULL"] - } - } - ], + "NextAction": "Get Routing Number", "Errors": [ { - "NextAction": "Card Number Validation Error", - "ErrorType": "NoMatchingCondition" + "NextAction": "Internal Error", + "ErrorType": "NoMatchingError" } ] } }, { "Parameters": { - "ComparisonValue": "$.StoredCustomerInput" + "Attributes": { + "RoutingNumber": "$.StoredCustomerInput" + }, + "TargetContact": "Current" }, - "Identifier": "Account Number Timeout Check", - "Type": "Compare", + "Identifier": "Store Routing Number", + "Type": "UpdateContactAttributes", "Transitions": { - "NextAction": "Validate Account Number", - "Conditions": [ - { - "NextAction": "Account Number Timeout", - "Condition": { - "Operator": "Equals", - "Operands": ["Timeout"] - } - } - ], + "NextAction": "Tokenize Transaction", "Errors": [ { - "NextAction": "Validate Account Number", - "ErrorType": "NoMatchingCondition" + "NextAction": "Internal Error", + "ErrorType": "NoMatchingError" } ] } }, { "Parameters": { - "Text": "\n>\" rate=\"<>\">\n$.External.ValidationError\n\nPlease check your entry and try again.\n\n" + "Attributes": { + "ExpirationDate": "$.StoredCustomerInput" + }, + "TargetContact": "Current" }, - "Identifier": "Account Number Validation Error", - "Type": "MessageParticipant", + "Identifier": "Store Expiration Date", + "Type": "UpdateContactAttributes", "Transitions": { - "NextAction": "Get & Encrypt Account Number", + "NextAction": "Tokenize Transaction", "Errors": [ { - "NextAction": "Get & Encrypt Account Number", + "NextAction": "Internal Error", "ErrorType": "NoMatchingError" } ] @@ -2515,50 +2581,15 @@ }, { "Parameters": { - "StoreInput": "True", - "InputTimeLimitSeconds": "10", - "Text": "\n>\" rate=\"<>\">\nPlease enter your bank's routing number, followed by the pound key when complete.\n\n", - "DTMFConfiguration": { - "DisableCancelKey": "False", - "InputTerminationSequence": "#" - }, - "InputValidation": { - "CustomValidation": { - "MaximumLength": "25" - } - } - }, - "Identifier": "Get Routing Number", - "Type": "GetParticipantInput", - "Transitions": { - "NextAction": "Routing Number Timeout Check", - "Errors": [ - { - "NextAction": "Try Routing Number Again", - "ErrorType": "NoMatchingError" - } - ] - } - }, - { - "Parameters": { - "LambdaFunctionARN": "<>", - "InvocationTimeLimitSeconds": "8", - "LambdaInvocationAttributes": { - "ValidationType": "AccountNumber", - "CustomerEntry": "$.StoredCustomerInput" - }, - "ResponseValidation": { - "ResponseType": "JSON" - } + "Text": "\n>\" rate=\"<>\">\nThe payment failed because of the following error:\n\n$.External.Error\n\n" }, - "Identifier": "Validate Account Number", - "Type": "InvokeLambdaFunction", + "Identifier": "Speak Validation Error", + "Type": "MessageParticipant", "Transitions": { - "NextAction": "Check for Account Number Validation Error", + "NextAction": "Remove Failed Payment Token and Method", "Errors": [ { - "NextAction": "Store Encrypted Account Number", + "NextAction": "Remove Failed Payment Token and Method", "ErrorType": "NoMatchingError" } ] @@ -2566,15 +2597,15 @@ }, { "Parameters": { - "ComparisonValue": "$.External.ValidationError" + "ComparisonValue": "$.External.Error" }, - "Identifier": "Check for Account Number Validation Error", + "Identifier": "Check for Tokenize Error", "Type": "Compare", "Transitions": { - "NextAction": "Account Number Validation Error", + "NextAction": "Speak Validation Error", "Conditions": [ { - "NextAction": "Store Encrypted Account Number", + "NextAction": "Record Token", "Condition": { "Operator": "Equals", "Operands": ["NULL"] @@ -2583,7 +2614,7 @@ ], "Errors": [ { - "NextAction": "Account Number Validation Error", + "NextAction": "Speak Validation Error", "ErrorType": "NoMatchingCondition" } ] @@ -2591,18 +2622,15 @@ }, { "Parameters": { - "Attributes": { - "EncryptedAccountNumber": "$.StoredCustomerInput" - }, - "TargetContact": "Current" + "Text": "\n>\" rate=\"<>\">\nYour payment was processed successfully.\n\n" }, - "Identifier": "Store Encrypted Account Number", - "Type": "UpdateContactAttributes", + "Identifier": "Payment Success", + "Type": "MessageParticipant", "Transitions": { - "NextAction": "Get Routing Number", + "NextAction": "Check for Customer Email", "Errors": [ { - "NextAction": "Internal Error", + "NextAction": "Check for Customer Email", "ErrorType": "NoMatchingError" } ] @@ -2610,18 +2638,19 @@ }, { "Parameters": { - "Attributes": { - "RoutingNumber": "$.StoredCustomerInput" - }, - "TargetContact": "Current" + "LambdaFunctionARN": "<>", + "InvocationTimeLimitSeconds": "8", + "ResponseValidation": { + "ResponseType": "JSON" + } }, - "Identifier": "Store Routing Number", - "Type": "UpdateContactAttributes", + "Identifier": "Tokenize Transaction", + "Type": "InvokeLambdaFunction", "Transitions": { - "NextAction": "Tokenize Transaction", + "NextAction": "Check for Tokenize Error", "Errors": [ { - "NextAction": "Internal Error", + "NextAction": "Payment Validation Error", "ErrorType": "NoMatchingError" } ] @@ -2629,15 +2658,15 @@ }, { "Parameters": { - "Text": "\n>\" rate=\"<>\">\n$.External.ValidationError\n\nPlease check your entry and try again.\n\n" + "Text": "\n>\" rate=\"<>\">\nThere was a problem validating your $.Attributes.PaymentMethod information.\n\n" }, - "Identifier": "Routing Number Validation Error", + "Identifier": "Payment Validation Error", "Type": "MessageParticipant", "Transitions": { - "NextAction": "Get Routing Number", + "NextAction": "Remove Failed Payment Token and Method", "Errors": [ { - "NextAction": "Get Routing Number", + "NextAction": "Remove Failed Payment Token and Method", "ErrorType": "NoMatchingError" } ] @@ -2645,73 +2674,102 @@ }, { "Parameters": { - "ComparisonValue": "$.StoredCustomerInput" + "StoreInput": "False", + "InputTimeLimitSeconds": "5", + "Text": "\n>\" rate=\"<>\">\nYou previously paid with a credit or debit card ending in $.Attributes.PaymentMethodEndingDigits.\n\nIf you would like to use this card again for this payment, press 1.\nTo use a different payment method, press 2.\n\n" }, - "Identifier": "Routing Number Timeout Check", - "Type": "Compare", + "Identifier": "Use Card Again?", + "Type": "GetParticipantInput", "Transitions": { - "NextAction": "Validate Routing Number", + "NextAction": "Ask for Payment Method", "Conditions": [ { - "NextAction": "Routing Number Timeout", + "NextAction": "Submit Payment", "Condition": { "Operator": "Equals", - "Operands": ["Timeout"] + "Operands": ["1"] + } + }, + { + "NextAction": "Ask for Payment Method", + "Condition": { + "Operator": "Equals", + "Operands": ["2"] } } ], "Errors": [ { - "NextAction": "Validate Routing Number", + "NextAction": "Use Payment Method Again Timeout", + "ErrorType": "InputTimeLimitExceeded" + }, + { + "NextAction": "Ask for Payment Method", "ErrorType": "NoMatchingCondition" + }, + { + "NextAction": "Ask for Payment Method", + "ErrorType": "NoMatchingError" } ] } }, { "Parameters": { - "ComparisonValue": "$.External.ValidationError" + "StoreInput": "False", + "InputTimeLimitSeconds": "5", + "Text": "\n>\" rate=\"<>\">\nYou previously paid with a bank account ending in $.Attributes.PaymentMethodEndingDigits.\n\nIf you would like to use this account again for this payment, press 1.\nTo use a different payment method, press 2.\n\n" }, - "Identifier": "Check for Routing Number Validation Error", - "Type": "Compare", + "Identifier": "Use Bank Account Again?", + "Type": "GetParticipantInput", "Transitions": { - "NextAction": "Routing Number Validation Error", + "NextAction": "Ask for Payment Method", "Conditions": [ { - "NextAction": "Store Routing Number", + "NextAction": "Submit Payment", "Condition": { "Operator": "Equals", - "Operands": ["NULL"] + "Operands": ["1"] + } + }, + { + "NextAction": "Ask for Payment Method", + "Condition": { + "Operator": "Equals", + "Operands": ["2"] } } ], "Errors": [ { - "NextAction": "Routing Number Validation Error", + "NextAction": "Use Payment Method Again Timeout", + "ErrorType": "InputTimeLimitExceeded" + }, + { + "NextAction": "Ask for Payment Method", "ErrorType": "NoMatchingCondition" + }, + { + "NextAction": "Ask for Payment Method", + "ErrorType": "NoMatchingError" } ] } }, { "Parameters": { - "LambdaFunctionARN": "<>", - "InvocationTimeLimitSeconds": "8", - "LambdaInvocationAttributes": { - "ValidationType": "RoutingNumber", - "CustomerEntry": "$.StoredCustomerInput" + "Attributes": { + "PaymentToken": "$.External.PaymentToken" }, - "ResponseValidation": { - "ResponseType": "JSON" - } + "TargetContact": "Current" }, - "Identifier": "Validate Routing Number", - "Type": "InvokeLambdaFunction", + "Identifier": "Record Token", + "Type": "UpdateContactAttributes", "Transitions": { - "NextAction": "Check for Routing Number Validation Error", + "NextAction": "Submit Payment", "Errors": [ { - "NextAction": "Store Routing Number", + "NextAction": "Submit Payment", "ErrorType": "NoMatchingError" } ] @@ -2720,17 +2778,19 @@ { "Parameters": { "Attributes": { - "ExpirationDate": "$.StoredCustomerInput" + "TransactionId": "$.External.TransactionId", + "PaymentMethodEndingDigits": "$.External.PaymentMethodEndingDigits", + "TransactionIds": "$.External.TransactionIds" }, "TargetContact": "Current" }, - "Identifier": "Store Expiration Date", + "Identifier": "Record Transaction Attributes", "Type": "UpdateContactAttributes", "Transitions": { - "NextAction": "Tokenize Transaction", + "NextAction": "Payment Success", "Errors": [ { - "NextAction": "Internal Error", + "NextAction": "Payment Success", "ErrorType": "NoMatchingError" } ] @@ -2738,15 +2798,19 @@ }, { "Parameters": { - "Text": "\n>\" rate=\"<>\">\n$.External.ValidationError\n\nPlease check your entry and try again.\n\n" + "LambdaFunctionARN": "<>", + "InvocationTimeLimitSeconds": "8", + "ResponseValidation": { + "ResponseType": "JSON" + } }, - "Identifier": "Expiration Date Validation Error", - "Type": "MessageParticipant", + "Identifier": "Submit Payment", + "Type": "InvokeLambdaFunction", "Transitions": { - "NextAction": "Get Expiration Date", + "NextAction": "Check for Submit Payment Error", "Errors": [ { - "NextAction": "Get Expiration Date", + "NextAction": "Speak Payment Submission Unknown Error", "ErrorType": "NoMatchingError" } ] @@ -2754,40 +2818,31 @@ }, { "Parameters": { - "ComparisonValue": "$.StoredCustomerInput" + "Text": "\n>\" rate=\"<>\">\nThe payment failed to submit because of an unknown error. You have not been charged.\n\n" }, - "Identifier": "Expiration Date Timeout Check", - "Type": "Compare", + "Identifier": "Speak Payment Submission Unknown Error", + "Type": "MessageParticipant", "Transitions": { - "NextAction": "Validate Expiration Date", - "Conditions": [ - { - "NextAction": "Expiration Date Timeout", - "Condition": { - "Operator": "Equals", - "Operands": ["Timeout"] - } - } - ], + "NextAction": "Remove Failed Payment Token and Method", "Errors": [ { - "NextAction": "Validate Expiration Date", - "ErrorType": "NoMatchingCondition" + "NextAction": "Remove Failed Payment Token and Method", + "ErrorType": "NoMatchingError" } ] } }, { "Parameters": { - "ComparisonValue": "$.External.ValidationError" + "ComparisonValue": "$.External.Error" }, - "Identifier": "Check for Expiration Date Validation Error", + "Identifier": "Check for Submit Payment Error", "Type": "Compare", "Transitions": { - "NextAction": "Expiration Date Validation Error", + "NextAction": "Speak Payment Submission Error", "Conditions": [ { - "NextAction": "Store Expiration Date", + "NextAction": "Record Transaction Attributes", "Condition": { "Operator": "Equals", "Operands": ["NULL"] @@ -2796,7 +2851,7 @@ ], "Errors": [ { - "NextAction": "Expiration Date Validation Error", + "NextAction": "Speak Payment Submission Error", "ErrorType": "NoMatchingCondition" } ] @@ -2804,23 +2859,35 @@ }, { "Parameters": { - "LambdaFunctionARN": "<>", - "InvocationTimeLimitSeconds": "8", - "LambdaInvocationAttributes": { - "ValidationType": "ExpirationDate", - "CustomerEntry": "$.StoredCustomerInput" + "Attributes": { + "PaymentToken": "NULL", + "PaymentMethod": "NULL" }, - "ResponseValidation": { - "ResponseType": "JSON" - } + "TargetContact": "Current" }, - "Identifier": "Validate Expiration Date", - "Type": "InvokeLambdaFunction", + "Identifier": "Remove Failed Payment Token and Method", + "Type": "UpdateContactAttributes", "Transitions": { - "NextAction": "Check for Expiration Date Validation Error", + "NextAction": "Redact Sensitive Contact Attributes", "Errors": [ { - "NextAction": "Store Expiration Date", + "NextAction": "Redact Sensitive Contact Attributes", + "ErrorType": "NoMatchingError" + } + ] + } + }, + { + "Parameters": { + "Text": "\n>\" rate=\"<>\">\nThe payment failed to submit because of the following error:\n\n$.External.Error\n\nYou have not been charged.\n\n" + }, + "Identifier": "Speak Payment Submission Error", + "Type": "MessageParticipant", + "Transitions": { + "NextAction": "Remove Failed Payment Token and Method", + "Errors": [ + { + "NextAction": "Remove Failed Payment Token and Method", "ErrorType": "NoMatchingError" } ] diff --git a/lib/features/receipt-app.ts b/lib/features/receipt-app.ts new file mode 100644 index 0000000..746a969 --- /dev/null +++ b/lib/features/receipt-app.ts @@ -0,0 +1,184 @@ +import { Stack } from 'aws-cdk-lib'; +import { + CfnContactFlow, + CfnHoursOfOperation, + CfnIntegrationAssociation, + CfnQueue, + CfnQuickConnect, +} from 'aws-cdk-lib/aws-connect'; +import { Function } from 'aws-cdk-lib/aws-lambda'; +import { getReceiptFlowContent } from '../connect/content-transformations'; +import { AmazonConnectContext, C3Context, OptionsContext } from '../models'; +import { writeFileToExports } from '../helpers/file'; +import { CfnApplication } from 'aws-cdk-lib/aws-appintegrations'; + +/** + * Class for creating the necessary resources for the agent-assisted receipt app. + */ +export class ReceiptApp { + private receiptQueue: CfnQueue; + private receiptFlow: CfnContactFlow; + + /** + * Creates the necessary resources for the agent-assisted receipt app. + */ + constructor( + private stack: Stack, + private stackLabel: string, + private amazonConnectContext: AmazonConnectContext, + private sendReceiptFunction: Function, + private sendAgentMessageFunction: Function, + private hoursOfOperation: CfnHoursOfOperation, + private externalRoleArn: string, + private c3AppUrlFragment: string, + ) { + console.log('Creating resources for receipt app...'); + this.createReceiptQueue(); + this.createReceiptFlow(); + this.createReceiptQuickConnect(); + const appUrl = this.getReceiptAppUrl( + !this.amazonConnectContext.addAppsToWorkspace, + ); + if (this.amazonConnectContext.addAppsToWorkspace) { + this.createReceiptApp(appUrl); + } + } + + /** + * Creates the queue for the receipt quick connect. + * + * This queue is required so that an agent can send a receipt using a quick connect. + */ + private createReceiptQueue(): void { + console.log('Creating receipt quick connect queue...'); + this.receiptQueue = new CfnQueue(this.stack, 'C3ReceiptQueue', { + name: 'C3 Receipt Quick Connect Queue', + description: 'Queue for sending receipts in the C3 agent workspace.', + instanceArn: this.amazonConnectContext.instanceArn, + hoursOfOperationArn: this.hoursOfOperation.attrHoursOfOperationArn, + }); + } + + /** + * Creates a Amazon Connect flow for sending receipts. + * + * This flow is required to send receipts in the agent workspace. + */ + private createReceiptFlow(): void { + console.log('Creating flow C3ReceiptFlow...'); + const optionsContext = this.stack.node.tryGetContext( + 'options', + ) as OptionsContext; + const receiptFlowContent = getReceiptFlowContent( + this.sendReceiptFunction, + this.sendAgentMessageFunction, + optionsContext.ivrSpeaking, + ); + writeFileToExports('C3ReceiptFlow.json', receiptFlowContent); + this.receiptFlow = new CfnContactFlow(this.stack, 'C3ReceiptFlow', { + name: 'C3 Receipt', + description: 'Flow to send payment receipts in the agent workspace.', + content: receiptFlowContent, + instanceArn: this.amazonConnectContext.instanceArn, + type: 'QUEUE_TRANSFER', + }); + } + + /** + * Creates a quick connect to allow agents to send receipts. + * + * This quick connect is required to send receipts in the agent workspace. + */ + private createReceiptQuickConnect(): void { + console.log('Creating quick connect...'); + new CfnQuickConnect(this.stack, 'C3ReceiptQuickConnect', { + instanceArn: this.amazonConnectContext.instanceArn, + name: 'Receipt', + description: + 'Quick connect for sending receipts in the C3 agent workspace.', + quickConnectConfig: { + quickConnectType: 'QUEUE', + queueConfig: { + contactFlowArn: this.receiptFlow.attrContactFlowArn, + queueArn: this.receiptQueue.attrQueueArn, + }, + }, + }); + } + + /** + * Gets the URL to be used for the C3 Receipt app. + * + * @param customEmbed Whether to use a custom embed URL for the app. + * @returns The URL for the app. + */ + private getReceiptAppUrl(customEmbed: boolean): string { + const c3Context = this.stack.node.tryGetContext('c3') as C3Context; + const instanceId = this.amazonConnectContext.instanceArn.split('/')[1]; + const region = this.amazonConnectContext.instanceArn.split(':')[3]; + + // Add parameters to the URL for the specific features. + let configuredFeatureParams = ''; + if (customEmbed) { + configuredFeatureParams += '&customEmbed=true'; + } + + const appUrl = `https://${c3Context.vendorId}.${this.c3AppUrlFragment}/agent-workspace/receipt?contactCenter=amazon&instanceId=${instanceId}®ion=${region}&externalRoleArn=${this.externalRoleArn}${configuredFeatureParams}`; + writeFileToExports( + 'C3ReceiptAppUrl.txt', + `๐Ÿงพ Your C3 Receipt app URL is:\n\n๐ŸŒ ${appUrl}\n`, + ); + return appUrl; + } + + /** + * Creates a 3rd party application to be used for agent-assisted receipts and associates it with your Amazon Connect instance. + * + * @param appUrl The URL for the 3rd party application. + * This app is required in order for an agent to initiate a receipt while on a call with a customer. Once created, it will show as + * an app in the agent workspace. NOTE: You will also have to enable this app to viewed on the security profile for your agents. + */ + private createReceiptApp(appUrl: string): void { + console.log('Creating receipt application...'); + + // Create the app. + const stackLabelTitleCase = + this.stackLabel.charAt(0).toUpperCase() + this.stackLabel.slice(1); + const appLabel = this.stackLabel ? ` - ${stackLabelTitleCase}` : ''; + const application = new CfnApplication( + this.stack, + `C3ConnectReceiptApp${stackLabelTitleCase}`, + { + name: 'Receipt' + appLabel, // App name is unfortunately required to be unique to create. + namespace: `c3-receipt-${this.stackLabel}`, + description: 'Agent application for sending receipts with C3.', + permissions: ['User.Details.View', 'Contact.Details.View'], + applicationSourceConfig: { + externalUrlConfig: { + accessUrl: appUrl, + approvedOrigins: [], // Don't allow any other origins. + }, + }, + }, + ); + + // Workaround to delete the existing associations. Necessary when the naming format changes. + const skipAssociations = + this.stack.node.tryGetContext('options').skipAssociations; + if (skipAssociations) { + console.log('โš ๏ธ Skipping Amazon Connect associations! โš ๏ธ'); + return; + } + + // Associate the app with the Amazon Connect instance. + new CfnIntegrationAssociation( + this.stack, + `C3ConnectReceiptIntegrationApp`, + { + instanceId: this.amazonConnectContext.instanceArn, + integrationType: 'APPLICATION', + integrationArn: application.attrApplicationArn, + }, + ); + } +} diff --git a/lib/lambda/c3-send-receipt/index.js b/lib/lambda/c3-send-receipt/index.js index 9a00ffd..18bb619 100644 --- a/lib/lambda/c3-send-receipt/index.js +++ b/lib/lambda/c3-send-receipt/index.js @@ -7,12 +7,26 @@ export async function handler(event) { console.log(`EVENT: ${JSON.stringify(event)}`); // Get the contact attributes. - let contactAttributes = {}; - contactAttributes = event.Details.ContactData.Attributes; + const contactAttributes = event.Details.ContactData.Attributes; + const parameters = event.Details.Parameters; + const sendAll = parameters.SendAll === 'true'; + const emailAddress = contactAttributes.Email; - // Email the receipt. + // Send all the receipts, if sendAll is true. + if (sendAll) { + const transactionIds = JSON.parse(contactAttributes.TransactionIds); + for (const transactionId of transactionIds) { + try { + await sendReceiptEmail(transactionId, emailAddress); + } catch (error) { + console.error('Error sending receipt:', error); + } + } + return; + } + + // Otherwise, send the receipt for the current transaction. const transactionId = contactAttributes.TransactionId; - const emailAddress = contactAttributes.Email; await sendReceiptEmail(transactionId, emailAddress); } diff --git a/lib/lambda/c3-submit-payment/index.js b/lib/lambda/c3-submit-payment/index.js index 0c169b6..f8faa21 100644 --- a/lib/lambda/c3-submit-payment/index.js +++ b/lib/lambda/c3-submit-payment/index.js @@ -1,4 +1,5 @@ import { getAPIKey } from '/opt/nodejs/c3.js'; +import { stripTagsFromText } from '/opt/nodejs/formatting.js'; /** * @type {import ('aws-lambda').Handler} @@ -6,64 +7,81 @@ import { getAPIKey } from '/opt/nodejs/c3.js'; export async function handler(event) { console.log(`EVENT: ${JSON.stringify(event)}`); - // Get the contact attributes. - let contactAttributes = {}; - contactAttributes = event.Details.ContactData.Attributes; - if (!contactAttributes) { - throw new Error('Contact attributes not found.'); - } - if (!contactAttributes.PaymentToken) { - throw new Error('PaymentToken contact attribute not found.'); - } - if (!contactAttributes.PaymentMethod) { - throw new Error('PaymentMethod contact attribute not found.'); - } - const paymentMethod = contactAttributes.PaymentMethod; + try { + // Get the contact attributes. + let contactAttributes = {}; + contactAttributes = event.Details.ContactData.Attributes; + if (!contactAttributes) { + throw new Error('Contact attributes not found.'); + } + if (!contactAttributes.PaymentToken) { + throw new Error('PaymentToken contact attribute not found.'); + } + if (!contactAttributes.PaymentMethod) { + throw new Error('PaymentMethod contact attribute not found.'); + } + const paymentMethod = contactAttributes.PaymentMethod; - // Post the transaction. - let paymentInfo = { - name: contactAttributes.ContactName, - paymentAmount: +contactAttributes.PaymentAmount, - token: contactAttributes.PaymentToken, + // Post the transaction. + let paymentInfo = { + name: contactAttributes.ContactName, + paymentAmount: +contactAttributes.PaymentAmount, + token: contactAttributes.PaymentToken, - // Passing these if they exist, but they are not required. - address1: contactAttributes.Address1, - address2: contactAttributes.Address2, - city: contactAttributes.City, - state: contactAttributes.State, - zipCode: contactAttributes.ZipCode, - }; - if (paymentMethod === 'Card') { - const creditCardPaymentInfo = { - expiration: '', // Expiration date is not required for Zift. - }; - paymentInfo = { ...paymentInfo, ...creditCardPaymentInfo }; - } else if (paymentMethod === 'Bank') { - const bankAccountPaymentInfo = { - routingNumber: contactAttributes.RoutingNumber, + // Passing these if they exist, but they are not required. + address1: contactAttributes.Address1, + address2: contactAttributes.Address2, + city: contactAttributes.City, + state: contactAttributes.State, + zipCode: contactAttributes.ZipCode, }; - paymentInfo = { ...paymentInfo, ...bankAccountPaymentInfo }; - } + if (paymentMethod === 'Card') { + const creditCardPaymentInfo = { + expiration: '', // Expiration date is not required for Zift. + }; + paymentInfo = { ...paymentInfo, ...creditCardPaymentInfo }; + } else if (paymentMethod === 'Bank') { + const bankAccountPaymentInfo = { + routingNumber: contactAttributes.RoutingNumber, + }; + paymentInfo = { ...paymentInfo, ...bankAccountPaymentInfo }; + } - const response = await postTransaction( - contactAttributes.PaymentRequestId, - paymentInfo, - ); - console.log('Post transaction response:', response); + const response = await postTransaction( + contactAttributes.PaymentRequestId, + paymentInfo, + ); + console.log('Post transaction response:', response); + + // Get the last 4 digits of the card number or the bank account number. + const maskedNumber = + paymentMethod === 'Card' + ? response.transaction.cardNumber + : response.transaction.bankAccountNumber; + const endingDigits = maskedNumber.slice(-4); - // Get the last 4 digits of the card number or the bank account number. - const maskedNumber = - paymentMethod === 'Card' - ? response.transaction.cardNumber - : response.transaction.bankAccountNumber; - const endingDigits = maskedNumber.slice(-4); + // Update the list of all transaction IDs. + const previousTransactionIds = contactAttributes.TransactionIds + ? JSON.parse(contactAttributes.TransactionIds) + : []; + const newTransactionIds = [ + ...previousTransactionIds, + response.transaction.id, + ]; - return { - TransactionApproved: response.transactionApproved, - TransactionId: response.transaction.id, - TransactionMeta: response.transactionMeta, - PaymentMethodEndingDigits: endingDigits, - }; + return { + TransactionApproved: response.transactionApproved, + TransactionId: response.transaction.id, + TransactionIds: JSON.stringify(newTransactionIds), + TransactionMeta: response.transactionMeta, + PaymentMethodEndingDigits: endingDigits, + Error: 'NULL', + }; + } catch (error) { + return { + Error: stripTagsFromText(error.message), + }; + } } /** @@ -93,8 +111,10 @@ async function postTransaction(paymentRequestId, paymentInfo) { }, ); if (!postTransactionResponse.ok) { + const response = await postTransactionResponse.json(); + const metaInfo = JSON.parse(response.transactionMeta.metaInfo); throw new Error( - `Failed to post transaction: ${postTransactionResponse.statusText}`, + `Zift Error: ${metaInfo.responseMessage ?? 'An unknown error occurred.'}`, ); } return postTransactionResponse.json(); diff --git a/lib/lambda/c3-tokenize-transaction/gateways/zift.js b/lib/lambda/c3-tokenize-transaction/gateways/zift.js index 5262f4d..ae634fd 100644 --- a/lib/lambda/c3-tokenize-transaction/gateways/zift.js +++ b/lib/lambda/c3-tokenize-transaction/gateways/zift.js @@ -155,7 +155,7 @@ export class Zift { : TokenizeErrors.InvalidRoutingNumber; default: // Return the Zift message for any other scenario. - return message; + return `Zift Error: ${message}`; } } } diff --git a/lib/lambda/c3-tokenize-transaction/index.js b/lib/lambda/c3-tokenize-transaction/index.js index 80f763d..717071d 100644 --- a/lib/lambda/c3-tokenize-transaction/index.js +++ b/lib/lambda/c3-tokenize-transaction/index.js @@ -1,4 +1,5 @@ import { decryptData } from '/opt/nodejs/decryption.js'; +import { stripTagsFromText } from '/opt/nodejs/formatting.js'; import { PaymentGateway } from './gateways/payment-gateway.js'; const REDACTED = 'REDACTED'; @@ -68,7 +69,7 @@ export async function handler(event) { // Return the error message to the flow. return { PaymentToken: 'NULL', - Error: tokenizeError.message, + Error: stripTagsFromText(tokenizeError.message), }; } } diff --git a/lib/lambda/c3-utils-layer/lib/nodejs/formatting.js b/lib/lambda/c3-utils-layer/lib/nodejs/formatting.js new file mode 100644 index 0000000..d691fef --- /dev/null +++ b/lib/lambda/c3-utils-layer/lib/nodejs/formatting.js @@ -0,0 +1,12 @@ +/** + * Removes any HTML tags from the given text. + * + * This function is useful for formatting messages to be spoken, to + * ensure that the SSML is not spoken as part of the message. + * + * @param {string} text The text to strip HTML tags from. + * @returns {string} The text with HTML tags removed. + */ +export function stripTagsFromText(text) { + return text.replace(/<[^>]*>/g, ''); +} diff --git a/lib/lambda/c3-validate-entry/bank/validation.js b/lib/lambda/c3-validate-entry/bank/validation.js index cf845b9..281d0c5 100644 --- a/lib/lambda/c3-validate-entry/bank/validation.js +++ b/lib/lambda/c3-validate-entry/bank/validation.js @@ -3,14 +3,17 @@ import { ABARoutingNumber } from './routing-number/formats/aba-routing-number.js /** * Validates a bank account number. * - * There is currently no standard format for US bank account numbers, so this function only checks if the account number is present. + * There is currently no standard format for US bank account numbers, so this function only checks if the account number is between + * 4 and 17 digits. * * @param {string} accountNumber The bank account number to validate. * @returns {string | null} An IVR-speakable error message if the bank account number is invalid, or null if it's valid. */ export function validateAccountNumber(accountNumber) { if (!accountNumber) { - return 'Account number is required.'; + return 'An account number is required.'; + } else if (accountNumber.length < 4 || accountNumber.length > 17) { + return 'The account number must be between 4 and 17 digits.'; } return null; } diff --git a/lib/lambda/c3-validate-entry/card/validation.js b/lib/lambda/c3-validate-entry/card/validation.js index 886947b..a82e977 100644 --- a/lib/lambda/c3-validate-entry/card/validation.js +++ b/lib/lambda/c3-validate-entry/card/validation.js @@ -66,7 +66,7 @@ export function getCardNetwork(cardNumber) { */ export function validateExpirationDate(expirationDate) { if (!expirationDate) { - return 'Expiration date is required.'; + return 'An expiration date is required.'; } else if (!/^\d{4}$/.test(expirationDate)) { return 'The expiration date must be four digits long.'; } diff --git a/lib/models/amazon-connect-context.ts b/lib/models/amazon-connect-context.ts index de92d0a..e8b81ab 100644 --- a/lib/models/amazon-connect-context.ts +++ b/lib/models/amazon-connect-context.ts @@ -2,7 +2,7 @@ export interface AmazonConnectContext { instanceArn: string; securityKeyId: string; securityKeyCertificateContent: string; - workspaceApp: boolean; + addAppsToWorkspace: boolean; receiptQueueArn: string; } diff --git a/lib/models/features-context.ts b/lib/models/features-context.ts index df4f028..887b811 100644 --- a/lib/models/features-context.ts +++ b/lib/models/features-context.ts @@ -5,6 +5,7 @@ export interface FeaturesContext { agentAssistedLink: boolean; selfServiceIVR: boolean; subjectLookup: SubjectLookupMode; + receiptApp: boolean; } /** @@ -30,5 +31,12 @@ export function validateFeaturesContext( throw new Error( 'features.subjectLookup requires features.agentAssistedIVR or features.agentAssistedLink to be enabled.', ); + } else if ( + featuresContext.receiptApp && + !(featuresContext.agentAssistedIVR || featuresContext.agentAssistedLink) + ) { + throw new Error( + 'features.receiptApp requires features.agentAssistedIVR or features.agentAssistedLink to be enabled.', + ); } } diff --git a/package.json b/package.json index 2dbc6d3..9f8aa08 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "cdk": "cdk", "synth": "bash ./scripts/synth.sh", "deploy": "bash ./scripts/deploy.sh", - "display-url": "echo \"$(<./exports/C3WorkspaceAppUrl.txt )\"", + "display-urls": "echo \"$(<./exports/C3PaymentRequestAppUrl.txt )\" && echo \"\n\" && echo \"$(<./exports/C3ReceiptAppUrl.txt )\"", "insert-placeholders": "npm run style:fix && bash ./scripts/insert-placeholders.sh", "compress-files": "bash ./scripts/compress-files.sh", "postinstall": "npm --prefix ./lib/lambda/c3-utils-layer/lib/nodejs ci && npm --prefix ./lib/lambda/c3-create-payment-request ci && npm --prefix ./lib/lambda/c3-validate-entry ci && npm --prefix ./lib/lambda/c3-send-receipt ci && npm --prefix ./lib/lambda/c3-submit-payment ci && npm --prefix ./lib/lambda/c3-tokenize-transaction ci && npm --prefix ./lib/lambda/c3-subject-lookup ci && npm --prefix ./lib/lambda/c3-send-agent-message ci", diff --git a/scripts/deploy.sh b/scripts/deploy.sh index c12e79f..6a7f7a0 100755 --- a/scripts/deploy.sh +++ b/scripts/deploy.sh @@ -27,5 +27,5 @@ done # Run the CDK deploy command with the profile (if provided) cdk deploy $AWS_PROFILE -# Display the URL of the deployed application -npm run display-url +# Display the URLs of the deployed applications +npm run display-urls diff --git a/scripts/insert-placeholders.sh b/scripts/insert-placeholders.sh index bc19a27..0e75272 100755 --- a/scripts/insert-placeholders.sh +++ b/scripts/insert-placeholders.sh @@ -4,8 +4,9 @@ # they can be used in different environments. AGENT_ASSISTED_PAYMENT_IVR_FLOW_FILE="lib/connect/flows/c3-agent-assisted-payment-ivr-flow.json" -SUBJECT_LOOKUP_FLOW_FILE="lib/connect/flows/c3-subject-lookup-flow.json" PAYMENT_IVR_FLOW_MODULE_FILE="lib/connect/flows/modules/c3-payment-ivr-flow-module.json" +SUBJECT_LOOKUP_FLOW_FILE="lib/connect/flows/c3-subject-lookup-flow.json" +RECEIPT_FLOW_FILE="lib/connect/flows/c3-receipt-flow.json" # ---- LAMBDA FUNCTIONS ---- @@ -38,6 +39,7 @@ FUNCTION_NAME="C3SendAgentMessage" PLACEHOLDER="<>" sed -i '' "s|\(\"[^\"]*\": \)\".*${FUNCTION_NAME}.*\"|\1\"$PLACEHOLDER\"|g" "$AGENT_ASSISTED_PAYMENT_IVR_FLOW_FILE" sed -i '' "s|\(\"[^\"]*\": \)\".*${FUNCTION_NAME}.*\"|\1\"$PLACEHOLDER\"|g" "$SUBJECT_LOOKUP_FLOW_FILE" +sed -i '' "s|\(\"[^\"]*\": \)\".*${FUNCTION_NAME}.*\"|\1\"$PLACEHOLDER\"|g" "$RECEIPT_FLOW_FILE" # Replace the ARN of the C3SubjectLookup Lambda function FUNCTION_NAME="C3SubjectLookup" @@ -50,6 +52,11 @@ PLACEHOLDER="<>" sed -i '' "s|\(\"[^\"]*\": \)\".*${FUNCTION_NAME}.*\"|\1\"$PLACEHOLDER\"|g" "$AGENT_ASSISTED_PAYMENT_IVR_FLOW_FILE" sed -i '' "s|\(\"[^\"]*\": \)\".*${FUNCTION_NAME}.*\"|\1\"$PLACEHOLDER\"|g" "$PAYMENT_IVR_FLOW_MODULE_FILE" +# Replace the ARN of the C3SendReceipt Lambda function +FUNCTION_NAME="C3SendReceipt" +PLACEHOLDER="<>" +sed -i '' "s|\(\"[^\"]*\": \)\".*${FUNCTION_NAME}.*\"|\1\"$PLACEHOLDER\"|g" "$RECEIPT_FLOW_FILE" + # ---- SECURITY KEY ---- # Replace the security key ID @@ -73,6 +80,7 @@ PROSODY_TAG='' REPLACEMENT='>\\" rate=\\"<>\\">' sed -i '' "s|$PROSODY_TAG|$REPLACEMENT|g" "$AGENT_ASSISTED_PAYMENT_IVR_FLOW_FILE" sed -i '' "s|$PROSODY_TAG|$REPLACEMENT|g" "$PAYMENT_IVR_FLOW_MODULE_FILE" +sed -i '' "s|$PROSODY_TAG|$REPLACEMENT|g" "$RECEIPT_FLOW_FILE" # ---- RECEIPT QUEUE ID ---- @@ -87,5 +95,6 @@ sed -i '' "s|$QUEUE_ID_PREFIX|$PLACEHOLDER|g" "$PAYMENT_IVR_FLOW_MODULE_FILE" sed -i '' "s| (Working Copy)||g" "$AGENT_ASSISTED_PAYMENT_IVR_FLOW_FILE" sed -i '' "s| (Working Copy)||g" "$PAYMENT_IVR_FLOW_MODULE_FILE" sed -i '' "s| (Working Copy)||g" "$SUBJECT_LOOKUP_FLOW_FILE" +sed -i '' "s| (Working Copy)||g" "$RECEIPT_FLOW_FILE" echo "โœ… Placeholders inserted!" diff --git a/scripts/synth.sh b/scripts/synth.sh index 00ffd4f..8a36792 100755 --- a/scripts/synth.sh +++ b/scripts/synth.sh @@ -27,5 +27,5 @@ done # Run the CDK synth command with the profile (if provided) cdk synth $AWS_PROFILE -# Display the URL of the application -npm run display-url +# Display the URLs of the applications +npm run display-urls diff --git a/test/c3-amazon-connect.test.ts b/test/c3-amazon-connect.test.ts index 7c29751..4cef52b 100644 --- a/test/c3-amazon-connect.test.ts +++ b/test/c3-amazon-connect.test.ts @@ -17,7 +17,7 @@ const mockContext: Context = { securityKeyId: 'placeholder', securityKeyCertificateContent: '-----BEGIN CERTIFICATE-----\\n-----END CERTIFICATE-----\\n', - workspaceApp: true, + addAppsToWorkspace: true, receiptQueueArn: 'placeholder', }, c3: { @@ -30,6 +30,7 @@ const mockContext: Context = { agentAssistedLink: true, selfServiceIVR: true, subjectLookup: SubjectLookupMode.RequiredEditable, + receiptApp: true, }, options: { codeSigning: true, diff --git a/test/features/agent-assisted-ivr.test.ts b/test/features/agent-assisted-ivr.test.ts index ae5bf57..fa33014 100644 --- a/test/features/agent-assisted-ivr.test.ts +++ b/test/features/agent-assisted-ivr.test.ts @@ -17,7 +17,7 @@ const mockContext: Context = { securityKeyId: 'placeholder', securityKeyCertificateContent: '-----BEGIN CERTIFICATE-----\\n-----END CERTIFICATE-----\\n', - workspaceApp: true, + addAppsToWorkspace: true, receiptQueueArn: 'placeholder', }, c3: { @@ -30,6 +30,7 @@ const mockContext: Context = { agentAssistedLink: false, selfServiceIVR: false, subjectLookup: SubjectLookupMode.Disabled, + receiptApp: false, }, options: { codeSigning: true, diff --git a/test/features/agent-assisted-link.test.ts b/test/features/agent-assisted-link.test.ts index 17ffcea..9f764bc 100644 --- a/test/features/agent-assisted-link.test.ts +++ b/test/features/agent-assisted-link.test.ts @@ -17,7 +17,7 @@ const mockContext: Context = { securityKeyId: 'placeholder', securityKeyCertificateContent: '-----BEGIN CERTIFICATE-----\\n-----END CERTIFICATE-----\\n', - workspaceApp: true, + addAppsToWorkspace: true, receiptQueueArn: 'placeholder', }, c3: { @@ -30,6 +30,7 @@ const mockContext: Context = { agentAssistedLink: true, selfServiceIVR: false, subjectLookup: SubjectLookupMode.Disabled, + receiptApp: false, }, options: { codeSigning: true, diff --git a/test/features/self-service-ivr.test.ts b/test/features/self-service-ivr.test.ts index 7306e00..84d6a37 100644 --- a/test/features/self-service-ivr.test.ts +++ b/test/features/self-service-ivr.test.ts @@ -17,7 +17,7 @@ const mockContext: Context = { securityKeyId: 'placeholder', securityKeyCertificateContent: '-----BEGIN CERTIFICATE-----\\n-----END CERTIFICATE-----\\n', - workspaceApp: true, + addAppsToWorkspace: true, receiptQueueArn: 'placeholder', }, c3: { @@ -30,6 +30,7 @@ const mockContext: Context = { agentAssistedLink: false, selfServiceIVR: true, subjectLookup: SubjectLookupMode.Disabled, + receiptApp: false, }, options: { codeSigning: true, diff --git a/test/features/subject-lookup.test.ts b/test/features/subject-lookup.test.ts index 12b6c04..45a764b 100644 --- a/test/features/subject-lookup.test.ts +++ b/test/features/subject-lookup.test.ts @@ -17,7 +17,7 @@ const mockContext: Context = { securityKeyId: 'placeholder', securityKeyCertificateContent: '-----BEGIN CERTIFICATE-----\\n-----END CERTIFICATE-----\\n', - workspaceApp: true, + addAppsToWorkspace: true, receiptQueueArn: 'placeholder', }, c3: { @@ -30,6 +30,7 @@ const mockContext: Context = { agentAssistedLink: false, selfServiceIVR: false, subjectLookup: SubjectLookupMode.OptionalEditable, + receiptApp: false, }, options: { codeSigning: true, diff --git a/test/options/code-signing.test.ts b/test/options/code-signing.test.ts index aaa9d55..1852391 100644 --- a/test/options/code-signing.test.ts +++ b/test/options/code-signing.test.ts @@ -17,7 +17,7 @@ const mockContext: Context = { securityKeyId: 'placeholder', securityKeyCertificateContent: '-----BEGIN CERTIFICATE-----\\n-----END CERTIFICATE-----\\n', - workspaceApp: true, + addAppsToWorkspace: true, receiptQueueArn: 'placeholder', }, c3: { @@ -30,6 +30,7 @@ const mockContext: Context = { agentAssistedLink: true, selfServiceIVR: true, subjectLookup: SubjectLookupMode.RequiredEditable, + receiptApp: true, }, options: { codeSigning: false, diff --git a/test/options/workspace-app.test.ts b/test/options/payment-request-app.test.ts similarity index 90% rename from test/options/workspace-app.test.ts rename to test/options/payment-request-app.test.ts index 8f17c71..b09583e 100644 --- a/test/options/workspace-app.test.ts +++ b/test/options/payment-request-app.test.ts @@ -17,7 +17,7 @@ const mockContext: Context = { securityKeyId: 'placeholder', securityKeyCertificateContent: '-----BEGIN CERTIFICATE-----\\n-----END CERTIFICATE-----\\n', - workspaceApp: true, + addAppsToWorkspace: true, receiptQueueArn: 'placeholder', }, c3: { @@ -30,6 +30,7 @@ const mockContext: Context = { agentAssistedLink: false, selfServiceIVR: false, subjectLookup: SubjectLookupMode.Disabled, + receiptApp: false, }, options: { codeSigning: true, @@ -45,8 +46,8 @@ const mockContext: Context = { const NUMBER_OF_LAMBDAS = 6; -// Verify created resources for agent-assisted IVR. -describe('Workspace app', () => { +// Verify created resources for payment request app +describe('Payment Request App', () => { // 3rd party apps describe('3rd party apps', () => { it('Has 1 3rd party app when flag is true', () => { @@ -64,7 +65,7 @@ describe('Workspace app', () => { }); it('Has no 3rd party apps when flag is false', () => { - mockContext.amazonConnect.workspaceApp = false; + mockContext.amazonConnect.addAppsToWorkspace = false; const app = new App({ context: mockContext, });