Payment service integrates with Stripe and provides a REST API for pre-authorization, collection and refund operations.
Payment is comprised of a Serverless Application Repository App named API Lambda Stripe Charge and Python Lambda functions.
The SAR App provides a public regional API Gateway endpoint coupled with Lambda functions that integrates with Stripe.
Lambda Stripe Charge requires a Stripe Secret key to be stored in Parameter Store. We read the environment variable STRIPE_SECRET_KEY
set in Amplify Console, and as part of the custom workflow we store the value in a parameter named /{env}/service/payment/stripe/secretKey
.
API currently provides the following resources:
Resource | Method | Description |
---|---|---|
/charge | POST | Pre-authorize payment by invoking CreateStripeCharge Lambda function. It expects a simple JSON blob with amount , currency , stripeToken , description , email as keys - See Stripe specification for values and response. |
/capture | POST | Capture pre-authorized payment by invoking CaptureStripeCharge Lambda function. It expects chargeId with the previously captured payment token - See Stripe specification for response values. |
/refund | POST | Refund existing payment by invoking CreateRefund Lambda function. It expects chargeId with the previously captured payment token - See Stripe specification for response values. |
Both functions call our Lambda Stripe Charge API as part of the Booking business workflow to collect previous pre-authorizations and refund should a booking isn't successful. PAYMENT_API_URL
environment variable defined SAR App API URL.
Custom metrics currently emitted to CloudWatch:
Metric | Description | Dimensions |
---|---|---|
ColdStart | Number of cold start executions | function_name , service |
InvalidPaymentRequest | Number of payment transactions that didn't include pre-authorization/authorization charge token for collection | service |
InvalidRefundRequest | Number of payment transactions that didn't include pre-authorization/authorization charge token for refund | service |
SuccessfulPayment | Number of payments successfully collected from confirmed bookings | service |
FailedPayment | Number of payments that failed to be collected from confirmed bookings e.g. payment already collected from charge token | service |
{env}
being a git branch from where deployment originates (e.g. twitch):
Parameter | Description |
---|---|
/{env}/service/payment/function/collect | Collect-function ARN |
/{env}/service/payment/function/refund | Refund-function ARN |
/{env}/service/payment/stripe/secretKey | Stripe Secret Key, created and managed by Amplify Console Custom workflow |
Stripe Elements provides card UI and Stripe JS implements card tokenization and validation. Once card is tokenized and validated, the front-end posts the tokenized information to the SAR App API on /charge
. If successful, it makes a call to Booking API to starts processing booking details.
Process Booking state machine invokes Collect
and Refund
function as part of their execution steps. As of now, Step Functions doesn't support HTTP calls hence we need Lambda functions to call our SAR App API.
Almost as a tech debt record, this help us understand why certain patterns were implemented over others.
Decision | Description | Timeframe |
---|---|---|
Abstract Stripe implementation | Most customers already have a payment provider and we wanted to replicate that with minimum effort. API Gateway provides a contract for payment operations regardless of the payment provider, and Lambda functions provide additional operations visibility. | During Twitch season (Apr-Aug '19) |
Drop Logging Stack | AWS Lambda Powertools Metrics utilize the new Amazon CloudWatch Embedded Metrics Format (EMF) making our custom implementation unnecessary. This also has the benefit of not requiring any additional stack. | July 22nd 2020 |
Introduce Lambda Layers | Dependencies are now deployed separately as a Lambda Layer given it's shared with Booking too. This makes new changes to be deployed in seconds from ~1.5m. | July 24th 2020 |