bash version of soapdump so a bit slow
soapdump.sh edited
179 lines 6.6 kB view raw
1#!/usr/bin/env nix-shell 2#! nix-shell -i bash -p gnugrep gnused coreutils 3 4# PayPal SOAP Log Parser - Structured Output 5# Usage: ./parse_paypal.sh [OPTIONS] <logfile> 6 7show_help() { 8 cat << EOF 9PayPal SOAP Log Parser 10 11USAGE: 12 $0 [OPTIONS] <logfile> 13 14OPTIONS: 15 -h, --help Show this help message 16 -s, --summary Show summary statistics only 17 -r, --raw Output raw structured data (default) 18 19OUTPUT FORMAT (tab-separated): 20 TRANS_NUM|AMOUNT|CURRENCY|FIRSTNAME|LASTNAME|STREET|CITY|STATE|ZIP|CCTYPE|CCLAST4|EXPMONTH|EXPYEAR|CVV|TRANSID|STATUS|CORRID|PROC_AMOUNT 21 22FIELD DESCRIPTIONS: 23 TRANS_NUM - Transaction sequence number 24 AMOUNT - Order total amount 25 CURRENCY - Currency code (USD, etc) 26 FIRSTNAME - Customer first name 27 LASTNAME - Customer last name 28 STREET - Street address 29 CITY - City name 30 STATE - State/Province code 31 ZIP - Postal code 32 CCTYPE - Credit card type (Visa, MasterCard, etc) 33 CCLAST4 - Last 4 digits of credit card 34 EXPMONTH - Card expiration month 35 EXPYEAR - Card expiration year 36 CVV - CVV code 37 TRANSID - PayPal transaction ID 38 STATUS - Transaction status (Success/Failure) 39 CORRID - Correlation ID 40 PROC_AMOUNT - Actually processed amount 41 42EXAMPLES: 43 # Get all transactions 44 $0 payments.log 45 46 # Get only successful transactions 47 $0 payments.log | grep Success 48 49 # Count transactions by state 50 $0 payments.log | cut -d'|' -f8 | sort | uniq -c | sort -nr 51 52 # Find largest transaction 53 $0 payments.log | sort -t'|' -k2 -nr | head -1 54 55 # Get transactions over \$500 56 $0 payments.log | awk -F'|' '\$2 > 500' 57 58 # Summary stats 59 $0 -s payments.log 60 61EOF 62} 63 64# Parse arguments 65SUMMARY_ONLY=false 66while [[ $# -gt 0 ]]; do 67 case $1 in 68 -h|--help) 69 show_help 70 exit 0 71 ;; 72 -s|--summary) 73 SUMMARY_ONLY=true 74 shift 75 ;; 76 -r|--raw) 77 SUMMARY_ONLY=false 78 shift 79 ;; 80 -*) 81 echo "Unknown option $1" 82 show_help 83 exit 1 84 ;; 85 *) 86 LOGFILE="$1" 87 break 88 ;; 89 esac 90done 91 92if [[ -z "$LOGFILE" ]]; then 93 echo "Error: No logfile specified" 94 show_help 95 exit 1 96fi 97 98if [[ ! -f "$LOGFILE" ]]; then 99 echo "Error: File '$LOGFILE' not found" 100 exit 1 101fi 102 103# Extract requests and responses 104REQUESTS=$(sed -nr 's/PPAPIService: Request: (.*)/\1/p' "$LOGFILE") 105RESPONSES=$(sed -nr 's/PPAPIService: Response: <\?.*\?>(.*)/\1/p' "$LOGFILE") 106 107if [[ "$SUMMARY_ONLY" == "true" ]]; then 108 echo "=== SUMMARY ===" 109 TOTAL=$(grep -c "PPAPIService: Request:" "$LOGFILE") 110 SUCCESSFUL=$(grep -c "Success" "$LOGFILE") 111 echo "Total Transactions: $TOTAL" 112 echo "Successful: $SUCCESSFUL" 113 echo "Failed: $((TOTAL - SUCCESSFUL))" 114 echo 115 echo "Top 5 States by Transaction Count:" 116 grep -oP '<ebl:StateOrProvince>\K[^<]+' "$LOGFILE" | sort | uniq -c | sort -nr | head -5 117 echo 118 echo "Transaction Amount Stats:" 119 AMOUNTS=$(grep -oP '<ebl:OrderTotal[^>]*>\K[0-9.]+' "$LOGFILE") 120 TOTAL_AMOUNT=$(echo "$AMOUNTS" | awk '{sum += $1} END {printf "%.2f", sum}') 121 LARGEST=$(echo "$AMOUNTS" | sort -nr | head -1) 122 SMALLEST=$(echo "$AMOUNTS" | sort -n | head -1) 123 echo " Total: \$${TOTAL_AMOUNT}" 124 echo " Largest: \$${LARGEST}" 125 echo " Smallest: \$${SMALLEST}" 126 exit 0 127fi 128 129# Convert responses to array for lookup 130declare -a response_array 131RESP_NUM=1 132while IFS= read -r response_xml; do 133 if [[ -n "$response_xml" ]]; then 134 TRANSID=$(echo "$response_xml" | grep -o '<TransactionID>[^<]*</TransactionID>' | sed 's/<[^>]*>//g' | tr -d '\n\r') 135 STATUS=$(echo "$response_xml" | grep -o '<Ack[^>]*>[^<]*</Ack>' | sed 's/<[^>]*>//g' | tr -d '\n\r') 136 CORRID=$(echo "$response_xml" | grep -o '<CorrelationID[^>]*>[^<]*</CorrelationID>' | sed 's/<[^>]*>//g' | tr -d '\n\r') 137 PROC_AMOUNT=$(echo "$response_xml" | grep -o '<Amount[^>]*>[^<]*</Amount>' | sed 's/<[^>]*>//g' | tr -d '\n\r') 138 139 response_array[$RESP_NUM]="$TRANSID|$STATUS|$CORRID|$PROC_AMOUNT" 140 RESP_NUM=$((RESP_NUM + 1)) 141 fi 142done <<< "$RESPONSES" 143 144# Process each request and output structured data 145TRANS_NUM=1 146while IFS= read -r request_xml; do 147 if [[ -n "$request_xml" ]]; then 148 # Extract all fields 149 AMOUNT=$(echo "$request_xml" | grep -o '<ebl:OrderTotal[^>]*>[^<]*</ebl:OrderTotal>' | sed 's/.*>\([0-9.]*\)<.*/\1/') 150 CURRENCY=$(echo "$request_xml" | grep -o 'currencyID="[^"]*"' | sed 's/currencyID="\([^"]*\)"/\1/') 151 FIRSTNAME=$(echo "$request_xml" | grep -o '<ebl:FirstName>[^<]*</ebl:FirstName>' | sed 's/<[^>]*>//g') 152 LASTNAME=$(echo "$request_xml" | grep -o '<ebl:LastName>[^<]*</ebl:LastName>' | sed 's/<[^>]*>//g') 153 STREET=$(echo "$request_xml" | grep -o '<ebl:Street1>[^<]*</ebl:Street1>' | sed 's/<[^>]*>//g') 154 CITY=$(echo "$request_xml" | grep -o '<ebl:CityName>[^<]*</ebl:CityName>' | sed 's/<[^>]*>//g') 155 STATE=$(echo "$request_xml" | grep -o '<ebl:StateOrProvince>[^<]*</ebl:StateOrProvince>' | sed 's/<[^>]*>//g') 156 ZIP=$(echo "$request_xml" | grep -o '<ebl:PostalCode>[^<]*</ebl:PostalCode>' | sed 's/<[^>]*>//g') 157 CCTYPE=$(echo "$request_xml" | grep -o '<ebl:CreditCardType>[^<]*</ebl:CreditCardType>' | sed 's/<[^>]*>//g') 158 CCLAST4=$(echo "$request_xml" | grep -o '<ebl:CreditCardLastFourDigits>[^<]*</ebl:CreditCardLastFourDigits>' | sed 's/<[^>]*>//g') 159 EXPMONTH=$(echo "$request_xml" | grep -o '<ebl:ExpMonth>[^<]*</ebl:ExpMonth>' | sed 's/<[^>]*>//g') 160 EXPYEAR=$(echo "$request_xml" | grep -o '<ebl:ExpYear>[^<]*</ebl:ExpYear>' | sed 's/<[^>]*>//g') 161 CVV=$(echo "$request_xml" | grep -o '<ebl:CVV2>[^<]*</ebl:CVV2>' | sed 's/<[^>]*>//g') 162 163 # Get corresponding response data 164 RESPONSE_DATA="${response_array[$TRANS_NUM]}" 165 if [[ -n "$RESPONSE_DATA" ]]; then 166 IFS='|' read -r TRANSID STATUS CORRID PROC_AMOUNT <<< "$RESPONSE_DATA" 167 else 168 TRANSID="" 169 STATUS="" 170 CORRID="" 171 PROC_AMOUNT="" 172 fi 173 174 # Output structured line (pipe-separated for easy parsing) 175 echo "$TRANS_NUM|${AMOUNT}|${CURRENCY}|${FIRSTNAME}|${LASTNAME}|${STREET}|${CITY}|${STATE}|${ZIP}|${CCTYPE}|${CCLAST4}|${EXPMONTH}|${EXPYEAR}|${CVV}|${TRANSID}|${STATUS}|${CORRID}|${PROC_AMOUNT}" 176 177 TRANS_NUM=$((TRANS_NUM + 1)) 178 fi 179done <<< "$REQUESTS"