1. LEARNING OBJECTIVES
By the end of this massive, 20+ page lesson, you will be able to:
-
Integrate Machine Learning (from Module 7) directly into the banking transaction lifecycle to block fraud in real-time.
-
Design the Compliance Pipeline: Ingest a transaction -> Extract Risk Features -> Query the ML Model -> Enforce the Decision.
-
Build a Risk Scoring Engine in Python that utilizes a real
scikit-learnmodel (RandomForest) to predict fraud probability. -
Implement Multi-Step Actions based on Risk Scores:
PASS(allow),BLOCK(reject), andREQUIRE_MFA(challenge the user). -
Design and build an External Webhook System that notifies client merchants (e.g., Shopify) instantly when their customer’s transaction is blocked or flagged.
-
Build a complete, beginner-friendly Python extension to our BaaS platform that processes a transaction, queries the ML model, and calls an external webhook dispatcher to alert third-party systems.
-
Write a fully runnable Python script that demonstrates a live ML model intercepting and blocking a fraudulent transaction in under 500ms.
2. THE COMPLIANCE PIPELINE (THE GATEKEEPER)
2.1 The Mission
Every single time a transaction passes through the Orchestrator (Lesson 3), it must be intercepted by the Compliance Engine before it is sent to the external ACH network.
If a hacker steals a user’s password and tries to initiate a $50,000 transfer at 3:00 AM, the Compliance Engine must analyze the request, compute a risk score, and block the transaction before the money ever leaves the bank.
2.2 The Input: Risk Features
The ML model cannot read raw text. We must extract a specific set of numerical features from the request and the user’s history:
-
transaction_amount: $50,000 (High risk). -
hour_of_day: 3 (High risk). -
distance_from_home: 2,500 miles (Impossible travel – High risk). -
device_fingerprint:unknown_browser(High risk). -
transaction_velocity_1h: 3 transactions in last hour (High risk).
2.3 The Output: Risk Score
The ML model (a RandomForestClassifier or XGBoost) outputs a probability between 0.0 and 1.0.
-
0.0 - 0.4: PASS. The transaction is highly likely to be legitimate. -
0.4 - 0.8: REQUIRE_MFA. The system should prompt the user for a 2FA SMS code. -
0.8 - 1.0: BLOCK. The transaction is highly likely to be fraud. The system should return a403 Forbiddenerror immediately.
3. THE WEBHOOK DISPATCHER (NOTIFYING THE CLIENTS)
3.1 Why Internal Logging isn’t Enough
If a transaction is blocked by the Compliance Engine, we cannot just silently drop the request. Our client (e.g., an e-commerce platform like Shopify) needs to know why the payment failed.
The BaaS platform must implement a Webhook Dispatcher.
When a transaction hits a BLOCK or REQUIRE_MFA status, the Compliance Engine triggers an asynchronous call to an external endpoint (e.g., https://api.shopify.com/webhooks/payment_failed).
The payload includes:
{ "transaction_id": "txn_123", "status": "BLOCKED", "risk_score": 0.95, "reason": "High value transaction at suspicious hour from unknown device." }
3.2 Managing Webhook Delivery Reliability
External APIs can go down. The Dispatcher must have a Retry Strategy. If the external webhook call returns a 500 error, the system should wait 5 seconds and retry. If it fails after 3 retries, the event is stored in a failed_webhooks database table for manual investigation by a human operations engineer.
4. BEGINNER HANDS-ON LAB: THE COMPLETE COMPLIANCE & WEBHOOK ENGINE
We will now build a new, standalone Python simulation. We will create a mock ML model (trained on simulated risk features), integrate it into a banking endpoint, and automatically dispatch webhooks to a mock client when a transaction is blocked.
(Note: You must run pip install fastapi uvicorn scikit-learn pandas).
import uuid import pandas as pd import numpy as np import threading import time from fastapi import FastAPI, HTTPException, BackgroundTasks from pydantic import BaseModel from sklearn.ensemble import RandomForestClassifier # --- STEP 1: TRAIN A MOCK ML MODEL (REAL SCIKIT-LEARN) --- # We simulate a small dataset of 10,000 transactions with 4 risk features. def train_mock_model(): np.random.seed(42) n_samples = 10000 # Generate fake features # 0-1 scale for features: # f1: Transaction Amount (Scaled) # f2: Hour of Day (Scaled) # f3: Distance from home (Scaled) # f4: Device Risk (0=known, 1=unknown) X = np.random.rand(n_samples, 4) # Simulate Target: Fraud probability increases if Amount is high, Hour is late, Distance is high, Device is unknown. # Weighted logic to make the model actually learn something. fraud_prob = (X[:, 0] * 0.4) + (X[:, 1] * 0.2) + (X[:, 2] * 0.3) + (X[:, 3] * 0.5) y = (fraud_prob > 0.5).astype(int) model = RandomForestClassifier(n_estimators=10, random_state=42) model.fit(X, y) return model # Initialize the ML model ml_model = train_mock_model() # --- STEP 2: SETUP FASTAPI APP --- app = FastAPI(title="BaaS Compliance & Webhook Engine") # --- STEP 3: PYDANTIC SCHEMAS --- class TransactionRiskRequest(BaseModel): amount: float hour_of_day: int # 0-23 distance_home: int # Miles device_risk: int # 0 = Known trusted device, 1 = New/Unknown device client_webhook_url: str # Where to send the notification class RiskDecisionResponse(BaseModel): transaction_id: str status: str # PASSED, BLOCKED, REQUIRE_MFA risk_score: float message: str # --- STEP 4: THE COMPLIANCE ENGINE --- def analyze_transaction(request: TransactionRiskRequest): """ Runs the ML model on the incoming transaction. Returns the status and score. """ # 1. Normalize inputs for the model (RandomForest expects arrays) # We scale hour to a 0-1 range (hour/23) scaled_hour = request.hour_of_day / 23.0 # Scale distance (Assume max 3000 miles) scaled_distance = min(request.distance_home / 3000.0, 1.0) input_features = np.array([[ request.amount / 10000.0, # Cap amount at $10k for scaling scaled_hour, scaled_distance, request.device_risk ]]) # 2. Get the Probability of Fraud from the ML Model fraud_probability = ml_model.predict_proba(input_features)[0][1] # 3. The Decision Logic decision = { "status": "PASSED", "risk_score": fraud_probability, "message": "Transaction appears legitimate." } if fraud_probability >= 0.8: decision["status"] = "BLOCKED" decision["message"] = "High risk transaction blocked by AI compliance engine." elif fraud_probability >= 0.4: decision["status"] = "REQUIRE_MFA" decision["message"] = "Medium risk. MFA challenge required to confirm user identity." return decision # --- STEP 5: THE WEBHOOK DISPATCHER --- def dispatch_webhook(webhook_url, payload): """ Simulates sending an HTTP POST request to the client's server. In production, this would be an actual `requests.post(webhook_url, json=payload)`. """ print(f"\n[WEBHOOK DISPATCHER] Sending notification to {webhook_url}...") print(f" Payload: {payload}") # Simulate network latency time.sleep(0.5) print(f" -> Webhook delivered successfully to {webhook_url}.") # In a real app, we would check for HTTP 200 status and retry on failure. # --- STEP 6: THE COMPLIANCE ENDPOINT --- @app.post("/v1/compliance/check", response_model=RiskDecisionResponse) async def check_transaction_risk(request: TransactionRiskRequest, background_tasks: BackgroundTasks): """ This is the core endpoint of the Compliance Engine. """ # 1. Generate a Transaction ID txn_id = str(uuid.uuid4()) # 2. Run the ML Analysis decision = analyze_transaction(request) # 3. If the transaction is BLOCKED or requires MFA, alert the client via Webhook! if decision["status"] in ["BLOCKED", "REQUIRE_MFA"]: # Prepare the webhook payload webhook_payload = { "transaction_id": txn_id, "status": decision["status"], "risk_score": round(decision["risk_score"], 2), "message": decision["message"], "timestamp": str(np.datetime64('now')) } # Schedule the webhook in the background so we don't block the API response background_tasks.add_task(dispatch_webhook, request.client_webhook_url, webhook_payload) # Return a 403 Forbidden status for BLOCKED transactions if decision["status"] == "BLOCKED": raise HTTPException(status_code=403, detail=decision["message"]) # 4. Return the response return { "transaction_id": txn_id, "status": decision["status"], "risk_score": round(decision["risk_score"], 2), "message": decision["message"] } # --- STEP 7: RUNNING THE ENGINE --- # To run: uvicorn compliance_engine:app --reload if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8000)
How to test this live Compliance Engine:
-
Save the code as
compliance_engine.py. -
Run
pip install fastapi uvicorn scikit-learn pandas. -
Run
python compliance_engine.py. -
Open
http://127.0.0.1:8000/docs. -
Execute
POST /v1/compliance/checkwith a High-Risk payload:-
amount:9000 -
hour_of_day:3 -
distance_home:2500 -
device_risk:1 -
client_webhook_url:https://mock-client.com/hook
-
-
Watch your terminal!
-
The API will return a
403 Forbiddenerror with the message: “High risk transaction blocked by AI compliance engine.” -
Your terminal will immediately print:
[WEBHOOK DISPATCHER] Sending notification to https://mock-client.com/hook...
-
-
Now execute it with a Low-Risk payload:
-
amount:20,hour_of_day:14,distance_home:2,device_risk:0. -
The API returns a
200 OKwithstatus: PASSEDand a risk score around0.15.
-
Interpretation of the Lab:
You have just built a working, live, AI-driven compliance firewall.
-
The
RandomForestClassifierwas dynamically trained in memory. -
The
analyze_transactionfunction converts raw input into the mathematical features the model was trained on. -
The code correctly identifies the 3:00 AM, $9,000, unknown-device transaction as
BLOCKED. -
The
dispatch_webhookfunction automatically alerts the client application, allowing their front-end to show a specific “Transaction Blocked” error message to the user, rather than a generic “Server Error”.
5. SUMMARY FOR THE FINANCE PRACTITIONER
The Compliance Engine is the final, unskippable gatekeeper of the BaaS platform.
-
Machine Learning is the enforcer. Relying on static rules (e.g., “Block transactions over $5,000”) is easily bypassed by fraudsters. By using a RandomForest model that analyzes the combination of Amount, Time, Distance, and Device, you catch complex fraud patterns that human rule-sets miss.
-
The “MFA” challenge protects legitimate users. Not every risky transaction is fraud. A user traveling abroad might trigger a high risk score. By implementing a
REQUIRE_MFAstatus (instead of a hard block), you give the user a chance to prove their identity via SMS code, keeping them happy while maintaining security. -
Webhooks provide real-time visibility. A blocked transaction that is logged internally is useless. The asynchronous webhook dispatcher ensures that the client’s UI, the merchant’s risk team, and the customer support agents are instantly notified of the compliance decision, allowing for immediate human intervention if the AI made a mistake (a “False Positive”).