Payment Settlement Pipeline

End-to-end payment settlement pipeline covering field validation, fraud detection, payment rail authorization, and ledger settlement. Publishes EventBridge events at each major milestone — fraud detected, payment authorized, and settlement complete.

{
  "Comment": "End-to-end payment settlement pipeline with EventBridge notifications at each milestone",
  "StartAt": "ValidatePayment",
  "States": {
    "ValidatePayment": {
      "Type": "Task",
      "Resource": "arn:aws:states:::lambda:invoke",
      "Parameters": {
        "FunctionName": "${ValidatePaymentFunctionArn}",
        "Payload.$": "$"
      },
      "ResultPath": "$.validation",
      "Retry": [
        {
          "ErrorEquals": [
            "Lambda.ServiceException",
            "Lambda.AWSLambdaException",
            "Lambda.SdkClientException"
          ],
          "IntervalSeconds": 2,
          "MaxAttempts": 3,
          "BackoffRate": 2
        }
      ],
      "Catch": [
        {
          "ErrorEquals": [
            "States.ALL"
          ],
          "ResultPath": "$.error",
          "Next": "PaymentInvalid"
        }
      ],
      "Next": "IsPaymentValid"
    },
    "IsPaymentValid": {
      "Type": "Choice",
      "Choices": [
        {
          "Variable": "$.validation.Payload.isValid",
          "BooleanEquals": true,
          "Next": "RunFraudCheck"
        }
      ],
      "Default": "PaymentInvalid"
    },
    "PaymentInvalid": {
      "Type": "Fail",
      "Error": "InvalidPayment",
      "Cause": "Payment failed field validation"
    },
    "RunFraudCheck": {
      "Type": "Task",
      "Resource": "arn:aws:states:::lambda:invoke",
      "Parameters": {
        "FunctionName": "${RunFraudCheckFunctionArn}",
        "Payload.$": "$.validation.Payload"
      },
      "ResultPath": "$.fraud",
      "Retry": [
        {
          "ErrorEquals": [
            "States.ALL"
          ],
          "IntervalSeconds": 2,
          "MaxAttempts": 2,
          "BackoffRate": 2
        }
      ],
      "Catch": [
        {
          "ErrorEquals": [
            "States.ALL"
          ],
          "ResultPath": "$.error",
          "Next": "FraudCheckError"
        }
      ],
      "Next": "IsFraudulent"
    },
    "FraudCheckError": {
      "Type": "Fail",
      "Error": "FraudCheckUnavailable",
      "Cause": "Fraud detection service was unavailable"
    },
    "IsFraudulent": {
      "Type": "Choice",
      "Choices": [
        {
          "Variable": "$.fraud.Payload.isFraudulent",
          "BooleanEquals": true,
          "Next": "PublishFraudDetectedEvent"
        }
      ],
      "Default": "AuthorizePayment"
    },
    "PublishFraudDetectedEvent": {
      "Type": "Task",
      "Resource": "arn:aws:states:::events:putEvents",
      "Parameters": {
        "Entries": [
          {
            "EventBusName": "default",
            "Source": "thrubit.payments",
            "DetailType": "PaymentFraudDetected",
            "Detail": {
              "paymentId.$": "$.fraud.Payload.paymentId",
              "riskScore.$": "$.fraud.Payload.riskScore",
              "riskLevel.$": "$.fraud.Payload.riskLevel",
              "fraudSignals.$": "$.fraud.Payload.fraudSignals",
              "amount.$": "$.validation.Payload.amount",
              "currency.$": "$.validation.Payload.currency",
              "merchantId.$": "$.validation.Payload.merchantId",
              "customerId.$": "$.validation.Payload.customerId"
            }
          }
        ]
      },
      "ResultPath": "$.fraudEventResult",
      "Next": "FlagFraudulentPayment"
    },
    "FlagFraudulentPayment": {
      "Type": "Task",
      "Resource": "arn:aws:states:::lambda:invoke",
      "Parameters": {
        "FunctionName": "${FlagFraudulentPaymentFunctionArn}",
        "Payload.$": "$.fraud.Payload"
      },
      "ResultPath": "$.flagResult",
      "Next": "PaymentFraudBlocked"
    },
    "PaymentFraudBlocked": {
      "Type": "Fail",
      "Error": "FraudDetected",
      "Cause": "Payment blocked due to fraud signals exceeding risk threshold"
    },
    "AuthorizePayment": {
      "Type": "Task",
      "Resource": "arn:aws:states:::lambda:invoke",
      "Parameters": {
        "FunctionName": "${AuthorizePaymentFunctionArn}",
        "Payload.$": "$.validation.Payload"
      },
      "ResultPath": "$.authorization",
      "Retry": [
        {
          "ErrorEquals": [
            "Lambda.ServiceException",
            "Lambda.AWSLambdaException",
            "Lambda.SdkClientException"
          ],
          "IntervalSeconds": 2,
          "MaxAttempts": 3,
          "BackoffRate": 2
        }
      ],
      "Catch": [
        {
          "ErrorEquals": [
            "States.ALL"
          ],
          "ResultPath": "$.error",
          "Next": "AuthorizationError"
        }
      ],
      "Next": "PublishPaymentAuthorizedEvent"
    },
    "AuthorizationError": {
      "Type": "Fail",
      "Error": "AuthorizationFailed",
      "Cause": "Payment authorization was declined by the payment rail"
    },
    "PublishPaymentAuthorizedEvent": {
      "Type": "Task",
      "Resource": "arn:aws:states:::events:putEvents",
      "Parameters": {
        "Entries": [
          {
            "EventBusName": "default",
            "Source": "thrubit.payments",
            "DetailType": "PaymentAuthorized",
            "Detail": {
              "paymentId.$": "$.authorization.Payload.paymentId",
              "authCode.$": "$.authorization.Payload.authCode",
              "networkTransactionId.$": "$.authorization.Payload.networkTransactionId",
              "amount.$": "$.validation.Payload.amount",
              "currency.$": "$.validation.Payload.currency",
              "merchantId.$": "$.validation.Payload.merchantId",
              "customerId.$": "$.validation.Payload.customerId"
            }
          }
        ]
      },
      "ResultPath": "$.authEventResult",
      "Next": "SettlePayment"
    },
    "SettlePayment": {
      "Type": "Task",
      "Resource": "arn:aws:states:::lambda:invoke",
      "Parameters": {
        "FunctionName": "${SettlePaymentFunctionArn}",
        "Payload.$": "$.authorization.Payload"
      },
      "ResultPath": "$.settlement",
      "Retry": [
        {
          "ErrorEquals": [
            "Lambda.ServiceException",
            "Lambda.AWSLambdaException",
            "Lambda.SdkClientException"
          ],
          "IntervalSeconds": 3,
          "MaxAttempts": 3,
          "BackoffRate": 2
        }
      ],
      "Catch": [
        {
          "ErrorEquals": [
            "States.ALL"
          ],
          "ResultPath": "$.error",
          "Next": "SettlementError"
        }
      ],
      "Next": "PublishSettlementCompleteEvent"
    },
    "SettlementError": {
      "Type": "Fail",
      "Error": "SettlementFailed",
      "Cause": "Payment settled with the payment rail but ledger entry could not be recorded"
    },
    "PublishSettlementCompleteEvent": {
      "Type": "Task",
      "Resource": "arn:aws:states:::events:putEvents",
      "Parameters": {
        "Entries": [
          {
            "EventBusName": "default",
            "Source": "thrubit.payments",
            "DetailType": "PaymentSettled",
            "Detail": {
              "paymentId.$": "$.settlement.Payload.paymentId",
              "settlementId.$": "$.settlement.Payload.settlementId",
              "ledgerEntryId.$": "$.settlement.Payload.ledgerEntryId",
              "authCode.$": "$.settlement.Payload.authCode",
              "amount.$": "$.settlement.Payload.amount",
              "currency.$": "$.settlement.Payload.currency",
              "merchantId.$": "$.settlement.Payload.merchantId",
              "customerId.$": "$.settlement.Payload.customerId",
              "settledAt.$": "$.settlement.Payload.settledAt"
            }
          }
        ]
      },
      "ResultPath": "$.settlementEventResult",
      "Next": "PaymentSettled"
    },
    "PaymentSettled": {
      "Type": "Succeed"
    }
  }
}
JSON
Expand
100%

Financial Services teams can use patterns like this to build reliable, compliant, and scalable automation for payment systems and can test and refine these flows locally with Thrubit to reduce cloud cost and speed up iteration.

Related Articles

  • business person working on a virtual aws state machine
  • thrubit industry financial bank