Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Orchestration pipeline

Four POST steps of a fake payment flow, for gateway request chaining, workflow and API composition demos: each step needs something the previous one produced. The module keeps no state, so steps can be called independently.

StepRequiresProduces
POST /orchestration/step/1 (authenticate)a non-empty X-Api-Key (else 401)correlation_id, merchant details, permissions
POST /orchestration/step/2 (enrich)X-Correlation-Idenrichment.risk_score (0 to 99), risk level, card details, velocity check
POST /orchestration/step/3 (validate)X-Correlation-Idvalidation.result: approved, or declined when a rule fails
POST /orchestration/step/4 (process)X-Correlation-Id and X-Validation-Result: approved (else 403)a completed transaction
GET /orchestration/statusMachine-readable documentation of the pipeline

Validation rules: risk score below 70, amount at most 50000, merchant active, card_payment permitted, velocity check. The risk score is a stable hash of the correlation id, merchant, amount and card BIN, so the same inputs always get the same score and roughly 30 percent of flows are declined. Step 3 uses the risk_score from its body when given (what an orchestration layer passes along from step 2), else computes it (risk_score_source says which). Errors, including malformed JSON, go through JSON / XML content negotiation.

The chained flow, the way a gateway's orchestration feature would run it:

# Step 1: authenticate (any non-empty X-Api-Key) and get a correlation id.
POST {{base_url}}/orchestration/step/1
X-Api-Key: demo-key
Content-Type: application/json
{"merchant_id": "merchant_123"}
HTTP 200
[Captures]
correlation_id: jsonpath "$.correlation_id"
[Asserts]
jsonpath "$.status" == "success"
jsonpath "$.permissions" contains "card_payment"

# Step 2: enrich. The risk score is a stable hash of the inputs.
POST {{base_url}}/orchestration/step/2
X-Correlation-Id: {{correlation_id}}
Content-Type: application/json
{"merchant_id": "merchant_123", "card_number": "4111111111111111", "amount": 99.99}
HTTP 200
[Captures]
risk_score: jsonpath "$.enrichment.risk_score"
[Asserts]
jsonpath "$.correlation_id" == "{{correlation_id}}"
jsonpath "$.enrichment.risk_threshold" == 70

# Step 3: validate, passing the enrichment result along.
POST {{base_url}}/orchestration/step/3
X-Correlation-Id: {{correlation_id}}
Content-Type: application/json
{"merchant_id": "merchant_123", "amount": 99.99, "currency": "USD", "risk_score": {{risk_score}}}
HTTP 200
[Asserts]
jsonpath "$.validation.risk_score" == {{risk_score}}
jsonpath "$.validation.risk_score_source" exists
jsonpath "$.validation.result" matches /^(approved|declined)$/

An approved and a declined validation, with what step 4 does with each:

# A low risk score is approved; step 4 then processes the payment.
POST {{base_url}}/orchestration/step/3
X-Correlation-Id: demo-corr-1
Content-Type: application/json
{"merchant_id": "merchant_123", "amount": 99.99, "currency": "USD", "risk_score": 15}
HTTP 200
[Asserts]
jsonpath "$.validation.result" == "approved"

POST {{base_url}}/orchestration/step/4
X-Correlation-Id: demo-corr-1
X-Validation-Result: approved
Content-Type: application/json
{"merchant_id": "merchant_123", "amount": 99.99, "currency": "USD"}
HTTP 200
[Asserts]
jsonpath "$.transaction.status" == "completed"
jsonpath "$.transaction.processor_response.code" == "00"
POST {{base_url}}/orchestration/step/3
X-Correlation-Id: demo-corr-2
Content-Type: application/json
{"merchant_id": "merchant_123", "amount": 99.99, "risk_score": 85}
HTTP 200
[Asserts]
jsonpath "$.validation.approved" == false
jsonpath "$.validation.result" == "declined"

POST {{base_url}}/orchestration/step/4
X-Correlation-Id: demo-corr-2
X-Validation-Result: declined
Content-Type: application/json
{"amount": 99.99, "currency": "USD"}
HTTP 403
POST {{base_url}}/orchestration/step/1
Content-Type: application/json
{"merchant_id": "merchant_123"}
HTTP 401