Case Study 2: Credit Card Authorization System
Background
Coastal Federal Bank (CFB) issues approximately 2.8 million credit cards across its consumer, business, and premium product lines. Every time a cardholder presents their card at a merchant terminal, an authorization request travels from the point-of-sale device through the payment network to CFB's mainframe authorization engine -- a COBOL program called CCAUTH that must return a decision within 250 milliseconds.
The authorization engine is the bank's single most critical real-time system. A false decline frustrates the cardholder and costs the bank interchange revenue. A false approval exposes the bank to fraud losses. In 2023, CFB processed an average of 3.4 million authorization requests per day, approving 94.2% and declining 5.8%.
In early 2024, CFB's fraud analytics team identified a gap in the authorization engine: the existing logic used simple threshold checks for fraud detection but did not combine multiple risk factors into a single decision. The team requested an enhancement to implement multi-factor authorization -- a system that evaluates card status, available credit, transaction velocity, merchant category, and fraud risk indicators simultaneously, using compound conditions and multi-dimensional decision logic.
Priya Venkatesh, a senior COBOL developer with 11 years of experience in payment systems, was assigned to redesign the authorization decision engine. This case study examines her implementation, which demonstrates EVALUATE for transaction routing, nested IF for multi-factor checks, 88-level conditions for card and transaction states, and complex compound conditions for authorization rules.
The Business Requirements
The authorization engine must evaluate each incoming transaction against six sequential checks:
- Card Status Check -- Is the card active? Cards that are blocked, stolen, lost, or frozen must be declined immediately.
- Available Credit Check -- Does the cardholder have sufficient available credit for the transaction amount?
- Transaction Velocity Check -- Has this card been used an abnormal number of times in the last 24 hours?
- Merchant Category Check -- Is the merchant category code (MCC) restricted for this card product?
- Fraud Score Check -- Does the real-time fraud scoring model flag this transaction as suspicious?
- Multi-Factor Risk Assessment -- Combining transaction amount, geographic location, and fraud score into a final risk determination.
Each check can produce one of three outcomes: - PASS -- The transaction clears this check and proceeds to the next - FLAG -- The transaction is marked for post-authorization review but continues - FAIL -- The transaction is immediately declined with a specific response code
The Complete Program
IDENTIFICATION DIVISION.
PROGRAM-ID. CCAUTH.
*================================================================*
* Program: CCAUTH
* Description: Credit Card Multi-Factor Authorization Engine
* Author: Priya Venkatesh
* Date: 2024-04-10
* Purpose: Demonstrates conditional logic patterns for
* real-time credit card authorization at
* Coastal Federal Bank.
*================================================================*
DATA DIVISION.
WORKING-STORAGE SECTION.
*================================================================*
* PROGRAM CONSTANTS *
*================================================================*
01 WS-C-VELOCITY-LIMITS.
05 WS-C-MAX-DAILY-TXN PIC 9(03) VALUE 025.
05 WS-C-MAX-HOURLY-TXN PIC 9(02) VALUE 008.
05 WS-C-HIGH-VALUE-LIMIT PIC 9(07)V99
VALUE 5000.00.
05 WS-C-VERY-HIGH-VALUE PIC 9(07)V99
VALUE 10000.00.
01 WS-C-FRAUD-THRESHOLDS.
05 WS-C-FRAUD-LOW-MAX PIC 9(03) VALUE 030.
05 WS-C-FRAUD-MED-MAX PIC 9(03) VALUE 060.
05 WS-C-FRAUD-HIGH-MAX PIC 9(03) VALUE 080.
01 WS-C-REPORT-SEP PIC X(65) VALUE ALL '='.
01 WS-C-DETAIL-SEP PIC X(65) VALUE ALL '-'.
*================================================================*
* PROCESSING FLAGS *
*================================================================*
01 WS-F-CONTINUE-FLAG PIC X(01) VALUE 'Y'.
88 WS-CONTINUE-PROCESSING VALUE 'Y'.
88 WS-STOP-PROCESSING VALUE 'N'.
01 WS-F-REVIEW-FLAG PIC X(01) VALUE 'N'.
88 WS-NEEDS-REVIEW VALUE 'Y'.
88 WS-NO-REVIEW-NEEDED VALUE 'N'.
01 WS-F-FLAG-COUNT PIC 9(02) VALUE ZERO.
*================================================================*
* AUTHORIZATION RESULT *
*================================================================*
01 WS-AUTH-RESULT.
05 WS-AUTH-RESPONSE-CODE PIC X(02) VALUE SPACES.
88 AUTH-APPROVED VALUE '00'.
88 AUTH-APPROVED-REVIEW VALUE '01'.
88 AUTH-CALL-CENTER VALUE '02'.
88 AUTH-DECLINED-CREDIT VALUE '51'.
88 AUTH-DECLINED-CARD VALUE '05'.
88 AUTH-DECLINED-STOLEN VALUE '43'.
88 AUTH-DECLINED-LOST VALUE '41'.
88 AUTH-DECLINED-FROZEN VALUE '62'.
88 AUTH-DECLINED-VELOCITY VALUE '65'.
88 AUTH-DECLINED-FRAUD VALUE '59'.
88 AUTH-DECLINED-MCC VALUE '57'.
88 AUTH-SYSTEM-ERROR VALUE '96'.
05 WS-AUTH-MESSAGE PIC X(50) VALUE SPACES.
05 WS-AUTH-RISK-LEVEL PIC X(01) VALUE SPACE.
88 RISK-LOW VALUE 'L'.
88 RISK-MEDIUM VALUE 'M'.
88 RISK-HIGH VALUE 'H'.
88 RISK-CRITICAL VALUE 'C'.
05 WS-AUTH-FLAGS-RAISED PIC 9(02) VALUE ZERO.
*================================================================*
* CARD INFORMATION (from card master file) *
*================================================================*
01 WS-CARD-INFO.
05 WS-CARD-NUMBER PIC X(16).
05 WS-CARD-STATUS PIC X(01).
88 CARD-ACTIVE VALUE 'A'.
88 CARD-BLOCKED VALUE 'B'.
88 CARD-STOLEN VALUE 'S'.
88 CARD-LOST VALUE 'L'.
88 CARD-FROZEN VALUE 'Z'.
88 CARD-EXPIRED VALUE 'E'.
88 CARD-USABLE VALUE 'A'.
88 CARD-COMPROMISED VALUE 'S' 'L'.
88 CARD-INACTIVE
VALUE 'B' 'S' 'L' 'Z' 'E'.
05 WS-CARD-PRODUCT PIC X(02).
88 PRODUCT-STANDARD VALUE 'ST'.
88 PRODUCT-GOLD VALUE 'GD'.
88 PRODUCT-PLATINUM VALUE 'PT'.
88 PRODUCT-BUSINESS VALUE 'BZ'.
88 PRODUCT-PREMIUM
VALUE 'GD' 'PT'.
05 WS-CREDIT-LIMIT PIC 9(07)V99.
05 WS-CURRENT-BALANCE PIC 9(07)V99.
05 WS-AVAILABLE-CREDIT PIC S9(07)V99.
05 WS-DAILY-TXN-COUNT PIC 9(03).
05 WS-HOURLY-TXN-COUNT PIC 9(02).
05 WS-CARDHOLDER-NAME PIC X(25).
*================================================================*
* TRANSACTION INFORMATION (from authorization request) *
*================================================================*
01 WS-TXN-INFO.
05 WS-TXN-AMOUNT PIC 9(07)V99.
05 WS-TXN-MERCHANT-NAME PIC X(25).
05 WS-TXN-MCC PIC X(04).
88 MCC-GAMBLING
VALUE '7800' '7801' '7802' '7995'.
88 MCC-CASH-ADVANCE
VALUE '6010' '6011' '6012'.
88 MCC-WIRE-TRANSFER
VALUE '4829'.
88 MCC-CRYPTO
VALUE '6051'.
88 MCC-HIGH-RISK-MCC
VALUE '7800' '7801' '7802' '7995'
'6010' '6011' '6012'
'4829' '6051'.
88 MCC-RETAIL
VALUE '5200' THRU '5499'
'5500' THRU '5699'
'5700' THRU '5799'.
88 MCC-GROCERY
VALUE '5411' '5422' '5441' '5451'.
88 MCC-RESTAURANT
VALUE '5812' '5813' '5814'.
05 WS-TXN-COUNTRY PIC X(03).
88 TXN-DOMESTIC VALUE 'USA'.
88 TXN-CANADA VALUE 'CAN'.
88 TXN-ALLIED-COUNTRY
VALUE 'USA' 'CAN' 'GBR' 'AUS'.
88 TXN-HIGH-RISK-COUNTRY
VALUE 'NGA' 'ROU' 'UKR' 'RUS' 'BRA'.
88 TXN-CROSS-BORDER VALUE
'CAN' 'GBR' 'AUS' 'FRA' 'DEU'
'JPN' 'NGA' 'ROU' 'UKR' 'RUS' 'BRA'
'MEX' 'IND' 'CHN' 'KOR'.
05 WS-TXN-ENTRY-MODE PIC X(02).
88 ENTRY-CHIP VALUE 'CP'.
88 ENTRY-CONTACTLESS VALUE 'CL'.
88 ENTRY-SWIPE VALUE 'SW'.
88 ENTRY-MANUAL VALUE 'MN'.
88 ENTRY-ECOMMERCE VALUE 'EC'.
88 ENTRY-CARD-PRESENT
VALUE 'CP' 'CL' 'SW'.
88 ENTRY-CARD-NOT-PRESENT
VALUE 'MN' 'EC'.
05 WS-TXN-FRAUD-SCORE PIC 9(03).
88 FRAUD-LOW-RISK VALUE 000 THRU 030.
88 FRAUD-MED-RISK VALUE 031 THRU 060.
88 FRAUD-HIGH-RISK VALUE 061 THRU 080.
88 FRAUD-CRITICAL VALUE 081 THRU 100.
88 FRAUD-ACCEPTABLE VALUE 000 THRU 060.
*================================================================*
* MCC RESTRICTION TABLE (by product) *
*================================================================*
01 WS-MCC-RESTRICTIONS.
05 WS-STANDARD-RESTRICTED PIC X(01) VALUE 'Y'.
88 STD-HAS-MCC-LIMITS VALUE 'Y'.
05 WS-BUSINESS-RESTRICTED PIC X(01) VALUE 'N'.
88 BIZ-NO-MCC-LIMITS VALUE 'N'.
*================================================================*
* DISPLAY FIELDS *
*================================================================*
01 WS-DSP-AMOUNT PIC $$$,$$$,$$9.99.
01 WS-DSP-SCORE PIC ZZ9.
01 WS-DSP-COUNT PIC ZZ9.
*--- Test data counter ---
01 WS-TEST-TXN-NUMBER PIC 9(01) VALUE ZERO.
PROCEDURE DIVISION.
0000-MAIN-CONTROL.
PERFORM 1000-INITIALIZATION
PERFORM 2000-PROCESS-TRANSACTIONS
STOP RUN
.
*================================================================*
* 1000-INITIALIZATION *
*================================================================*
1000-INITIALIZATION.
DISPLAY WS-C-REPORT-SEP
DISPLAY ' COASTAL FEDERAL BANK'
DISPLAY ' CREDIT CARD AUTHORIZATION ENGINE'
DISPLAY WS-C-REPORT-SEP
DISPLAY SPACES
.
*================================================================*
* 2000-PROCESS-TRANSACTIONS: Run authorization for test cases *
*================================================================*
2000-PROCESS-TRANSACTIONS.
* Transaction 1: Normal domestic retail purchase
PERFORM 2010-CLEAR-AUTH
PERFORM 2100-LOAD-TXN-1
PERFORM 3000-AUTHORIZE-TRANSACTION
PERFORM 4000-DISPLAY-RESULT
* Transaction 2: Cross-border high-value from compromised
* card
PERFORM 2010-CLEAR-AUTH
PERFORM 2100-LOAD-TXN-2
PERFORM 3000-AUTHORIZE-TRANSACTION
PERFORM 4000-DISPLAY-RESULT
* Transaction 3: E-commerce gambling purchase with high
* fraud score
PERFORM 2010-CLEAR-AUTH
PERFORM 2100-LOAD-TXN-3
PERFORM 3000-AUTHORIZE-TRANSACTION
PERFORM 4000-DISPLAY-RESULT
* Transaction 4: Normal restaurant purchase, velocity alert
PERFORM 2010-CLEAR-AUTH
PERFORM 2100-LOAD-TXN-4
PERFORM 3000-AUTHORIZE-TRANSACTION
PERFORM 4000-DISPLAY-RESULT
* Transaction 5: Large cross-border purchase, medium fraud
PERFORM 2010-CLEAR-AUTH
PERFORM 2100-LOAD-TXN-5
PERFORM 3000-AUTHORIZE-TRANSACTION
PERFORM 4000-DISPLAY-RESULT
.
*================================================================*
* 2010-CLEAR-AUTH: Reset authorization fields *
*================================================================*
2010-CLEAR-AUTH.
INITIALIZE WS-AUTH-RESULT
INITIALIZE WS-CARD-INFO
INITIALIZE WS-TXN-INFO
SET WS-CONTINUE-PROCESSING TO TRUE
SET WS-NO-REVIEW-NEEDED TO TRUE
MOVE ZERO TO WS-F-FLAG-COUNT
.
*================================================================*
* LOAD TEST TRANSACTION 1: Normal domestic retail *
*================================================================*
2100-LOAD-TXN-1.
MOVE '4532100098761234' TO WS-CARD-NUMBER
SET CARD-ACTIVE TO TRUE
SET PRODUCT-GOLD TO TRUE
MOVE 10000.00 TO WS-CREDIT-LIMIT
MOVE 03200.00 TO WS-CURRENT-BALANCE
MOVE 06800.00 TO WS-AVAILABLE-CREDIT
MOVE 003 TO WS-DAILY-TXN-COUNT
MOVE 001 TO WS-HOURLY-TXN-COUNT
MOVE 'SMITH, JENNIFER L.' TO WS-CARDHOLDER-NAME
MOVE 00125.50 TO WS-TXN-AMOUNT
MOVE 'TARGET STORE #4521' TO WS-TXN-MERCHANT-NAME
MOVE '5311' TO WS-TXN-MCC
SET TXN-DOMESTIC TO TRUE
SET ENTRY-CHIP TO TRUE
MOVE 012 TO WS-TXN-FRAUD-SCORE
.
*================================================================*
* LOAD TEST TRANSACTION 2: Stolen card, cross-border *
*================================================================*
2100-LOAD-TXN-2.
MOVE '4532100098769876' TO WS-CARD-NUMBER
SET CARD-STOLEN TO TRUE
SET PRODUCT-STANDARD TO TRUE
MOVE 05000.00 TO WS-CREDIT-LIMIT
MOVE 01200.00 TO WS-CURRENT-BALANCE
MOVE 03800.00 TO WS-AVAILABLE-CREDIT
MOVE 012 TO WS-DAILY-TXN-COUNT
MOVE 006 TO WS-HOURLY-TXN-COUNT
MOVE 'JONES, MARK R.' TO WS-CARDHOLDER-NAME
MOVE 02500.00 TO WS-TXN-AMOUNT
MOVE 'ELECTRONICS SHOP' TO WS-TXN-MERCHANT-NAME
MOVE '5732' TO WS-TXN-MCC
MOVE 'ROU' TO WS-TXN-COUNTRY
SET ENTRY-ECOMMERCE TO TRUE
MOVE 085 TO WS-TXN-FRAUD-SCORE
.
*================================================================*
* LOAD TEST TRANSACTION 3: E-commerce gambling, high fraud *
*================================================================*
2100-LOAD-TXN-3.
MOVE '4532100098765555' TO WS-CARD-NUMBER
SET CARD-ACTIVE TO TRUE
SET PRODUCT-STANDARD TO TRUE
MOVE 08000.00 TO WS-CREDIT-LIMIT
MOVE 02100.00 TO WS-CURRENT-BALANCE
MOVE 05900.00 TO WS-AVAILABLE-CREDIT
MOVE 005 TO WS-DAILY-TXN-COUNT
MOVE 002 TO WS-HOURLY-TXN-COUNT
MOVE 'DAVIS, ANNA K.' TO WS-CARDHOLDER-NAME
MOVE 00500.00 TO WS-TXN-AMOUNT
MOVE 'LUCKY STAR CASINO' TO WS-TXN-MERCHANT-NAME
MOVE '7995' TO WS-TXN-MCC
SET TXN-DOMESTIC TO TRUE
SET ENTRY-ECOMMERCE TO TRUE
MOVE 072 TO WS-TXN-FRAUD-SCORE
.
*================================================================*
* LOAD TEST TRANSACTION 4: Velocity alert on restaurant *
*================================================================*
2100-LOAD-TXN-4.
MOVE '4532100098764444' TO WS-CARD-NUMBER
SET CARD-ACTIVE TO TRUE
SET PRODUCT-PLATINUM TO TRUE
MOVE 25000.00 TO WS-CREDIT-LIMIT
MOVE 08500.00 TO WS-CURRENT-BALANCE
MOVE 16500.00 TO WS-AVAILABLE-CREDIT
MOVE 022 TO WS-DAILY-TXN-COUNT
MOVE 007 TO WS-HOURLY-TXN-COUNT
MOVE 'WILSON, THOMAS P.' TO WS-CARDHOLDER-NAME
MOVE 00087.25 TO WS-TXN-AMOUNT
MOVE 'OLIVE GARDEN #312' TO WS-TXN-MERCHANT-NAME
MOVE '5812' TO WS-TXN-MCC
SET TXN-DOMESTIC TO TRUE
SET ENTRY-CONTACTLESS TO TRUE
MOVE 025 TO WS-TXN-FRAUD-SCORE
.
*================================================================*
* LOAD TEST TRANSACTION 5: Cross-border, large, medium fraud *
*================================================================*
2100-LOAD-TXN-5.
MOVE '4532100098763333' TO WS-CARD-NUMBER
SET CARD-ACTIVE TO TRUE
SET PRODUCT-BUSINESS TO TRUE
MOVE 50000.00 TO WS-CREDIT-LIMIT
MOVE 12000.00 TO WS-CURRENT-BALANCE
MOVE 38000.00 TO WS-AVAILABLE-CREDIT
MOVE 004 TO WS-DAILY-TXN-COUNT
MOVE 001 TO WS-HOURLY-TXN-COUNT
MOVE 'GARCIA, CARLOS M.' TO WS-CARDHOLDER-NAME
MOVE 07800.00 TO WS-TXN-AMOUNT
MOVE 'TECH SUPPLIES LTD' TO WS-TXN-MERCHANT-NAME
MOVE '5045' TO WS-TXN-MCC
MOVE 'GBR' TO WS-TXN-COUNTRY
SET ENTRY-CHIP TO TRUE
MOVE 048 TO WS-TXN-FRAUD-SCORE
.
*================================================================*
* 3000-AUTHORIZE-TRANSACTION: The authorization decision flow *
* Each check uses the CONTINUE-PROCESSING flag pattern. *
* When any check sets STOP-PROCESSING, subsequent checks *
* are skipped. *
*================================================================*
3000-AUTHORIZE-TRANSACTION.
IF WS-CONTINUE-PROCESSING
PERFORM 3100-CHECK-CARD-STATUS
END-IF
IF WS-CONTINUE-PROCESSING
PERFORM 3200-CHECK-AVAILABLE-CREDIT
END-IF
IF WS-CONTINUE-PROCESSING
PERFORM 3300-CHECK-VELOCITY
END-IF
IF WS-CONTINUE-PROCESSING
PERFORM 3400-CHECK-MERCHANT-CATEGORY
END-IF
IF WS-CONTINUE-PROCESSING
PERFORM 3500-CHECK-FRAUD-SCORE
END-IF
IF WS-CONTINUE-PROCESSING
PERFORM 3600-MULTI-FACTOR-ASSESSMENT
END-IF
* Final approval if all checks passed
IF WS-CONTINUE-PROCESSING
PERFORM 3700-FINAL-APPROVAL
END-IF
.
*================================================================*
* 3100-CHECK-CARD-STATUS *
* Uses EVALUATE TRUE with 88-level conditions for clean *
* multi-way branching on card status. *
*================================================================*
3100-CHECK-CARD-STATUS.
EVALUATE TRUE
WHEN CARD-ACTIVE
CONTINUE
WHEN CARD-STOLEN
SET AUTH-DECLINED-STOLEN TO TRUE
MOVE 'Card reported stolen - retain card'
TO WS-AUTH-MESSAGE
SET RISK-CRITICAL TO TRUE
SET WS-STOP-PROCESSING TO TRUE
WHEN CARD-LOST
SET AUTH-DECLINED-LOST TO TRUE
MOVE 'Card reported lost'
TO WS-AUTH-MESSAGE
SET RISK-CRITICAL TO TRUE
SET WS-STOP-PROCESSING TO TRUE
WHEN CARD-BLOCKED
SET AUTH-DECLINED-CARD TO TRUE
MOVE 'Card is blocked by issuer'
TO WS-AUTH-MESSAGE
SET RISK-HIGH TO TRUE
SET WS-STOP-PROCESSING TO TRUE
WHEN CARD-FROZEN
SET AUTH-DECLINED-FROZEN TO TRUE
MOVE 'Card is temporarily frozen'
TO WS-AUTH-MESSAGE
SET RISK-MEDIUM TO TRUE
SET WS-STOP-PROCESSING TO TRUE
WHEN CARD-EXPIRED
SET AUTH-DECLINED-CARD TO TRUE
MOVE 'Card has expired'
TO WS-AUTH-MESSAGE
SET RISK-LOW TO TRUE
SET WS-STOP-PROCESSING TO TRUE
WHEN OTHER
SET AUTH-SYSTEM-ERROR TO TRUE
MOVE 'Unknown card status'
TO WS-AUTH-MESSAGE
SET RISK-HIGH TO TRUE
SET WS-STOP-PROCESSING TO TRUE
END-EVALUATE
.
*================================================================*
* 3200-CHECK-AVAILABLE-CREDIT *
* Nested IF for credit limit check with near-limit warning. *
*================================================================*
3200-CHECK-AVAILABLE-CREDIT.
IF WS-AVAILABLE-CREDIT < WS-TXN-AMOUNT
SET AUTH-DECLINED-CREDIT TO TRUE
MOVE 'Insufficient available credit'
TO WS-AUTH-MESSAGE
SET RISK-LOW TO TRUE
SET WS-STOP-PROCESSING TO TRUE
ELSE
* Check if transaction would use more than 90%
* of remaining credit
IF WS-TXN-AMOUNT > ZERO
AND WS-AVAILABLE-CREDIT > ZERO
IF (WS-TXN-AMOUNT / WS-AVAILABLE-CREDIT)
> 0.90
SET WS-NEEDS-REVIEW TO TRUE
ADD 1 TO WS-F-FLAG-COUNT
END-IF
END-IF
END-IF
.
*================================================================*
* 3300-CHECK-VELOCITY *
* Compound conditions check both daily and hourly velocity. *
*================================================================*
3300-CHECK-VELOCITY.
* Hard decline: hourly velocity exceeded
IF WS-HOURLY-TXN-COUNT >= WS-C-MAX-HOURLY-TXN
SET AUTH-DECLINED-VELOCITY TO TRUE
MOVE 'Hourly transaction velocity exceeded'
TO WS-AUTH-MESSAGE
SET RISK-HIGH TO TRUE
SET WS-STOP-PROCESSING TO TRUE
ELSE
* Soft flag: daily velocity approaching limit
IF WS-DAILY-TXN-COUNT >= WS-C-MAX-DAILY-TXN
SET AUTH-DECLINED-VELOCITY TO TRUE
MOVE 'Daily transaction velocity exceeded'
TO WS-AUTH-MESSAGE
SET RISK-HIGH TO TRUE
SET WS-STOP-PROCESSING TO TRUE
ELSE
* Warning: high daily count with card-not-present
IF WS-DAILY-TXN-COUNT >= 15
AND ENTRY-CARD-NOT-PRESENT
SET WS-NEEDS-REVIEW TO TRUE
ADD 1 TO WS-F-FLAG-COUNT
END-IF
END-IF
END-IF
.
*================================================================*
* 3400-CHECK-MERCHANT-CATEGORY *
* EVALUATE with ALSO for two-dimensional decision: *
* card product type vs. merchant category. *
*================================================================*
3400-CHECK-MERCHANT-CATEGORY.
EVALUATE TRUE ALSO TRUE
* Standard cards: gambling and cash advance restricted
WHEN PRODUCT-STANDARD
ALSO MCC-GAMBLING
SET AUTH-DECLINED-MCC TO TRUE
MOVE 'Merchant category restricted'
TO WS-AUTH-MESSAGE
SET WS-STOP-PROCESSING TO TRUE
WHEN PRODUCT-STANDARD
ALSO MCC-CASH-ADVANCE
SET AUTH-DECLINED-MCC TO TRUE
MOVE 'Cash advance not allowed on this card'
TO WS-AUTH-MESSAGE
SET WS-STOP-PROCESSING TO TRUE
* Standard cards: crypto restricted
WHEN PRODUCT-STANDARD
ALSO MCC-CRYPTO
SET AUTH-DECLINED-MCC TO TRUE
MOVE 'Cryptocurrency purchase restricted'
TO WS-AUTH-MESSAGE
SET WS-STOP-PROCESSING TO TRUE
* Gold/Platinum: gambling flagged, not blocked
WHEN PRODUCT-PREMIUM
ALSO MCC-GAMBLING
SET WS-NEEDS-REVIEW TO TRUE
ADD 1 TO WS-F-FLAG-COUNT
* Business cards: no MCC restrictions
WHEN PRODUCT-BUSINESS
ALSO ANY
CONTINUE
* All other combinations: pass
WHEN OTHER
CONTINUE
END-EVALUATE
.
*================================================================*
* 3500-CHECK-FRAUD-SCORE *
* Multi-level fraud response based on score ranges. *
*================================================================*
3500-CHECK-FRAUD-SCORE.
EVALUATE TRUE
WHEN FRAUD-LOW-RISK
CONTINUE
WHEN FRAUD-MED-RISK
* Medium risk: flag for review but continue
SET WS-NEEDS-REVIEW TO TRUE
ADD 1 TO WS-F-FLAG-COUNT
WHEN FRAUD-HIGH-RISK
* High risk: compound condition determines outcome
* High fraud + card not present = decline
* High fraud + card present = flag and continue
IF ENTRY-CARD-NOT-PRESENT
SET AUTH-DECLINED-FRAUD TO TRUE
MOVE 'High fraud risk - CNP transaction'
TO WS-AUTH-MESSAGE
SET RISK-HIGH TO TRUE
SET WS-STOP-PROCESSING TO TRUE
ELSE
SET WS-NEEDS-REVIEW TO TRUE
ADD 1 TO WS-F-FLAG-COUNT
END-IF
WHEN FRAUD-CRITICAL
* Critical: immediate decline regardless
SET AUTH-DECLINED-FRAUD TO TRUE
MOVE 'Critical fraud risk score'
TO WS-AUTH-MESSAGE
SET RISK-CRITICAL TO TRUE
SET WS-STOP-PROCESSING TO TRUE
END-EVALUATE
.
*================================================================*
* 3600-MULTI-FACTOR-ASSESSMENT *
* The most complex check: combines geographic risk, transaction *
* amount, entry mode, and accumulated flags into a final *
* risk determination using EVALUATE TRUE ALSO TRUE. *
*================================================================*
3600-MULTI-FACTOR-ASSESSMENT.
* First dimension: geographic risk
* Second dimension: transaction amount threshold
EVALUATE TRUE ALSO TRUE
* High-risk country: always decline
WHEN TXN-HIGH-RISK-COUNTRY
ALSO ANY
SET AUTH-DECLINED-FRAUD TO TRUE
MOVE 'Transaction from high-risk country'
TO WS-AUTH-MESSAGE
SET RISK-CRITICAL TO TRUE
SET WS-STOP-PROCESSING TO TRUE
* Cross-border + very high value: call center referral
WHEN TXN-CROSS-BORDER
ALSO WS-TXN-AMOUNT > WS-C-VERY-HIGH-VALUE
SET AUTH-CALL-CENTER TO TRUE
MOVE 'Large cross-border: manual review'
TO WS-AUTH-MESSAGE
SET RISK-HIGH TO TRUE
SET WS-STOP-PROCESSING TO TRUE
* Cross-border + high value + not low fraud: flag
WHEN TXN-CROSS-BORDER
ALSO WS-TXN-AMOUNT > WS-C-HIGH-VALUE-LIMIT
IF NOT FRAUD-LOW-RISK
SET WS-NEEDS-REVIEW TO TRUE
ADD 1 TO WS-F-FLAG-COUNT
END-IF
* Cross-border + card not present + any flags: flag
WHEN TXN-CROSS-BORDER
ALSO OTHER
IF ENTRY-CARD-NOT-PRESENT
AND WS-F-FLAG-COUNT > 0
SET WS-NEEDS-REVIEW TO TRUE
ADD 1 TO WS-F-FLAG-COUNT
END-IF
* Domestic, any amount: no additional action
WHEN TXN-DOMESTIC
ALSO ANY
CONTINUE
* Allied country, any amount: no additional action
WHEN TXN-ALLIED-COUNTRY
ALSO ANY
CONTINUE
* Default: pass through
WHEN OTHER
CONTINUE
END-EVALUATE
.
*================================================================*
* 3700-FINAL-APPROVAL *
* If we reach this point, all checks passed. Determine *
* whether to approve clean or approve with review. *
*================================================================*
3700-FINAL-APPROVAL.
MOVE WS-F-FLAG-COUNT TO WS-AUTH-FLAGS-RAISED
IF WS-NEEDS-REVIEW
* Multiple flags or high-value with flags: call center
IF WS-F-FLAG-COUNT >= 3
OR (WS-TXN-AMOUNT > WS-C-HIGH-VALUE-LIMIT
AND WS-F-FLAG-COUNT >= 2)
SET AUTH-CALL-CENTER TO TRUE
MOVE 'Multiple risk factors: manual review'
TO WS-AUTH-MESSAGE
SET RISK-HIGH TO TRUE
ELSE
* Approved with post-transaction review
SET AUTH-APPROVED-REVIEW TO TRUE
MOVE 'Approved with monitoring'
TO WS-AUTH-MESSAGE
SET RISK-MEDIUM TO TRUE
END-IF
ELSE
* Clean approval
SET AUTH-APPROVED TO TRUE
MOVE 'Approved' TO WS-AUTH-MESSAGE
SET RISK-LOW TO TRUE
END-IF
.
*================================================================*
* 4000-DISPLAY-RESULT: Show the authorization decision *
*================================================================*
4000-DISPLAY-RESULT.
DISPLAY WS-C-DETAIL-SEP
DISPLAY ' Card: '
WS-CARD-NUMBER(1:4) '-****-****-'
WS-CARD-NUMBER(13:4)
DISPLAY ' Holder: ' WS-CARDHOLDER-NAME
DISPLAY ' Merchant: ' WS-TXN-MERCHANT-NAME
DISPLAY ' MCC: ' WS-TXN-MCC
' Country: ' WS-TXN-COUNTRY
' Entry: ' WS-TXN-ENTRY-MODE
MOVE WS-TXN-AMOUNT TO WS-DSP-AMOUNT
DISPLAY ' Amount: ' WS-DSP-AMOUNT
MOVE WS-TXN-FRAUD-SCORE TO WS-DSP-SCORE
DISPLAY ' Fraud Score: ' WS-DSP-SCORE
' Card Status: ' WS-CARD-STATUS
' Product: ' WS-CARD-PRODUCT
DISPLAY SPACES
EVALUATE TRUE
WHEN AUTH-APPROVED
DISPLAY ' >> RESPONSE: 00 - APPROVED'
WHEN AUTH-APPROVED-REVIEW
DISPLAY ' >> RESPONSE: 01 - APPROVED'
' (MONITORING)'
WHEN AUTH-CALL-CENTER
DISPLAY ' >> RESPONSE: 02 - REFER TO'
' CALL CENTER'
WHEN AUTH-DECLINED-CREDIT
DISPLAY ' >> RESPONSE: 51 - DECLINED'
' (INSUFFICIENT CREDIT)'
WHEN AUTH-DECLINED-CARD
DISPLAY ' >> RESPONSE: 05 - DECLINED'
' (CARD STATUS)'
WHEN AUTH-DECLINED-STOLEN
DISPLAY ' >> RESPONSE: 43 - DECLINED'
' (STOLEN CARD)'
WHEN AUTH-DECLINED-LOST
DISPLAY ' >> RESPONSE: 41 - DECLINED'
' (LOST CARD)'
WHEN AUTH-DECLINED-FROZEN
DISPLAY ' >> RESPONSE: 62 - DECLINED'
' (CARD FROZEN)'
WHEN AUTH-DECLINED-VELOCITY
DISPLAY ' >> RESPONSE: 65 - DECLINED'
' (VELOCITY)'
WHEN AUTH-DECLINED-FRAUD
DISPLAY ' >> RESPONSE: 59 - DECLINED'
' (FRAUD)'
WHEN AUTH-DECLINED-MCC
DISPLAY ' >> RESPONSE: 57 - DECLINED'
' (RESTRICTED MCC)'
WHEN AUTH-SYSTEM-ERROR
DISPLAY ' >> RESPONSE: 96 - SYSTEM ERROR'
WHEN OTHER
DISPLAY ' >> RESPONSE: UNKNOWN'
END-EVALUATE
DISPLAY ' Message: ' WS-AUTH-MESSAGE
DISPLAY ' Risk: ' WS-AUTH-RISK-LEVEL
' Flags: ' WS-F-FLAG-COUNT
DISPLAY SPACES
.
Solution Walkthrough
The Sequential Check Pattern with Continue Flag
The authorization flow uses the "continue processing" flag pattern introduced in Case Study 1 of this chapter. Each check paragraph is guarded by IF WS-CONTINUE-PROCESSING, so once any check sets WS-STOP-PROCESSING, all subsequent checks are skipped. This pattern has three benefits:
-
Performance. Once a card is identified as stolen, there is no point checking available credit, velocity, or fraud score. In a system processing 3.4 million requests per day, skipping unnecessary checks saves significant CPU time.
-
Correctness. Some checks depend on earlier checks passing. The credit check assumes the card is active. The fraud score check assumes the card has not already been declined for a prior reason. The sequential flag pattern enforces this dependency naturally.
-
Extensibility. When CFB needed to add a new check (sanctions screening), the developer added a new paragraph and a single
IF WS-CONTINUE-PROCESSING / PERFORMblock. No existing checks needed modification.
EVALUATE TRUE for Card Status: Clean Multi-Way Branching
The card status check (3100-CHECK-CARD-STATUS) demonstrates EVALUATE TRUE with 88-level conditions. Each card status maps to a specific response code and message:
CARD-STOLENproduces response code 43 (the ISO 8583 standard code for "pick up card, stolen")CARD-LOSTproduces response code 41 (the standard code for "pick up card, lost")CARD-FROZENproduces response code 62 (restricted card)
The WHEN OTHER clause catches any unexpected card status, producing a system error response. In production, this clause fires occasionally due to data migration errors or upstream system bugs. Without it, transactions with invalid card status codes would fall through without a decision -- a dangerous failure mode.
Nested IF for Credit Check with Near-Limit Warning
The credit check (3200-CHECK-AVAILABLE-CREDIT) uses nested IF to implement two levels of evaluation:
- Hard decline. If available credit is less than the transaction amount, decline immediately.
- Soft flag. If the transaction would consume more than 90% of remaining credit, flag it for review but allow it to continue.
The nested structure is natural here because the soft flag check only makes sense if the hard decline did not trigger. The division WS-TXN-AMOUNT / WS-AVAILABLE-CREDIT is protected by the outer IF (which guarantees WS-AVAILABLE-CREDIT >= WS-TXN-AMOUNT) and by the explicit check that both values are greater than zero, avoiding division by zero.
EVALUATE TRUE ALSO TRUE for Merchant Category Restrictions
The merchant category check (3400-CHECK-MERCHANT-CATEGORY) uses EVALUATE TRUE ALSO TRUE to create a two-dimensional decision matrix: card product type on one axis, merchant category on the other.
The business rules are expressed directly in the WHEN clauses: - Standard cards + gambling MCCs = decline - Standard cards + crypto = decline - Premium cards + gambling = flag (not decline) - Business cards + any MCC = no restrictions - Everything else = pass
The ANY keyword in the business card rule means "regardless of merchant category." This is cleaner than listing every possible MCC. When CFB later added a new MCC restriction (online pharmaceuticals), the developer added a single WHEN clause to the EVALUATE without modifying any existing rules.
Compound Conditions in Fraud Score Check
The fraud score check (3500-CHECK-FRAUD-SCORE) demonstrates compound conditions within an EVALUATE structure. The high-risk fraud score (61-80) does not automatically decline the transaction. Instead, it uses a compound condition to differentiate between card-present and card-not-present transactions:
IF ENTRY-CARD-NOT-PRESENT
SET AUTH-DECLINED-FRAUD TO TRUE
...
ELSE
SET WS-NEEDS-REVIEW TO TRUE
...
END-IF
The reasoning: a card-present transaction with a moderately high fraud score may simply reflect unusual spending patterns (a cardholder on vacation). A card-not-present transaction with the same score is far more likely to be actual fraud. The compound condition ENTRY-CARD-NOT-PRESENT combines with the EVALUATE branch for FRAUD-HIGH-RISK to express this two-factor rule cleanly.
The Multi-Factor Assessment: EVALUATE TRUE ALSO TRUE with Nested Conditions
The most complex check (3600-MULTI-FACTOR-ASSESSMENT) combines geographic risk with transaction amount in a two-dimensional EVALUATE, and then applies additional conditions within individual WHEN clauses:
WHEN TXN-CROSS-BORDER
ALSO WS-TXN-AMOUNT > WS-C-HIGH-VALUE-LIMIT
IF NOT FRAUD-LOW-RISK
SET WS-NEEDS-REVIEW TO TRUE
...
END-IF
This three-factor rule says: "If the transaction is cross-border, AND the amount exceeds the high-value threshold, AND the fraud score is not low-risk, then flag for review." The EVALUATE handles two dimensions; the nested IF adds a third. This approach avoids the explosion of WHEN clauses that would be needed to express all three factors purely through EVALUATE ALSO.
The Flag Accumulation Pattern
Throughout the authorization flow, the WS-F-FLAG-COUNT variable accumulates the number of risk flags raised. The final approval logic (3700-FINAL-APPROVAL) uses this accumulated count in a compound condition:
IF WS-F-FLAG-COUNT >= 3
OR (WS-TXN-AMOUNT > WS-C-HIGH-VALUE-LIMIT
AND WS-F-FLAG-COUNT >= 2)
This rule says: "If three or more flags were raised, OR if the transaction is high-value and at least two flags were raised, route to the call center for manual review." The parentheses around the AND clause are essential -- without them, the OR would bind to WS-TXN-AMOUNT > WS-C-HIGH-VALUE-LIMIT instead of to the entire AND expression, completely changing the meaning.
Lessons Learned
1. 88-Level Conditions Transform Cryptic Codes into Business Language
The authorization response codes (00, 01, 02, 05, 41, 43, 51, 57, 59, 62, 65, 96) are ISO 8583 standard codes that are meaningful to payment system professionals but opaque to everyone else. By defining condition names like AUTH-DECLINED-STOLEN and AUTH-APPROVED-REVIEW, the program reads in business language. When the compliance team reviewed the authorization logic, they could verify the rules without a code-to-meaning reference guide.
2. Composite 88-Level Conditions Reduce Error Rates
The composite conditions CARD-COMPROMISED (stolen or lost), CARD-INACTIVE (blocked, stolen, lost, frozen, expired), MCC-HIGH-RISK-MCC (all high-risk merchant categories), and ENTRY-CARD-NOT-PRESENT (manual or e-commerce) each combine multiple values under a single business concept. When a new entry mode was added (QR code payments, code 'QR'), the developer added it to ENTRY-CARD-PRESENT and every rule that tested card-present vs. card-not-present automatically included the new mode.
3. EVALUATE TRUE ALSO TRUE Replaces Massive Nested IF Structures
The merchant category check was originally implemented as a 67-line nested IF structure. After conversion to EVALUATE TRUE ALSO TRUE, it became 28 lines and was immediately understandable. More importantly, adding a new rule required adding a single WHEN clause rather than finding the correct insertion point in a nested IF chain.
4. The WHEN OTHER Clause Is Mandatory in Payment Systems
At 3.4 million transactions per day, "impossible" data conditions occur regularly -- a card status code of 'X' due to a database conversion error, a merchant category code with leading spaces due to a network translation issue, a country code that does not match any defined condition. The WHEN OTHER clause in every EVALUATE provides a safe default behavior for these cases. In a payment system, the safe default is typically to decline the transaction rather than to approve it by accident.
5. Parentheses in Compound Conditions Are Not Optional
The final approval logic contains the compound condition (WS-TXN-AMOUNT > WS-C-HIGH-VALUE-LIMIT AND WS-F-FLAG-COUNT >= 2). Without the parentheses, COBOL's operator precedence (AND before OR) would evaluate this as WS-F-FLAG-COUNT >= 3 OR WS-TXN-AMOUNT > WS-C-HIGH-VALUE-LIMIT, which has an entirely different meaning. In a system where every authorization decision has financial consequences, misplaced precedence can cost the bank millions.
Discussion Questions
-
The sequential check pattern skips all remaining checks after the first decline. Are there scenarios where continuing to evaluate subsequent checks (even after a decline) would be beneficial? How would you implement a "collect all decline reasons" approach while still maintaining the early-exit optimization?
-
The merchant category check uses EVALUATE TRUE ALSO TRUE with two dimensions. If CFB wanted to add a third dimension (time of day -- business hours vs. after hours), how would you restructure the logic? Would EVALUATE TRUE ALSO TRUE ALSO TRUE be readable, or would a different approach be better?
-
The fraud score thresholds (30, 60, 80) are stored as constants. If CFB wanted different thresholds for different card products (for example, business cards might have higher tolerance), how would you redesign the data structure and conditional logic?
-
The program uses the
WS-F-FLAG-COUNTto accumulate risk signals. What would happen if two different checks both flagged the same risk factor (for example, velocity and fraud score both detecting the same anomaly)? Is double-counting a problem, and how would you address it? -
Transaction 5 in the test data is a large cross-border purchase to the United Kingdom with a medium fraud score. Walk through the authorization flow step by step and predict the final decision. Which checks will flag the transaction, and what will the final response code be?