diff --git a/functional_tests/README.md b/functional_tests/README.md index 1c972b2..feab059 100644 --- a/functional_tests/README.md +++ b/functional_tests/README.md @@ -65,3 +65,20 @@ --- +**Execution Date:** 12/16/2025, 8:53:29 PM + +**Test Unique Identifier:** "hapao" + +**Input(s):** + 1. MS restore-details-gw.docx + Path: /Users/iamdm/Downloads/MS restore-details-gw.docx + +**Test Output Folder:** + 1. [hapao.json](hapao/hapao.json) + 2. [hapao.feature](hapao/hapao.feature) + 3. [hapao.csv](hapao/hapao.csv) + 4. [hapao.xlsx](hapao/hapao.xlsx) + 5. [hapao.yaml](hapao/hapao.yaml) + +--- + diff --git a/functional_tests/hapao/.roost/roost_metadata.json b/functional_tests/hapao/.roost/roost_metadata.json new file mode 100644 index 0000000..53111fa --- /dev/null +++ b/functional_tests/hapao/.roost/roost_metadata.json @@ -0,0 +1,19 @@ +{ + "project": { + "name": "hapao", + "created_at": "2025-12-16T15:23:29.499Z", + "updated_at": "2025-12-16T15:23:29.500Z" + }, + "files": { + "input_files": [ + { + "fileName": "MS restore-details-gw.docx", + "fileURI": "/var/tmp/Roost/RoostGPT/hapo-functional-test/1765898171/functional_tests/hapao/MS restore-details-gw.docx", + "fileSha": "929ed574ee" + } + ] + }, + "api_files": { + "input_files": [] + } +} \ No newline at end of file diff --git a/functional_tests/hapao/hapao.csv b/functional_tests/hapao/hapao.csv new file mode 100644 index 0000000..13b0a74 --- /dev/null +++ b/functional_tests/hapao/hapao.csv @@ -0,0 +1,31 @@ +הקמת בקשה OTP – כאל (SMS/IVR) – ניתוב, מיפוי שדות ובדיקת זמן תגובה +הקמת בקשה OTP – ישראכרט (SMS/IVR) – שני שלבים (token ואז send) כולל מיפוי CYYMMDD ו-alpha2CountryCode +ניתוב ל-MAX – הקמת OTP ובדיקת החזרת תשובה/שגיאה +ולידציות קלט generateOtp – שדות חסרים/לא תקינים (Id=7) +שגיאת המרה בקלט (Mismatch Conversion Id=19) – partySerialId בכותרת אינו מספרי +שגיאות/טיימאאוט – ישראכרט (token/send) ומיפוי לתשובת השירות +שגיאות/טיימאאוט – כאל sendOTP ומיפוי לתשובת השירות +מיפוי מספר טלפון – ישראכרט (masked) מול כאל (plain) +alpha2CountryCode – מיפוי IL מ-countryId=212 ונשלח לבקשת token +חסר alpha2CountryCode אצל ישראכרט – שגיאת ולידציה (Id=7) +requestTimeStamp – פורמט ותזמון Asia/Jerusalem בבקשת token +המרת תאריך לידה ל-CYYMMDD – לפני/אחרי שנת 2000 +קבועים bankCode ו-companyCode בבקשת token לישראכרט +אימות OTP – כאל: הצלחה (Authenticate ואז GetEncryptedKey) +אימות OTP – ישראכרט: הצלחה (validate – tek ו-authorizationToken) +ולידציות קלט verify-otp – חסרים/לא תקינים (Id=7) ושימור אפסים מובילים +טיימאאוט כאל – Authenticate (Id=8) +שגיאות validate – ישראכרט ומיפוי לתשובת השירות +השבת orderId בתשובות – generateOtp ו-verify-otp +אימות הרשאה – רמה 2 (CA) חסרה/פגה – החזרת 401 (Id=5) +ביצועים – זמן תגובה generateOtp תחת עומס (SLA) +ביצועים – זמן תגובה otpByToken תחת עומס (SLA) +אבטחה – תמיכת TLS1.2+ בלבד בתקשורת נכנסת/יוצאת +פרטיות – אי-לוגינג של OTP/Token/Master Key +נגישות ותמיכה תרבותית – תוכן SMS/IVR בעברית ו-RTL +איתור וניטור – קורלציה מלאה לפי orderId לאורך השרשרת +Rate Limiting/Brute Force – ניסיונות OTP מוגבלים במסלול ישראכרט +סקיילביליות – עומס מקבילי גבוה על /otp ו-/verify-otp +התאוששות מתקלות – טיימאאוט/404 והחזרת מסרים ידידותיים +לוקליזציה – פורמטי תאריך/זמן ואזור זמן Asia/Jerusalem +ציות לרגולציה – בנק ישראל והגנת הפרטיות \ No newline at end of file diff --git a/functional_tests/hapao/hapao.feature b/functional_tests/hapao/hapao.feature new file mode 100644 index 0000000..1feafa3 --- /dev/null +++ b/functional_tests/hapao/hapao.feature @@ -0,0 +1,563 @@ +Feature: ניהול בקשה לאחזור פרטי כרטיס – generateOtp ו-otpByToken (MS: restore-details-gw) + + # API Tests + Background: + Given כתובת הבסיס של ה-API מוגדרת במשתנה סביבה 'BASE_URL' + And כתובת הבסיס למתפעלת כאל מוגדרת במשתנה סביבה 'CAL_BASE_URL' כ-'https://tst-api.cal-online.co.il/PartnerAuthentication.Api' + And כתובת הבסיס למתפעלת ישראכרט מוגדרת במשתנה סביבה 'ISRC_BASE_URL' כ-'https://preprod.api.isracard.co.il/isracard/preprod' + And כותרת Authorization לרמת הרשאה CA מוגדרת עם ערך תקין + And מוגדרות הכותרות הבאות לשירות: + | header | value | + | Content-Type | application/json | + | variousChannelTypeCode | 10001 | + | bankNumber | 012 | + | branchNumber | 123 | + | accountNumber | 1234567 | + | partySerialId | 12345678901 | + | partyShortId | 012345678 | + | partyIdTypeCode | 1 | + | countryId | 212 | + + @api @cal @otp + Scenario Outline: הקמת בקשה OTP – כאל (SMS/IVR) – ניתוב, מיפוי שדות ובדיקת זמן תגובה + Given השירות זמין וההרשאות בתוקף + When אני שולח בקשת POST אל '/card-operator/restore-details-gw/otp' עם גוף: + """ + { + "activityTypeCode": 101, + "cardIssuingSpCode": 3, + "creditCardSerialId": "abcdef_1234_abcd_5678_90ab_cdef_1234", + "cardIdServiceProvider": "1234567890123456789", + "smsByVoice": , + "orderId": "a3e9f7d2-4b5c-11ee-be56-0242ac120002" + } + """ + And המערכת מפעילה קריאה חיצונית POST אל "{CAL_BASE_URL}/api/SendOtp/sendOTP" עם כותרת 'x-access-token' תקינה וגוף: + """ + { + "CustomerDetails": { + "idNumber": "012345678", + "CustomerIdType": 1 + }, + "cardInfo": { + "cardId": "1234567890123456789" + }, + "message": { + "smsTemplate": 0, + "smsSender": "", + "smsByVoice": + } + } + """ + Then תגובת המתפעלת מתקבלת בתוך פחות מ-5000ms + And התקבל קוד סטטוס HTTP 200 מהמתפעלת עם StatusCode=1 + And תגובת השירות היא HTTP 200 וללא errors + And הגוף כולל את השדות otpToken ו-phoneNumber + And orderId בתשובה זהה לערך שנשלח בגוף הבקשה + + Examples: + | smsByVoice | + | 0 | + | 1 | + + @api @isracard @otp + Scenario Outline: הקמת בקשה OTP – ישראכרט (SMS/IVR) – שני שלבים (token ואז send) כולל מיפוי CYYMMDD ו-alpha2CountryCode + Given השירות זמין וההרשאות בתוקף + When אני שולח בקשת POST אל '/card-operator/restore-details-gw/otp' עם גוף: + """ + { + "activityTypeCode": 101, + "cardIssuingSpCode": 1, + "creditCardSerialId": "abcdef_1234_abcd_5678_90ab_cdef_1234", + "cardSuffix": "1234", + "birthDate": "15/04/1998", + "smsByVoice": , + "orderId": "a3e9f7d2-4b5c-11ee-be56-0242ac120002", + "alpha2CountryCode": "IL" + } + """ + And המערכת מפעילה קריאה חיצונית POST אל "{ISRC_BASE_URL}/authorization/token/v1.2.0/byIdAndDateOfBirth" עם גוף המכיל: + """ + { + "tokenPostRequest": { + "requestId": "a3e9f7d2-4b5c-11ee-be56-0242ac120002", + "requestTimeStamp": "", + "idNumber": "012345678", + "idCode": 1, + "cardLastFourDigits": "1234", + "companyCode": "B", + "dateOfBirth": "0980415", + "activityType": 101, + "alpha2CountryCode": "IL", + "bankCode": "012" + } + } + """ + And מתקבל token תקין מהשלב הראשון + And המערכת מפעילה קריאה חיצונית POST אל "{ISRC_BASE_URL}/authorization/otpByToken/v1.3.0/send" עם גוף: + """ + { + "requestGeneralHeader": { + "requestId": "a3e9f7d2-4b5c-11ee-be56-0242ac120002" + }, + "tokenRequest": { + "authorizationToken": "" + }, + "deliveryMethod": + } + """ + Then התקבל קוד סטטוס HTTP 200 מהשלב השני + And תגובת השירות היא HTTP 200 וללא errors + And הגוף כולל את השדות otpToken ו-phoneNumber (maskedCellphoneNumber) + And orderId בתשובה זהה לערך שנשלח בגוף הבקשה + + Examples: + | smsByVoice | deliveryMethod | + | 0 | 0 | + | 1 | 1 | + + @api @max @otp + Scenario Outline: ניתוב ל-MAX – הקמת OTP ובדיקת החזרת תשובה/שגיאה + Given השירות זמין וההרשאות בתוקף + When אני שולח בקשת POST אל '/card-operator/restore-details-gw/otp' עם גוף: + """ + { + "activityTypeCode": 101, + "cardIssuingSpCode": 2, + "creditCardSerialId": "abcdef_1234_abcd_5678_90ab_cdef_1234", + "cardIdServiceProvider": "1234567890123456789", + "smsByVoice": 0, + "orderId": "a3e9f7d2-4b5c-11ee-be56-0242ac120002" + } + """ + And אני מאמת שהמערכת ניתבה לפעילות מול מתפעלת MAX והפעילה את נקודת הקצה של MAX + Then תגובת השירות היא HTTP ובה הגוף משקף את תשובת MAX (שדות otpToken/phoneNumber במקרה הצלחה או גוף שגיאה במקרה כישלון) + + Examples: + | expectedHttp | + | 200 | + | 400 | + + @api @validation @otp + Scenario Outline: ולידציות קלט generateOtp – שדות חסרים/לא תקינים (Id=7) + Given השירות זמין וההרשאות בתוקף + When אני שולח בקשת POST אל '/card-operator/restore-details-gw/otp' עם גוף: + """ + { + "activityTypeCode": , + "cardIssuingSpCode": , + "creditCardSerialId": "", + "cardIdServiceProvider": "", + "cardSuffix": "", + "birthDate": "", + "smsByVoice": , + "orderId": "", + "alpha2CountryCode": "" + } + """ + And אם הערך '' שונה מ-'none' אני מסיר את השדה '' מהגוף לפני השליחה + Then תגובת השירות היא HTTP 400 + And השדה errors כולל id=7 עם הודעה מתאימה + + Examples: + | missingField | activityTypeCode | cardIssuingSpCode | creditCardSerialId | cardIdServiceProvider | cardSuffix | birthDate | smsByVoice | orderId | alpha2CountryCode | + | cardIssuingSpCode | 101 | 3 | abcdef_1234_abcd_5678_90ab_cdef_1234 | 1234567890123456789 | | | 0 | a3e9f7d2-4b5c-11ee-be56-0242ac120002 | | + | none | 101 | 4 | abcdef_1234_abcd_5678_90ab_cdef_1234 | 1234567890123456789 | | | 0 | a3e9f7d2-4b5c-11ee-be56-0242ac120002 | | + | none | "10A" | 3 | abcdef_1234_abcd_5678_90ab_cdef_1234 | 1234567890123456789 | | | 0 | a3e9f7d2-4b5c-11ee-be56-0242ac120002 | | + | none | 101 | 3 | xyz123_@@@@_abcd_5678_90ab_cdef_1234 | 1234567890123456789 | | | 0 | a3e9f7d2-4b5c-11ee-be56-0242ac120002 | | + | none | 101 | 1 | abcdef_1234_abcd_5678_90ab_cdef_1234 | | 12AB | 15/04/1998 | 0 | a3e9f7d2-4b5c-11ee-be56-0242ac120002 | IL | + | none | 101 | 1 | abcdef_1234_abcd_5678_90ab_cdef_1234 | | 12345 | 15/04/1998 | 0 | a3e9f7d2-4b5c-11ee-be56-0242ac120002 | IL | + | none | 101 | 3 | abcdef_1234_abcd_5678_90ab_cdef_1234 | 12345678901234567A | | | 0 | a3e9f7d2-4b5c-11ee-be56-0242ac120002 | | + | none | 101 | 1 | abcdef_1234_abcd_5678_90ab_cdef_1234 | | 1234 | 1998-04-15 | 0 | a3e9f7d2-4b5c-11ee-be56-0242ac120002 | IL | + | none | 101 | 3 | abcdef_1234_abcd_5678_90ab_cdef_1234 | 1234567890123456789 | | | 2 | a3e9f7d2-4b5c-11ee-be56-0242ac120002 | | + | none | 101 | 3 | abcdef_1234_abcd_5678_90ab_cdef_1234 | 1234567890123456789 | | | 0 | a3e9f7d24b5c11eebe560242ac120002 | | + + @api @validation @otp + Scenario: שגיאת המרה בקלט (Mismatch Conversion Id=19) – partySerialId בכותרת אינו מספרי + Given השירות זמין וההרשאות בתוקף + And ערך הכותרת 'partySerialId' מוגדר ל-"ABCDEF" במקום מספר + When אני שולח בקשת POST אל '/card-operator/restore-details-gw/otp' עם גוף תקין מינימלי למתפעלת כאל + """ + { + "activityTypeCode": 101, + "cardIssuingSpCode": 3, + "creditCardSerialId": "abcdef_1234_abcd_5678_90ab_cdef_1234", + "cardIdServiceProvider": "1234567890123456789", + "smsByVoice": 0, + "orderId": "a3e9f7d2-4b5c-11ee-be56-0242ac120002" + } + """ + Then תגובת השירות היא HTTP 400 + And השדה errors כולל id=19 והודעה "Cannot assign field [partySerialId] due to a mismatch conversion" + + @api @isracard @errors @otp + Scenario Outline: שגיאות/טיימאאוט – ישראכרט (token/send) ומיפוי לתשובת השירות + Given השירות זמין וההרשאות בתוקף + And מוגדרת הדמיה לשלב '' של ישראכרט להחזיר '' עם קוד שגיאה '' + When אני שולח בקשת POST אל '/card-operator/restore-details-gw/otp' עם גוף תקין לישראכרט + """ + { + "activityTypeCode": 101, + "cardIssuingSpCode": 1, + "creditCardSerialId": "abcdef_1234_abcd_5678_90ab_cdef_1234", + "cardSuffix": "1234", + "birthDate": "15/04/1998", + "smsByVoice": 0, + "orderId": "a3e9f7d2-4b5c-11ee-be56-0242ac120002", + "alpha2CountryCode": "IL" + } + """ + Then תגובת השירות היא HTTP + And אם גדול מ-0 אז גוף התשובה כולל StatusCode= + And אם גדול מ-0 אז errors.id= + + Examples: + | stage | providerStatus | providerErrorCode | expectedHttp | expectedStatusCode | expectedErrorId | + | token | TIMEOUT | | 408 | 0 | 8 | + | token | 423 | | 409 | 3 | 0 | + | send | 404 | undefined_parameter | 409 | 4 | 0 | + | send | 500 | | 500 | 0 | 6 | + + @api @cal @errors @otp + Scenario Outline: שגיאות/טיימאאוט – כאל sendOTP ומיפוי לתשובת השירות + Given השירות זמין וההרשאות בתוקף + And מוגדרת הדמיה ל-sendOTP של כאל להחזיר '' + When אני שולח בקשת POST אל '/card-operator/restore-details-gw/otp' עם גוף תקין למתפעלת כאל + """ + { + "activityTypeCode": 101, + "cardIssuingSpCode": 3, + "creditCardSerialId": "abcdef_1234_abcd_5678_90ab_cdef_1234", + "cardIdServiceProvider": "1234567890123456789", + "smsByVoice": 0, + "orderId": "a3e9f7d2-4b5c-11ee-be56-0242ac120002" + } + """ + Then תגובת השירות היא HTTP + And אם גדול מ-0 אז errors.id= + + Examples: + | providerStatus | expectedHttp | expectedErrorId | + | TIMEOUT | 408 | 8 | + | 401 | 401 | 0 | + | 500 | 500 | 6 | + + @api @mapping @otp + Scenario: מיפוי מספר טלפון – ישראכרט (masked) מול כאל (plain) + Given השירות זמין וההרשאות בתוקף + When אני יוצר OTP במסלול ישראכרט ומקבל phoneNumber מהשירות + And אני יוצר OTP במסלול כאל ומקבל phoneNumber מהשירות + Then במסלול ישראכרט מספר הטלפון הוא מחרוזת באורך 10 המייצגת maskedCellphoneNumber + And במסלול כאל מספר הטלפון גלוי כפי שהתקבל מהמתפעלת + + @api @isracard @mapping + Scenario: alpha2CountryCode – מיפוי IL מ-countryId=212 ונשלח לבקשת token + Given השירות זמין וההרשאות בתוקף + When אני שולח בקשת POST אל '/card-operator/restore-details-gw/otp' עם גוף תקין לישראכרט + """ + { + "activityTypeCode": 101, + "cardIssuingSpCode": 1, + "creditCardSerialId": "abcdef_1234_abcd_5678_90ab_cdef_1234", + "cardSuffix": "1234", + "birthDate": "15/04/1998", + "smsByVoice": 0, + "orderId": "a3e9f7d2-4b5c-11ee-be56-0242ac120002", + "alpha2CountryCode": "IL" + } + """ + Then בבקשת token לישראכרט נשלח alpha2CountryCode="IL" + And תגובת השירות היא HTTP 200 + + @api @isracard @validation + Scenario: חסר alpha2CountryCode אצל ישראכרט – שגיאת ולידציה (Id=7) + Given השירות זמין וההרשאות בתוקף + When אני שולח בקשת POST אל '/card-operator/restore-details-gw/otp' עם גוף ללא alpha2CountryCode + """ + { + "activityTypeCode": 101, + "cardIssuingSpCode": 1, + "creditCardSerialId": "abcdef_1234_abcd_5678_90ab_cdef_1234", + "cardSuffix": "1234", + "birthDate": "15/04/1998", + "smsByVoice": 0, + "orderId": "a3e9f7d2-4b5c-11ee-be56-0242ac120002" + } + """ + Then תגובת השירות היא HTTP 400 + And errors.id=7 עם הודעה על שדה חסר alpha2CountryCode + + @api @isracard @timestamp + Scenario: requestTimeStamp – פורמט ותזמון Asia/Jerusalem בבקשת token + Given השירות זמין וההרשאות בתוקף + When אני מפעיל מסלול ישראכרט ומנטר את גוף בקשת token + Then השדה requestTimeStamp נמצא בפורמט yyyy-MM-dd-HH.mm.ss.SSSSSS + And השעה שנשלחה היא באזור זמן Asia/Jerusalem (כולל התאמה לשעון קיץ) + + @api @isracard @conversion + Scenario Outline: המרת תאריך לידה ל-CYYMMDD – לפני/אחרי שנת 2000 + Given השירות זמין וההרשאות בתוקף + When אני שולח בקשת POST אל '/card-operator/restore-details-gw/otp' עם birthDate="" במסלול ישראכרט + """ + { + "activityTypeCode": 101, + "cardIssuingSpCode": 1, + "creditCardSerialId": "abcdef_1234_abcd_5678_90ab_cdef_1234", + "cardSuffix": "1234", + "birthDate": "", + "smsByVoice": 0, + "orderId": "a3e9f7d2-4b5c-11ee-be56-0242ac120002", + "alpha2CountryCode": "IL" + } + """ + Then בבקשת token השדה dateOfBirth נשלח כ-"" + + Examples: + | birthDate | expectedCYYMMDD | + | 15/04/1998 | 0980415 | + | 02/01/2001 | 1010102 | + + @api @isracard @constants + Scenario: קבועים bankCode ו-companyCode בבקשת token לישראכרט + Given השירות זמין וההרשאות בתוקף + When אני מפעיל בקשת token במסלול ישראכרט + Then בבקשה נשלחים bankCode="012" ו-companyCode="B" + + @api @cal @verify + Scenario: אימות OTP – כאל: הצלחה (Authenticate ואז GetEncryptedKey) + Given השירות זמין וההרשאות בתוקף ויש otpToken תקף + When אני שולח בקשת POST אל '/card-operator/restore-details-gw/verify-otp' עם גוף: + """ + { + "activityTypeCode": 101, + "cardIssuingSpCode": 3, + "otpPassword": "123456", + "otpToken": "OTP123TOKEN", + "orderId": "a3e9f7d2-4b5c-11ee-be56-0242ac120002" + } + """ + And המערכת מפעילה POST אל "{CAL_BASE_URL}/api/Authenticate/authenticate" עם token=otpToken ו-password=otpPassword ומקבלת jwt + And המערכת מפעילה POST אל "{CAL_BASE_URL}/api/GetEncryptedKey/getEncryptedKey" עם authorization=jwt ומקבלת encryptionKey + Then תגובת השירות היא HTTP 200 וללא errors + And הגוף כולל ott= ו-encryptionKey= + And orderId בתשובה זהה לקלט + + @api @isracard @verify + Scenario: אימות OTP – ישראכרט: הצלחה (validate – tek ו-authorizationToken) + Given השירות זמין וההרשאות בתוקף ויש otpToken תקף + When אני שולח בקשת POST אל '/card-operator/restore-details-gw/verify-otp' עם גוף: + """ + { + "activityTypeCode": 101, + "cardIssuingSpCode": 1, + "otpPassword": "123456", + "otpToken": "OTP123TOKEN", + "orderId": "a3e9f7d2-4b5c-11ee-be56-0242ac120002" + } + """ + And המערכת מפעילה POST אל "{ISRC_BASE_URL}/authorization/otpByToken/v1.4.0/validate" עם הנתונים ומקבלת tek ו-authorizationToken + Then תגובת השירות היא HTTP 200 וללא errors + And הגוף כולל ott= ו-encryptionKey= + And orderId בתשובה זהה לקלט + + @api @validation @verify + Scenario Outline: ולידציות קלט verify-otp – חסרים/לא תקינים (Id=7) ושימור אפסים מובילים + Given השירות זמין וההרשאות בתוקף + When אני שולח בקשת POST אל '/card-operator/restore-details-gw/verify-otp' עם גוף: + """ + { + "activityTypeCode": 101, + "cardIssuingSpCode": 3, + "otpPassword": "", + "otpToken": "OTP123TOKEN", + "orderId": "" + } + """ + And אם הערך '' שונה מ-'none' אני מסיר את השדה '' מהגוף לפני השליחה + Then תגובת השירות היא HTTP + And אם = 400 אז errors.id=7 + And אם "" = "000123" אז אני מאמת שהערך נשלח כ-"000123" למתפעלת ללא איבוד אפסים מובילים + + Examples: + | missingField | otpPassword | orderId | expectedHttp | + | otpPassword | | a3e9f7d2-4b5c-11ee-be56-0242ac120002 | 400 | + | none | 12A45 | a3e9f7d2-4b5c-11ee-be56-0242ac120002 | 400 | + | none | 000123 | a3e9f7d2-4b5c-11ee-be56-0242ac120002 | 200 | + | none | 123456 | INVALID-UUID | 400 | + + @api @cal @timeout @verify + Scenario: טיימאאוט כאל – Authenticate (Id=8) + Given השירות זמין וההרשאות בתוקף + And מוגדרת הדמיה ל-Authenticate של כאל להחזיר TIMEOUT + When אני שולח בקשת POST אל '/card-operator/restore-details-gw/verify-otp' עם גוף תקין למסלול כאל + """ + { + "activityTypeCode": 101, + "cardIssuingSpCode": 3, + "otpPassword": "123456", + "otpToken": "OTP123TOKEN", + "orderId": "a3e9f7d2-4b5c-11ee-be56-0242ac120002" + } + """ + Then תגובת השירות היא HTTP 408 + And errors.id=8 + + @api @isracard @errors @verify + Scenario Outline: שגיאות validate – ישראכרט ומיפוי לתשובת השירות + Given השירות זמין וההרשאות בתוקף + And מוגדרת הדמיה ל-validate של ישראכרט להחזיר '' עם responseCode='' + When אני שולח בקשת POST אל '/card-operator/restore-details-gw/verify-otp' עם גוף תקין למסלול ישראכרט + """ + { + "activityTypeCode": 101, + "cardIssuingSpCode": 1, + "otpPassword": "123456", + "otpToken": "OTP123TOKEN", + "orderId": "a3e9f7d2-4b5c-11ee-be56-0242ac120002" + } + """ + Then תגובת השירות היא HTTP + And אם גדול מ-0 אז גוף התשובה כולל StatusCode= + And אם גדול מ-0 אז errors.id= + + Examples: + | providerStatus | responseCode | expectedHttp | expectedStatusCode | expectedErrorId | + | 200 | invalid_otp_attempt | 409 | 7 | 0 | + | 423 | | 409 | 8 | 0 | + | 401 | | 403 | 33 | 0 | + | 500 | | 500 | 0 | 6 | + + @api @echo + Scenario Outline: השבת orderId בתשובות – generateOtp ו-verify-otp + Given השירות זמין וההרשאות בתוקף + When אני שולח בקשת POST אל '' עם גוף המכיל orderId="" + """ + { + "activityTypeCode": 101, + "cardIssuingSpCode": , + "creditCardSerialId": "abcdef_1234_abcd_5678_90ab_cdef_1234", + "cardIdServiceProvider": "1234567890123456789", + "cardSuffix": "1234", + "birthDate": "15/04/1998", + "otpPassword": "123456", + "otpToken": "OTP123TOKEN", + "smsByVoice": 0, + "orderId": "", + "alpha2CountryCode": "IL" + } + """ + Then בתשובת השירות orderId זהה ל-"" + + Examples: + | endpoint | spCode | orderId | + | /card-operator/restore-details-gw/otp | 3 | a3e9f7d2-4b5c-11ee-be56-0242ac120002 | + | /card-operator/restore-details-gw/verify-otp | 1 | a3e9f7d2-4b5c-11ee-be56-0242ac120002 | + + @api @auth + Scenario Outline: אימות הרשאה – רמה 2 (CA) חסרה/פגה – החזרת 401 (Id=5) + Given אני מסיר או מבטל את כותרת ההרשאה CA + When אני שולח בקשת POST אל '' עם גוף תקין + """ + { + "activityTypeCode": 101, + "cardIssuingSpCode": 3, + "creditCardSerialId": "abcdef_1234_abcd_5678_90ab_cdef_1234", + "cardIdServiceProvider": "1234567890123456789", + "smsByVoice": 0, + "otpPassword": "123456", + "otpToken": "OTP123TOKEN", + "orderId": "a3e9f7d2-4b5c-11ee-be56-0242ac120002" + } + """ + Then תגובת השירות היא HTTP 401 + And errors.id=5 + + Examples: + | endpoint | + | /card-operator/restore-details-gw/otp | + | /card-operator/restore-details-gw/verify-otp | + + # Non-Functional Tests + @performance @otp + Scenario Outline: ביצועים – זמן תגובה generateOtp תחת עומס (SLA) + Given סביבת בדיקות יציבה וכלי עומס זמינים + When אני מריץ עומס של בקשות לשנייה למשך אל '/card-operator/restore-details-gw/otp' עם נתונים תקינים (חלוקה בין כאל/ישראכרט) + Then ממוצע זמן תגובה < ms ו-p95 < ms + And שיעור שגיאות < % + + Examples: + | rps | duration | split | avgMs | p95Ms | errorRate | + | 500 | 60s | 50/50 | 1500 | 2500 | 1 | + + @performance @verify + Scenario Outline: ביצועים – זמן תגובה otpByToken תחת עומס (SLA) + Given הוכנו מראש otpToken תקפים + When אני מריץ עומס של בקשות לשנייה למשך אל '/card-operator/restore-details-gw/verify-otp' עם נתונים תקינים למסלולי כאל/ישראכרט + Then ממוצע זמן תגובה < ms ו-p95 < ms + And שיעור שגיאות נמוך מ-% + + Examples: + | tokens | rps | duration | avgMs | p95Ms | errorRate | + | 300 | 300 | 60s | 1500 | 2500 | 1 | + + @security @tls + Scenario: אבטחה – תמיכת TLS1.2+ בלבד בתקשורת נכנסת/יוצאת + Given יש לי גישה לסריקת פרוטוקולי TLS עבור השירות והאינטגרציות + When אני מנסה להתחבר עם TLS1.0 ו-TLS1.1 + Then החיבור נכשל עבור TLS1.0/1.1 + And הנתמכים הם TLS1.2 ומעלה בלבד + + @privacy @logging + Scenario: פרטיות – אי-לוגינג של OTP/Token/Master Key + Given הופעלו תרחישי TC-001, TC-029, TC-030 ליצירת לוגים + When אני סורק את יומני המערכת וה-APM + Then אין מופעים של otpPassword, otpToken, encryptionKey או 16 ספרות מלאות של כרטיס + And נרשמים רק מזהים לא רגישים (orderId, StatusCode) + + @l10n @content + Scenario: נגישות ותמיכה תרבותית – תוכן SMS/IVR בעברית ו-RTL + Given הופקו מסרים בערוצי SMS/IVR בעקבות יצירת OTP במסלולים השונים + When אני בוחן את נוסח ההודעות כפי שנשלחו ללקוח + Then ההודעות בעברית תקינה, מיושרות RTL וברורות + And ספרות ה-OTP מוצגות באופן קריא (לדוגמה "הקוד שלך: 123456") + + @observability + Scenario: איתור וניטור – קורלציה מלאה לפי orderId לאורך השרשרת + Given הופעלו תרחישי OTP והפעלת אימות (למשל TC-003 ו-TC-030) + When אני בוחן לוגים, מטריקות ו-Traceים במערכות הניטור + Then קיים קשר קורלציה בין כל הקריאות לפי orderId (כולל TraceId/SpanId) + + @ratelimit + Scenario: Rate Limiting/Brute Force – ניסיונות OTP מוגבלים במסלול ישראכרט + Given זמינות להדמיית מספר ניסיונות גבוה לאימות OTP + When אני שולח רצף ניסיונות אימות כושלים ל-'/card-operator/restore-details-gw/verify-otp' עם cardIssuingSpCode=1 עד לקבלת 423 מהמתפעלת + Then תגובת השירות ממופה ל-HTTP 409 עם StatusCode=8 + And אין דליפת מידע רגיש בגוף התשובה + + @scalability + Scenario: סקיילביליות – עומס מקבילי גבוה על /otp ו-/verify-otp + Given תשתית עומס תומכת ב-1000 חיבורים מקביליים + When אני מריץ 1000 חיבורים מקביליים אל נקודות הקצה '/otp' ו-'/verify-otp' + Then המערכת יציבה, שיעור השגיאות נמוך ואין קריסה או דליפות זיכרון + + @resilience + Scenario: התאוששות מתקלות – טיימאאוט/404 והחזרת מסרים ידידותיים + Given מוגדרת הדמיית 408 במסלול כאל ו-404 במסלול ישראכרט + When אני מפעיל את המסלולים וגורם לשגיאות אלו + Then עבור 408 מוחזר errors.id=8 והודעה "The service is temporarily unavailable" + And עבור 404 מוחזר errors.id=20 והודעה "The server was not able to retrieve the requested page" + And אין חשיפת פרטים אישיים במסרים + + @l10n + Scenario: לוקליזציה – פורמטי תאריך/זמן ואזור זמן Asia/Jerusalem + Given הופעלו תרחישים המייצרים לוגים עם שדות תאריך + When אני בוחן תאריכים למשתמשים ולקריאות למתפעלת + Then למשתמשים פורמט dd/MM/yyyy + And ל-API החיצוניים נשלחים הפורמטים הנדרשים (כולל CYYMMDD ו-requestTimeStamp) + And אזור הזמן הוא Asia/Jerusalem + + @compliance + Scenario: ציות לרגולציה – בנק ישראל והגנת הפרטיות + Given קיימים מסמכי מדיניות ובקרות אבטחה + When אני בודק תהליכי הזדהות, ניהול הרשאות CA רמה 2, שמירת נתונים ואנונימיזציה + Then המערכת עומדת בדרישות הרגולציה המקומית ללא ליקויי פרטיות או אבטחה diff --git a/functional_tests/hapao/hapao.json b/functional_tests/hapao/hapao.json new file mode 100644 index 0000000..326eb5d --- /dev/null +++ b/functional_tests/hapao/hapao.json @@ -0,0 +1,524 @@ +{ + "scenarios": [ + { + "type": "functional", + "title": "הקמת בקשה OTP – כאל (SMS)", + "description": "ווידוא תהליך generateOtp עבור מתפעלת כאל עם משלוח קוד OTP ב-SMS.", + "testId": "TC-001", + "testDescription": "בדיקת ניתוב למתפעלת כאל (cardIssuingSpCode=3), יצירת OTP ושליחה ב-SMS. אימות שהשדות ממופים נכון ל-API של כאל ושחוזרים otpToken ו-phoneNumber כמצופה.", + "prerequisites": "לקוח קיים במערכות עם מספר נייד תקף אצל כאל. הרשאת רמה 2 (CA) תקינה. סביבת TST של כאל זמינה.", + "stepsToPerform": "1. בצע קריאה POST ל-card-operator/restore-details-gw/otp.\n2. HEADER: variousChannelTypeCode=10001, bankNumber=012, branchNumber=123, accountNumber=1234567, partySerialId=12345678901, partyShortId=012345678, partyIdTypeCode=1, countryId=212.\n3. BODY: activityTypeCode=101, cardIssuingSpCode=3, creditCardSerialId=\"abcdef_1234_abcd_5678_90ab_cdef_1234\", cardIdServiceProvider=\"1234567890123456789\", smsByVoice=0, orderId=\"a3e9f7d2-4b5c-11ee-be56-0242ac120002\".\n4. וודא שהמערכת מפעילה את API של כאל: POST https://tst-api.cal-online.co.il/PartnerAuthentication.Api/api/SendOtp/sendOTP, עם x-access-token תקף (getToken), ושדות ממופים לפי האפיון.\n5. אמת זמן תגובה של כאל < 5000ms.\n6. קבל תשובת 200 מהמתפעלת עם StatusCode=1.", + "expectedResult": "סטטוס 200, verify generateOtpResponseDto עם otpToken=token מהמתפעלת ו-phoneNumber=phoneNumber מהמתפעלת. orderId זהה לקלט. אין אובייקט errors." + }, + { + "type": "functional", + "title": "הקמת בקשה OTP – כאל (קולית/IVR)", + "description": "ווידוא תהליך generateOtp עבור כאל עם משלוח קוד OTP בהודעה קולית.", + "testId": "TC-002", + "testDescription": "בדיקת smsByVoice=1 גורם לשליחת OTP בערוץ IVR אצל כאל.", + "prerequisites": "לקוח קיים עם מספר נייד תקף, הרשאת CA רמה 2, סביבת TST של כאל זמינה.", + "stepsToPerform": "1. קריאה POST ל-/otp עם אותם ערכי HEADER כמו TC-001.\n2. BODY: activityTypeCode=101, cardIssuingSpCode=3, creditCardSerialId=\"abcdef_1234_abcd_5678_90ab_cdef_1234\", cardIdServiceProvider=\"1234567890123456789\", smsByVoice=1, orderId=\"a3e9f7d2-4b5c-11ee-be56-0242ac120002\".\n3. וודא ב-API של כאל שהשדה message.smsByVoice=1.\n4. אמת קבלת http 200 + StatusCode=1.", + "expectedResult": "סטטוס 200 עם otpToken ו-phoneNumber מממשק כאל. OTP נשלח בערוץ IVR. orderId זהה לקלט." + }, + { + "type": "functional", + "title": "הקמת בקשה OTP – ישראכרט (SMS)", + "description": "תהליך generateOtp מלא לישראכרט: קבלת טוקן זמני לפי מזהה ותאריך לידה ושליחת OTP ב-SMS.", + "testId": "TC-003", + "testDescription": "בדיקה של שני שלבים אצל ישראכרט: 1) token byIdAndDateOfBirth; 2) otpByToken/send. אימות המרות dateOfBirth ל-CYYMMDD, requestTimeStamp, קבועים bankCode=012 ו-companyCode=B ומיפוי ערכי ישראל alpha2CountryCode=IL.", + "prerequisites": "לקוח קיים אצל ישראכרט עם תאריך לידה ומספר נייד תקף. הרשאת CA רמה 2. סביבת preprod של ישראכרט זמינה.", + "stepsToPerform": "1. קריאה POST ל-/otp.\n2. HEADER: variousChannelTypeCode=10001, bankNumber=012, branchNumber=123, accountNumber=1234567, partySerialId=12345678901, partyShortId=012345678, partyIdTypeCode=1, countryId=212.\n3. BODY: activityTypeCode=101, cardIssuingSpCode=1, creditCardSerialId=\"abcdef_1234_abcd_5678_90ab_cdef_1234\", cardSuffix=\"1234\", birthDate=\"15/04/1998\", smsByVoice=0, orderId=\"a3e9f7d2-4b5c-11ee-be56-0242ac120002\", alpha2CountryCode=\"IL\".\n4. שלב 1: POST https://preprod.api.isracard.co.il/isracard/preprod/authorization/token/v1.2.0/byIdAndDateOfBirth עם:\n - requestId=orderId מהקלט\n - requestTimeStamp בפורמט yyyy-MM-dd-HH.mm.ss.SSSSSS לפי Asia/Jerusalem\n - idNumber=partyShortId\n - idCode=partyIdTypeCode\n - cardLastFourDigits=cardSuffix\n - companyCode=\"B\"\n - dateOfBirth= \"0980415\" עבור 15/04/1998 (C=0, YY=98, MM=04, DD=15)\n - activityType=activityTypeCode\n - alpha2CountryCode=\"IL\"\n - bankCode=\"012\".\n5. קבל token מהתשובה.\n6. שלב 2: POST https://preprod.api.isracard.co.il/isracard/preprod/authorization/otpByToken/v1.3.0/send עם:\n - requestGeneralHeader.requestId=orderId\n - tokenRequest.authorizationToken=token\n - deliveryMethod=0 (SMS).\n7. אמת http 200 בתשובה השנייה.", + "expectedResult": "סטטוס 200, generateOtpResponseDto עם otpToken=token (מממשק ישראכרט) ו-phoneNumber=maskedCellphoneNumber באורך 10 ספרות. orderId זהה לקלט. אין errors." + }, + { + "type": "functional", + "title": "הקמת בקשה OTP – ישראכרט (IVR)", + "description": "שליחת OTP בערוץ IVR אצל ישראכרט באמצעות deliveryMethod=1.", + "testId": "TC-004", + "testDescription": "בדיקת מסלול ישראכרט כש-BODY.smsByVoice=1. אימות שמועבר deliveryMethod=1 ל-endpoint send ושהתשובה תקינה.", + "prerequisites": "אותם תנאים כמו TC-003.", + "stepsToPerform": "1. קריאה POST ל-/otp עם אותם HEADER.\n2. BODY: cardIssuingSpCode=1, cardSuffix=\"1234\", birthDate=\"15/04/1998\", smsByVoice=1, alpha2CountryCode=\"IL\", שאר השדות כ-TC-003.\n3. הפעלה לשלב token ולאחר מכן send עם deliveryMethod=1.\n4. אמת http 200 בתשובה השנייה.", + "expectedResult": "סטטוס 200, otpToken ו-phoneNumber (maskedCellphoneNumber), orderId זהה לקלט. OTP נשלח בערוץ IVR." + }, + { + "type": "functional", + "title": "ניתוב ל-MAX – הקמת OTP", + "description": "בדיקת ניתוב תקין למתפעלת MAX עבור generateOtp.", + "testId": "TC-005", + "testDescription": "כאשר cardIssuingSpCode=2, השירות חייב לנתב ל-MAX. נבדק אימות שדות חובה ל-MAX (לפי האפיון: cardIdServiceProvider חובה), והחזרת תשובה או שגיאה בהתאם למה שהמתפעלת מחזירה.", + "prerequisites": "לקוח קיים אצל MAX, הרשאת CA, תצורת ניתוב ל-MAX פעילה ב-ESB/LB.", + "stepsToPerform": "1. POST ל-/otp עם HEADER תקין.\n2. BODY: activityTypeCode=101, cardIssuingSpCode=2, creditCardSerialId תקין, cardIdServiceProvider=\"1234567890123456789\", smsByVoice=0, orderId תקין.\n3. עקוב אחרי קריאה יוצאת ל-MAX (לוגי/מטריקות) ואמת שמופעלת נקודת הקצה של MAX.\n4. אמת קבלת תשובה תקינה או שגיאה מהמתפעלת.", + "expectedResult": "במקרה הצלחה: סטטוס 200 והחזרת otpToken/phoneNumber כפי שהתקבלו מ-MAX. במקרה כישלון: השגיאה כפי שהוגדרה ע\"י המתפעלת או מיפוי גלובלי לפי מדיניות השירות." + }, + { + "type": "functional", + "title": "חסר שדה חובה – generateOtp", + "description": "בדיקת התנהגות במצב חסר שדה חובה בקלט.", + "testId": "TC-006", + "testDescription": "השמטת שדה חובה (למשל cardIssuingSpCode) ב-BODY צריכה להחזיר 400 עם Id=7 והודעה מתאימה.", + "prerequisites": "שירות פעיל. הרשאת CA תקינה.", + "stepsToPerform": "1. POST ל-/otp עם HEADER תקין.\n2. BODY ללא cardIssuingSpCode.\n3. שלח בקשה.", + "expectedResult": "סטטוס 400, errors עם id=7 ו-message=\"Invalid request field [cardIssuingSpCode]\"." + }, + { + "type": "functional", + "title": "ולידציה ערך מתפעלת – generateOtp", + "description": "בדיקת ערך cardIssuingSpCode מחוץ לטווח המותר.", + "testId": "TC-007", + "testDescription": "ערכים מותרים: 1/2/3 בלבד. שליחת cardIssuingSpCode=4 אמורה להיכשל לפי טבלת הולידציות.", + "prerequisites": "שירות פעיל.", + "stepsToPerform": "1. POST ל-/otp עם HEADER תקין.\n2. BODY: cardIssuingSpCode=4 ושאר שדות חובה תקינים.\n3. שלח בקשה.", + "expectedResult": "סטטוס 400, errors עם id=7 והודעה מפורטת על הולידציה לא תקינה." + }, + { + "type": "functional", + "title": "ולידציה activityTypeCode – מספרים בלבד", + "description": "בדיקה ש-activityTypeCode אינו מקבל תווים לא מספריים.", + "testId": "TC-008", + "testDescription": "שליחת activityTypeCode=\"10A\" אמורה להיכשל.", + "prerequisites": "שירות פעיל.", + "stepsToPerform": "1. POST ל-/otp עם HEADER תקין.\n2. BODY: activityTypeCode=\"10A\", cardIssuingSpCode=3, שאר שדות תקינים.\n3. שלח בקשה.", + "expectedResult": "סטטוס 400, errors id=7 עם הודעה על ולידציה מספרית." + }, + { + "type": "functional", + "title": "ולידציה creditCardSerialId – פורמט ESB base16 עם קו תחתון", + "description": "בדיקה ש-creditCardSerialId בפורמט הנדרש.", + "testId": "TC-009", + "testDescription": "פורמט צפוי: xxxxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx עם תווים base16 בלבד. שליחת ערך כולל תו שאינו hex אמורה להיכשל.", + "prerequisites": "שירות פעיל.", + "stepsToPerform": "1. BODY: creditCardSerialId=\"xyz123_@@@@_abcd_5678_90ab_cdef_1234\".\n2. שאר שדות חובה תקינים.\n3. שלח POST ל-/otp.", + "expectedResult": "סטטוס 400, errors id=7 עם הודעה מפורטת על סוג הולידציה לפורמט מזהה כרטיס פועלים." + }, + { + "type": "functional", + "title": "ולידציה cardSuffix – 4 ספרות", + "description": "בדיקת אורך ותווים עבור cardSuffix אצל ישראכרט.", + "testId": "TC-010", + "testDescription": "שליחת cardSuffix=\"12AB\" או \"12345\" אמורה להיכשל (מספרים בלבד, אורך 4).", + "prerequisites": "שירות פעיל.", + "stepsToPerform": "1. POST ל-/otp עם cardIssuingSpCode=1.\n2. BODY: cardSuffix=\"12AB\", שאר שדות חובה לישראכרט.\n3. שלח.\n4. חזור עם cardSuffix=\"12345\".\n5. שלח.", + "expectedResult": "בשתי הבדיקות: סטטוס 400, errors id=7 עם הודעת ולידציה מתאימה." + }, + { + "type": "functional", + "title": "ולידציה cardIdServiceProvider – 19 ספרות", + "description": "בדיקת פורמט מזהה כרטיס מתפעלת ל-CAL/MAX.", + "testId": "TC-011", + "testDescription": "שליחת cardIdServiceProvider שאינו באורך 19 או כולל תווים שאינם מספרים – כישלון 400.", + "prerequisites": "שירות פעיל.", + "stepsToPerform": "1. POST ל-/otp עם cardIssuingSpCode=3.\n2. BODY: cardIdServiceProvider=\"12345678901234567A\".\n3. שלח.", + "expectedResult": "סטטוס 400, errors id=7 עם הודעת ולידציה על cardIdServiceProvider." + }, + { + "type": "functional", + "title": "ולידציה birthDate – פורמט DD/MM/YYYY", + "description": "בדיקת תאריך לידה אצל ישראכרט.", + "testId": "TC-012", + "testDescription": "שליחת birthDate=\"1998-04-15\" אמורה להיכשל.", + "prerequisites": "שירות פעיל.", + "stepsToPerform": "1. POST ל-/otp עם cardIssuingSpCode=1.\n2. BODY: birthDate=\"1998-04-15\" ושאר שדות תקינים.\n3. שלח.", + "expectedResult": "סטטוס 400, errors id=7 עם הודעת ולידציה על פורמט תאריך." + }, + { + "type": "functional", + "title": "ולידציה smsByVoice – ערכים מותרים 0/1", + "description": "בדיקת ערך smsByVoice.", + "testId": "TC-013", + "testDescription": "שליחת smsByVoice=2 אמורה להיכשל.", + "prerequisites": "שירות פעיל.", + "stepsToPerform": "1. POST ל-/otp עם smsByVoice=2.\n2. שאר השדות תקינים.\n3. שלח.", + "expectedResult": "סטטוס 400, errors id=7 עם הודעת ולידציה על ערך smsByVoice." + }, + { + "type": "functional", + "title": "ולידציה orderId – UUID תקין", + "description": "בדיקת פורמט orderId.", + "testId": "TC-014", + "testDescription": "שליחת orderId ללא מקפים או באורך שגוי אמורה להיכשל.", + "prerequisites": "שירות פעיל.", + "stepsToPerform": "1. POST ל-/otp עם orderId=\"a3e9f7d24b5c11eebe560242ac120002\".\n2. שאר השדות תקינים.\n3. שלח.", + "expectedResult": "סטטוס 400, errors id=7 עם הודעת ולידציה על UUID." + }, + { + "type": "functional", + "title": "שגיאת המרה – Mismatch Conversion (Id=19)", + "description": "בדיקת שגיאת סוג נתונים בקלט.", + "testId": "TC-015", + "testDescription": "כאשר שדה מספרי מועבר כמחרוזת לא ניתנת להמרה, מתקבלת שגיאה עם Id=19.", + "prerequisites": "שירות פעיל.", + "stepsToPerform": "1. POST ל-/otp.\n2. HEADER: partySerialId=\"ABCDEF\" (במקום Long).\n3. שלח.", + "expectedResult": "סטטוס 400, errors id=19 עם message=\"Cannot assign field [partySerialId] due to a mismatch conversion\"." + }, + { + "type": "functional", + "title": "טיימאאוט ישראכרט – token byIdAndDateOfBirth", + "description": "בדיקת מיפוי טיימאאוט 5000ms לשגיאה גלובלית 408 (Id=8).", + "testId": "TC-016", + "testDescription": "הדמיית עיכוב תשובה בשלב קבלת token מישראכרט.", + "prerequisites": "כלי הדמיה לעיכוב תשובה ב-preprod או הגדרות נסיוניות.", + "stepsToPerform": "1. POST ל-/otp עם cardIssuingSpCode=1 ושדות תקינים.\n2. הדמיית עיכוב > 5000ms בשירות /authorization/token/…/byIdAndDateOfBirth.\n3. שלח ובדוק תשובה.", + "expectedResult": "סטטוס 408, errors id=8 עם message=\"The service is temporarily unavailable\"." + }, + { + "type": "functional", + "title": "חריגה במספר ניסיונות – ישראכרט token (423)", + "description": "מיפוי 423 מישראכרט ל-409 עם StatusCode=3.", + "testId": "TC-017", + "testDescription": "הדמיית מצב בו מספר ניסיונות זיהוי לקוח חרג מהמותר בשלב token.", + "prerequisites": "כלי הדמיה להחזרת 423 ב-token.", + "stepsToPerform": "1. POST ל-/otp עם cardIssuingSpCode=1.\n2. הדמיה: תשובת 423 ב-token.\n3. שלח.", + "expectedResult": "סטטוס 409, StatusCode=3, הודעת כישלון בהתאם למתפעלת." + }, + { + "type": "functional", + "title": "ללקוח לא קיים מספר טלפון – ישראכרט send (404)", + "description": "מיפוי 404 undefined_parameter ל-409 עם StatusCode=4.", + "testId": "TC-018", + "testDescription": "הדמיית send מחזיר 404 עם error.code=undefined_parameter.", + "prerequisites": "כלי הדמיה להחזרת השגיאה המתוארת.", + "stepsToPerform": "1. POST ל-/otp עם cardIssuingSpCode=1.\n2. שלב token תקין.\n3. שלב send מחזיר 404 undefined_parameter.\n4. בדוק תשובת השירות.", + "expectedResult": "סטטוס 409, StatusCode=4, ללא otpToken, אובייקט errors בהתאם." + }, + { + "type": "functional", + "title": "שגיאות 40X/50X – ישראכרט send", + "description": "מיפוי שגיאות 40X/50X ל-500 גלובלי (Id=6).", + "testId": "TC-019", + "testDescription": "בדיקה שהשירות מחזיר 500 Internal Server Error עבור שגיאות 40X/50X שאינן מפורטות אחרת אצל ישראכרט.", + "prerequisites": "כלי הדמיה לשגיאת 401/500 ב-send.", + "stepsToPerform": "1. POST ל-/otp עם cardIssuingSpCode=1.\n2. שלב token תקין.\n3. שלב send מחזיר 500.\n4. בדוק תשובה.", + "expectedResult": "סטטוס 500, errors id=6 עם message=\"Internal Server Error\"." + }, + { + "type": "functional", + "title": "טיימאאוט כאל – sendOTP", + "description": "בדיקת מיפוי טיימאאוט ב-sendOTP של כאל לשגיאה 408 (Id=8).", + "testId": "TC-020", + "testDescription": "הדמיית TO>5000ms ב-API של כאל.", + "prerequisites": "כלי הדמיה לעיכוב תשובה ב-TST.", + "stepsToPerform": "1. POST ל-/otp עם cardIssuingSpCode=3.\n2. הדמיית עיכוב ב-sendOTP.\n3. בדוק תשובת השירות.", + "expectedResult": "סטטוס 408, errors id=8." + }, + { + "type": "functional", + "title": "שגיאת 40X של כאל – החזרה כפי שהתקבל", + "description": "כאשר שירות כאל מחזיר 40X, השירות מחזיר את השגיאה כפי שהתקבלה מהמתפעלת.", + "testId": "TC-021", + "testDescription": "אימות Pass-through לשגיאות 40X של כאל במתודה generateOtp.", + "prerequisites": "הדמיית תשובת 4XX ב-sendOTP.", + "stepsToPerform": "1. POST ל-/otp עם cardIssuingSpCode=3.\n2. הפעלת sendOTP מחזירה 4XX (למשל 401/403).\n3. בדוק תשובת השירות.", + "expectedResult": "סטטוס זהה לקוד 40X שהתקבל מכאל, גוף שגיאה כפי שהתקבל מהמתפעלת." + }, + { + "type": "functional", + "title": "שגיאת 50X של כאל – מיפוי ל-500 גלובלי", + "description": "בדיקת מיפוי 50X בכאל לשגיאה גלובלית (Id=6).", + "testId": "TC-022", + "testDescription": "כאל מחזיר 500; השירות צריך להחזיר 500 עם Id=6.", + "prerequisites": "הדמיית 500 ב-sendOTP.", + "stepsToPerform": "1. POST ל-/otp עם cardIssuingSpCode=3.\n2. הדמיית 500.\n3. בדוק תשובת השירות.", + "expectedResult": "סטטוס 500, errors id=6, message=\"Internal Server Error\"." + }, + { + "type": "functional", + "title": "מיפוי מספר טלפון – ישראכרט (masked) מול כאל (plain)", + "description": "אימות הבדלי מיפוי phoneNumber בתשובות.", + "testId": "TC-023", + "testDescription": "אצל ישראכרט, phoneNumber=maskedCellphoneNumber; אצל כאל, phoneNumber כשדה רגיל מהמתפעלת.", + "prerequisites": "TC-001 ו-TC-003 הצליחו.", + "stepsToPerform": "1. הפעל TC-003 וקבל phoneNumber.\n2. הפעל TC-001 וקבל phoneNumber.\n3. השווה תבניות.", + "expectedResult": "אצל ישראכרט: מחרוזת באורך 10, מוצנעת/מוסווית. אצל כאל: מספר גלוי כפי שהמתפעלת מחזירה." + }, + { + "type": "functional", + "title": "alpha2CountryCode – מיפוי IL מ-countryId=212", + "description": "בדיקת מיפוי קוד ארץ ל-alpha2CountryCode עבור ישראכרט.", + "testId": "TC-024", + "testDescription": "countryId=212 אמור להתמפות ל-IL לפי DPT0044. בדוק שה-BODY.alpha2CountryCode=IL נשלח ל-token של ישראכרט.", + "prerequisites": "טבלת מיפוי DPT0044 זמינה במערכת.", + "stepsToPerform": "1. POST ל-/otp עם cardIssuingSpCode=1 ו-countryId=212.\n2. BODY: alpha2CountryCode=\"IL\".\n3. נטר את בקשת token ובדוק הערך שנשלח.", + "expectedResult": "נשלח alpha2CountryCode=IL לשירות token. סטטוס 200." + }, + { + "type": "functional", + "title": "חסר alpha2CountryCode אצל ישראכרט", + "description": "בדיקת שדה alpha2CountryCode חובה לישראכרט.", + "testId": "TC-025", + "testDescription": "השמטת alpha2CountryCode כאשר cardIssuingSpCode=1 תגרום ל-400 Id=7.", + "prerequisites": "שירות פעיל.", + "stepsToPerform": "1. POST ל-/otp עם cardIssuingSpCode=1, ללא alpha2CountryCode.\n2. שלח.", + "expectedResult": "סטטוס 400, errors id=7 עם הודעה על שדה חסר." + }, + { + "type": "functional", + "title": "requestTimeStamp – פורמט ותזמון ישראל", + "description": "בדיקה שה-RequestTimeStamp נשלח בפורמט הנדרש ובאזור זמן ישראל.", + "testId": "TC-026", + "testDescription": "אמת פורמט yyyy-MM-dd-HH.mm.ss.SSSSSS לפי Asia/Jerusalem, כולל שינויי שעון קיץ, בשלב token לישראכרט.", + "prerequisites": "שעון שרת מסונכרן ל-Asia/Jerusalem.", + "stepsToPerform": "1. POST ל-/otp עם cardIssuingSpCode=1.\n2. בדוק את גוף בקשת token וערך requestTimeStamp.\n3. השווה לפורמט ולשעה הנוכחית בישראל.", + "expectedResult": "ערך requestTimeStamp עומד בפורמט הנדרש ובאזור הזמן ישראל." + }, + { + "type": "functional", + "title": "המרת תאריך לידה ל-CYYMMDD", + "description": "בדוק המרת תאריך לידה לפני ואחרי שנת 2000.", + "testId": "TC-027", + "testDescription": "בדיקה עם birthDate=\"15/04/1998\" => \"0980415\" ו-birthDate=\"02/01/2001\" => \"1010102\".", + "prerequisites": "שירות פעיל.", + "stepsToPerform": "1. POST ל-/otp עבור ישראכרט עם birthDate=\"15/04/1998\".\n2. אמת ערך שנשלח ל-token.\n3. חזור עם birthDate=\"02/01/2001\".\n4. אמת ערך שנשלח.", + "expectedResult": "המרות תואמות לכללי CYYMMDD: C=0 לפני 2000, C=1 מ-2000 ואילך." + }, + { + "type": "functional", + "title": "קבועים bankCode ו-companyCode – ישראכרט", + "description": "אימות קבועים בבקשת token לישראכרט.", + "testId": "TC-028", + "testDescription": "בדוק שבקשת token כוללת bankCode=\"012\" ו-companyCode=\"B\" כמפורט.", + "prerequisites": "שירות פעיל.", + "stepsToPerform": "1. POST ל-/otp עבור ישראכרט.\n2. בדוק גוף בקשת token.\n3. וודא הקבועים.", + "expectedResult": "נשלחים bankCode=012 ו-companyCode=B בבקשה ל-token." + }, + { + "type": "functional", + "title": "אימות OTP – כאל: הצלחה", + "description": "בדיקת מתודה otpByToken במסלול כאל, כולל קבלת jwt ואז מפתח הצפנה.", + "testId": "TC-029", + "testDescription": "קריאה ל-Authenticate לקבלת jwt (ott), ולאחר מכן GetEncryptedKey לקבלת encryptionKey. מיפוי הערכים לתשובת השירות.", + "prerequisites": "otpToken תקף שהתקבל מ-TC-001 או TC-002. הרשאת CA. סביבת TST זמינה.", + "stepsToPerform": "1. POST ל-card-operator/restore-details-gw/verify-otp.\n2. HEADER תקין.\n3. BODY: activityTypeCode=101, cardIssuingSpCode=3, otpPassword=\"123456\", otpToken=\"OTP123TOKEN\", orderId=\"a3e9f7d2-4b5c-11ee-be56-0242ac120002\".\n4. הפעלת POST Authenticate עם token=otpToken, password=otpPassword.\n5. קבל jwt.\n6. הפעלת POST GetEncryptedKey עם authorization=jwt.\n7. קבל encryptionKey.\n8. אמת http 200 + StatusCode=1 בשתי הקריאות.", + "expectedResult": "סטטוס 200, verifyOtpResponseDto: orderId זהה לקלט, ott=jwt, encryptionKey=encryptionKey, ללא errors." + }, + { + "type": "functional", + "title": "אימות OTP – ישראכרט: הצלחה", + "description": "בדיקת מתודה otpByToken במסלול ישראכרט, כולל validate והחזרת tek ו-authorizationToken.", + "testId": "TC-030", + "testDescription": "קריאה ל-validate עם authorizationToken=otpToken ו-otp=otpPassword. מיפוי tek=>encryptionKey ו-authorizationToken=>ott.", + "prerequisites": "otpToken תקף מ-TC-003/TC-004. הרשאת CA. סביבת preprod זמינה.", + "stepsToPerform": "1. POST ל-/verify-otp.\n2. HEADER תקין.\n3. BODY: activityTypeCode=101, cardIssuingSpCode=1, otpPassword=\"123456\", otpToken=\"OTP123TOKEN\", orderId.\n4. הפעלת validate לכתובת v1.4.0/validate עם הנתונים.\n5. קבל tek ו-authorizationToken.\n6. אמת http 200 + StatusCode=1.", + "expectedResult": "סטטוס 200, verifyOtpResponseDto: orderId זהה לקלט, ott=authorizationToken, encryptionKey=tek, ללא errors." + }, + { + "type": "functional", + "title": "חסר שדה חובה – otpByToken", + "description": "בדיקה של חסר שדה חובה במתודה verify-otp.", + "testId": "TC-031", + "testDescription": "השמטת otpPassword אמורה לגרום ל-400 Id=7.", + "prerequisites": "שירות פעיל.", + "stepsToPerform": "1. POST ל-/verify-otp ללא otpPassword.\n2. שאר השדות תקינים.\n3. שלח.", + "expectedResult": "סטטוס 400, errors id=7 עם message=\"Invalid request field [otpPassword]\"." + }, + { + "type": "functional", + "title": "ולידציה otpPassword – מספרים בלבד ושימור אפסים מובילים", + "description": "בדיקת שהקוד OTP חייב להיות מספרי ושאפסים מובילים נשמרים.", + "testId": "TC-032", + "testDescription": "שליחת otpPassword=\"000123\" צריכה להתקבל (אם תקף), ושליחת otpPassword=\"12A45\" צריכה להיכשל (400 Id=7).", + "prerequisites": "otpToken תקף.", + "stepsToPerform": "1. POST ל-/verify-otp עם otpPassword=\"12A45\".\n2. בדוק תשובה.\n3. POST עם otpPassword=\"000123\".\n4. בדוק תשובה.", + "expectedResult": "מקרה ראשון: 400 Id=7. מקרה שני: תהליך ממשיך בהתאם לתקפות ה-OTP, ללא איבוד אפסים מובילים." + }, + { + "type": "functional", + "title": "ולידציה orderId – otpByToken", + "description": "בדיקת פורמט UUID עבור orderId במתודה verify-otp.", + "testId": "TC-033", + "testDescription": "שליחת orderId בפורמט לא תקין אמורה להחזיר 400 Id=7.", + "prerequisites": "שירות פעיל.", + "stepsToPerform": "1. POST ל-/verify-otp עם orderId=\"INVALID-UUID\".\n2. שלח.", + "expectedResult": "סטטוס 400, errors id=7." + }, + { + "type": "functional", + "title": "טיימאאוט כאל – Authenticate", + "description": "בדיקת מיפוי טיימאאוט באימות OTP של כאל ל-408 (Id=8).", + "testId": "TC-034", + "testDescription": "הדמיית TO>5000ms ב-Authenticate.", + "prerequisites": "כלי הדמיה ב-TST.", + "stepsToPerform": "1. POST ל-/verify-otp עם cardIssuingSpCode=3.\n2. הדמיית עיכוב ב-Authenticate.\n3. בדוק תשובת השירות.", + "expectedResult": "סטטוס 408, errors id=8." + }, + { + "type": "functional", + "title": "סיסמה שגויה – ישראכרט validate (responseCode=invalid_otp_attempt)", + "description": "מיפוי תשובת 200 עם responseCode שגוי ל-409 StatusCode=7.", + "testId": "TC-035", + "testDescription": "בדיקת מצב בו validate מחזיר responseCode=invalid_otp_attempt.", + "prerequisites": "otpToken תקף, OTP שגוי.", + "stepsToPerform": "1. POST ל-/verify-otp עם cardIssuingSpCode=1, otpPassword לא נכון.\n2. בדוק תשובה.", + "expectedResult": "סטטוס 409, StatusCode=7." + }, + { + "type": "functional", + "title": "חסימת שימוש – ישראכרט (423)", + "description": "מיפוי 423 ב-validate ל-409 StatusCode=8.", + "testId": "TC-036", + "testDescription": "בדיקת מצב בו לא ניתן להשתמש עקב מספר רב של ניסיונות.", + "prerequisites": "כלי הדמיה 423 ב-validate.", + "stepsToPerform": "1. POST ל-/verify-otp עם cardIssuingSpCode=1.\n2. הדמיית 423.\n3. בדוק תשובה.", + "expectedResult": "סטטוס 409, StatusCode=8." + }, + { + "type": "functional", + "title": "פג תוקף סיסמא – ישראכרט (401)", + "description": "מיפוי 401 ב-validate ל-403 StatusCode=33.", + "testId": "TC-037", + "testDescription": "בדיקה של OTP שפג תוקפו אצל ישראכרט.", + "prerequisites": "otpToken קיים אך OTP פג תוקף.", + "stepsToPerform": "1. POST ל-/verify-otp עם cardIssuingSpCode=1.\n2. הדמיית 401.\n3. בדוק תשובה.", + "expectedResult": "סטטוס 403, StatusCode=33." + }, + { + "type": "functional", + "title": "שגיאות 40X/50X – ישראכרט validate", + "description": "מיפוי שגיאות כלליות ל-500 גלובלי (Id=6) במתודה validate.", + "testId": "TC-038", + "testDescription": "בדיקת היגיון מיפוי שגיאות שלא הוגדרו ספציפית.", + "prerequisites": "הדמיה 500 או 40X לא ספציפי.", + "stepsToPerform": "1. POST ל-/verify-otp עם cardIssuingSpCode=1.\n2. הדמיית 500.\n3. בדוק תשובה.", + "expectedResult": "סטטוס 500, errors id=6, message=\"Internal Server Error\"." + }, + { + "type": "functional", + "title": "בדיקת השבת orderId במתודה generateOtp", + "description": "אימות ש-orderId חוזר כפי שהתקבל בקלט.", + "testId": "TC-039", + "testDescription": "אחרי הצלחת generateOtp, יש לוודא ש-orderId בפלט זהה לקלט.", + "prerequisites": "TC-001 או TC-003 בוצעו בהצלחה.", + "stepsToPerform": "1. קבל תשובת generateOtp.\n2. השווה orderId לקלט.", + "expectedResult": "orderId בפלט זהה לערך שנשלח." + }, + { + "type": "functional", + "title": "בדיקת השבת orderId במתודה otpByToken", + "description": "אימות ש-orderId חוזר כפי שהתקבל בקלט ב-verify-otp.", + "testId": "TC-040", + "testDescription": "אחרי הצלחת otpByToken, orderId בפלט חייב להיות זהה לקלט.", + "prerequisites": "TC-029 או TC-030 בוצעו בהצלחה.", + "stepsToPerform": "1. קבל תשובת otpByToken.\n2. השווה orderId לקלט.", + "expectedResult": "orderId בפלט זהה לערך שנשלח." + }, + { + "type": "functional", + "title": "אימות הרשאה – רמה 2 (CA)", + "description": "בדיקת גישה ללא הרשאה תיקנית או עם הרשאה שפג תוקפה.", + "testId": "TC-041", + "testDescription": "קריאה לשירות ללא הרשאת רמה 2 או עם טוקן שפג תוקף צריכה להחזיר 401 Id=5.", + "prerequisites": "ביטול או הדמיית פג תוקף של הרשאת CA.", + "stepsToPerform": "1. POST ל-/otp ללא הרשאה.\n2. בדוק תשובה.\n3. POST ל-/verify-otp ללא הרשאה.\n4. בדוק תשובה.", + "expectedResult": "סטטוס 401, errors id=5 עם message מתאים." + }, + { + "type": "non-functional", + "title": "ביצועים – זמן תגובה generateOtp תחת עומס", + "description": "בדיקת SLA ביצועים תחת עומס בהתאם לנורמות בנק ישראל.", + "testId": "TC-042", + "testDescription": "מדידת זמן תגובה end-to-end (כולל קריאות למתפעלת) עבור generateOtp ב-500 בקשות בדקה, עם יעד ממוצע < 1500ms ו-p95 < 2500ms.", + "prerequisites": "סביבת בדיקות יציבה, כלי עומס (JMeter/Gatling), זמינות מתפעלת.", + "stepsToPerform": "1. הרץ עומס של 500 RPS למשך 1 דקה על /otp עם נתונים תקינים (CAL וישראכרט בחלוקה 50/50).\n2. מדוד זמני תגובה, שגיאות ו-timeouts.\n3. אסוף מדדים.", + "expectedResult": "עמידה ביעדים: ממוצע < 1500ms, p95 < 2500ms, שיעור שגיאות < 1%." + }, + { + "type": "non-functional", + "title": "ביצועים – זמן תגובה otpByToken תחת עומס", + "description": "בדיקת SLA ביצועים עבור אימות OTP וקבלת מפתח הצפנה.", + "testId": "TC-043", + "testDescription": "מדידת זמן תגובה end-to-end ל-/verify-otp ב-300 בקשות בדקה, יעד ממוצע < 1500ms, p95 < 2500ms.", + "prerequisites": "OTP תקפים שנוצרו מראש, כלי עומס.", + "stepsToPerform": "1. צור מראש 300 otpToken תקפים.\n2. הרץ 300 RPS ל-/verify-otp עם נתונים תקינים עבור CAL/ישראכרט.\n3. מדוד זמני תגובה ושגיאות.", + "expectedResult": "עמידה ביעדים הביצועיים ושיעור שגיאות נמוך." + }, + { + "type": "non-functional", + "title": "אבטחה – TLS1.2+ והקשחת תקשורת", + "description": "ווידוא שהתקשורת יוצאת ונכנסת מוצפנת לפי תקן בנק ישראל.", + "testId": "TC-044", + "testDescription": "בדיקה שכל התעבורת HTTPS לשירותי המתפעלת ולשירות עצמו מבוצעת עם TLS1.2 ומעלה, ללא תמיכה בגרסאות חלשות.", + "prerequisites": "גישה לנתבי אפליקציה/תצורה אבטחתית.", + "stepsToPerform": "1. סרוק את נקודות הקצה של השירות והמתפעלת עם כלי אבטחה (SSL Labs).\n2. וודא פרוטוקולים וצפנים נתמכים.\n3. נסה התחברות עם TLS1.0/1.1.", + "expectedResult": "נכשלה התחברות עם TLS1.0/1.1. רק TLS1.2+ נתמך." + }, + { + "type": "non-functional", + "title": "פרטיות – אי-לוגינג של OTP ומפתח הצפנה", + "description": "בדיקת תאימות לחוק הגנת הפרטיות בישראל ועקרונות בנק ישראל.", + "testId": "TC-045", + "testDescription": "ווידוא שאין רישום ביומני המערכת של otpPassword, otpToken, encryptionKey או פרטי כרטיס מלאים.", + "prerequisites": "גישה ליומני אפליקציה ו-APM.", + "stepsToPerform": "1. הרץ TC-001, TC-029, TC-030.\n2. נתח לוגים.\n3. חפש ערכי OTP/מפתחות/16 ספרות מלאות.", + "expectedResult": "אין מופעים של מידע רגיש ביומנים. קיימים רק מזהים לא רגישים (orderId, StatusCode)." + }, + { + "type": "non-functional", + "title": "נגישות ותמיכה תרבותית – תוכן SMS/IVR בעברית", + "description": "בדיקת שהמסרים ללקוח בעברית תקינה, מיושרת RTL וברורה למשתמשים בישראל.", + "testId": "TC-046", + "testDescription": "ווידוא שנוסח ה-SMS/IVR בעברית, קריא וב-RTL, ללא תווים באנגלית בלתי נחוצים, ותומך בקריאה של ספרות OTP.", + "prerequisites": "גישה לתבניות המסרים אצל המתפעלת או הדמיה.", + "stepsToPerform": "1. צור OTP באמצעות TC-003/TC-004/TC-001.\n2. בדוק את נוסח המסרים.\n3. אמת קריאות ספרות (למשל \"הקוד שלך: 123456\").", + "expectedResult": "מסרים בעברית תקינה ו-RTL, ברורים למשתמשים בישראל." + }, + { + "type": "non-functional", + "title": "איתור וניטור – קורלציה לפי orderId", + "description": "בדיקת יכולת מעקב מלא לפי orderId בכל רכיבי השרשרת.", + "testId": "TC-047", + "testDescription": "ווידוא שכל קריאה מתועדת עם orderId בקורלציה (TraceId/SpanId) לצורך חקירה ועמידה בתקנים.", + "prerequisites": "כלי ניטור (ELK/APM) פעילים.", + "stepsToPerform": "1. הרץ TC-003 ו-TC-030.\n2. בדוק יומנים ומטריקות.\n3. וודא קישוריות בין קריאות פנימה/החוצה לפי orderId.", + "expectedResult": "קיימת קורלציה מלאה לפי orderId בכל הלוגים והמדדים." + }, + { + "type": "non-functional", + "title": "Rate Limiting/Brute Force – ניסיונות OTP מוגבלים", + "description": "בדיקה שהמערכת מתמודדת עם ניסיונות רבים בהתאם לנורמות בנק ישראל.", + "testId": "TC-048", + "testDescription": "שליחת ניסיונות אימות OTP רבים לישראכרט עד לקבלת 423 ומיפוי ל-409 StatusCode=8.", + "prerequisites": "יכולת להגדיל ניסיונות ולנטר מספרם.", + "stepsToPerform": "1. שלח OTP שגוי שוב ושוב ל-/verify-otp (cardIssuingSpCode=1).\n2. תעד את מספר הניסיונות עד לקבלת 423.\n3. בדוק מיפוי תשובה.", + "expectedResult": "לאחר חציית הרף, סטטוס 409 StatusCode=8. אין דליפת מידע רגיש." + }, + { + "type": "non-functional", + "title": "סקיילביליות – עומס מקבילי גבוה", + "description": "בדיקת יכולת המערכת להתמודד עם עומס בו-זמני ללא פגיעה משמעותית בשירות.", + "testId": "TC-049", + "testDescription": "בחינת 1000 חיבורים מקביליים ל-/otp ו-/verify-otp, בדיקת כשלי ניתוב, זמני תגובה ויציבות.", + "prerequisites": "תשתית בדיקות עומס, סביבת מתפעלת זמינה.", + "stepsToPerform": "1. צור עומס מקבילי של 1000 חיבורים.\n2. מדוד זמני תגובה, שגיאות, timeouts.\n3. בדוק שימוש במשאבים.", + "expectedResult": "עמידה ביציבות, שיעור שגיאות נמוך, אין קריסה או דליפות זיכרון." + }, + { + "type": "non-functional", + "title": "התאוששות מתקלות – טיימאאוט והחזרת תשובה ידידותית", + "description": "בדיקת מסרים ידידותיים במקרי 408/404 ועמידה בדרישות שירות לקוחות בישראל.", + "testId": "TC-050", + "testDescription": "טיימאאוט/שגיאות ניתוב צריכים להחזיר הודעות ברורות ולוגים מספקים לטיפול.", + "prerequisites": "כלי הדמיה לטיימאאוט ושגיאת 404.", + "stepsToPerform": "1. הדמיית 408 ב-כאל.\n2. הדמיית 404 ב-ישראכרט.\n3. בדוק ההודעות.\n4. בדוק לוגים.", + "expectedResult": "מסרים בהתאם לטבלת השגיאות (Id=8/20), ללא חשיפת פרטים אישיים." + }, + { + "type": "non-functional", + "title": "לוקליזציה – פורמטי תאריך/זמן ומטבע", + "description": "ווידוא שימוש בפורמטי ישראל בתיעוד, לוגים ושדות תאריך.", + "testId": "TC-051", + "testDescription": "המערכת משתמשת בפורמט dd/MM/yyyy עבור תאריכים למשתמשים ובפורמט הנדרש ל-API חיצוניים. אזור הזמן הוא Asia/Jerusalem.", + "prerequisites": "גישה ללוגים ולפלטים.\n", + "stepsToPerform": "1. הפעל תרחישים מייצרי לוגים עם תאריכים.\n2. בדוק פורמט התאריכים למשתמשים ולמתפעלת.\n3. ודא אזור זמן.", + "expectedResult": "התאמה מלאה ללוקליזציה ישראלית ולדרישות האינטגרציה." + }, + { + "type": "non-functional", + "title": "ציות לרגולציה – בנק ישראל והגנת הפרטיות", + "description": "בדיקה כוללת לעמידה בתקנים ורגולציה מקומית.", + "testId": "TC-052", + "testDescription": "אימות תהליכי זיהוי ואימות, שמירת סודיות, מנגנוני בקרה, והיעדר אחסון פרטי כרטיס מלאים, בהתאם לדרישות בנק ישראל וחוק הגנת הפרטיות.", + "prerequisites": "מסמכי מדיניות, גישה לבקרות אבטחה.", + "stepsToPerform": "1. סקירת תהליכי הזדהות.\n2. בדיקת ניהול הרשאות CA רמה 2.\n3. סקירת מדיניות שמירת נתונים.\n4. בדיקת אנונימיזציה/מסיכה.\n", + "expectedResult": "עמידה בדרישות הרגולציה, ללא ליקויי פרטיות או אבטחה." + } + ] +} \ No newline at end of file diff --git a/functional_tests/hapao/hapao.xlsx b/functional_tests/hapao/hapao.xlsx new file mode 100644 index 0000000..b067a61 Binary files /dev/null and b/functional_tests/hapao/hapao.xlsx differ diff --git a/functional_tests/hapao/hapao.yaml b/functional_tests/hapao/hapao.yaml new file mode 100644 index 0000000..35f63ad --- /dev/null +++ b/functional_tests/hapao/hapao.yaml @@ -0,0 +1,757 @@ +openapi: 3.0.3 +info: + title: "MS: restore-details-gw – שירות ניתוב יציאה למתפעלת בתהליך אחזור פרטי כרטיס אונליין" + version: "1.1.0" + description: > + שירות REST לניהול בקשה לאחזור פרטי כרטיס אשראי ולתהליך אימות OTP מול מתפעלות חיצוניות (ישראכרט, MAX, כאל). + השירות כולל שתי מתודות: + - POST /otp (generateOtp): הקמת בקשה ויצירת/שליחת OTP ללקוח. + - POST /verify-otp (otpByToken): אימות OTP וקבלת מפתח הצפנה/מזהה תהליך (OTT). + ניתוב מתבצע לפי cardIssuingSpCode: + - 1: ישראכרט (שני שלבים: token ולאחר מכן send/validate עם מיפויים מיוחדים). + - 2: MAX (תשובת השירות משקפת את תשובת המתפעלת). + - 3: כאל (שלב יחיד לשליחה; אימות כולל שני שלבים). + הרשאות: נדרשת הרשאת CA ברמה 2 בכותרת Authorization. חסר/פג תוקף ⇒ 401, errors.id=5. + אבטחה: TLS1.2+ בלבד בתקשורת נכנסת/יוצאת. + ניהול שגיאות בהתאם לנספח ההודעות (ראו components/schemas/ErrorItem). + +servers: + - url: https://{host}/card-operator/restore-details-gw + description: "שרת השירות (ניתן לקבוע לפי משתנה סביבה BASE_URL)" + variables: + host: + default: api.example.com + - url: / + description: "בסיס יחסי – מתאים להרצה בסביבת בדיקות לפי BASE_URL" + +tags: + - name: "OTP" + description: "הקמה ושליחה של OTP" + - name: "Verify" + description: "אימות OTP וקבלת OTT/מפתח הצפנה" + +paths: + /otp: + post: + tags: ["OTP"] + summary: "הקמת בקשה OTP (generateOtp)" + description: > + ניתוב לבקשת OTP לפי חברה מתפעלת: + - כאל (cardIssuingSpCode=3): קריאה חיצונית sendOTP (עם x-access-token), זמן תגובה < 5000ms. + - ישראכרט (cardIssuingSpCode=1): token (byIdAndDateOfBirth) ואז send (otpByToken/v1.3.0), כולל: + • המרת birthDate ל־CYYMMDD, • שליחת alpha2CountryCode, • מס' טלפון במסכה. + - MAX (cardIssuingSpCode=2): ניתוב לנקודת הקצה של MAX; תשובה/שגיאה משוקפת. + ולידציות: + • activityTypeCode: מספרים בלבד. + • cardIssuingSpCode: אחד מ־[1,2,3]. + • creditCardSerialId: פורמט hex עם "_" (ESB requestId). + • cardIdServiceProvider: 19 ספרות (לכאל/MAX). + • cardSuffix: 4 ספרות (לישראכרט). + • birthDate: פורמט dd/MM/yyyy (לישראכרט). + • smsByVoice: 0 או 1. + • orderId: UUID. + שגיאות: + • 400 id=7 — שדה חסר/קלט לא תקין; 400 id=19 — שגיאת המרה (mismatch conversion). + • 401 id=5 — הרשאה CA חסרה/פגה. + • 408 id=8 — טיימאאוט מתפעולת (<= 5000ms). + • 404 id=20 — כישלון בפנייה לשירות חיצוני. + • 409 + StatusCode: מיפויי שגיאות מיוחדים בישראכרט (למשל 3/4). + • 500 id=6 — שגיאה פנימית/סדרת 40X/50X לפי מדיניות המיפוי. + security: + - CAAuth: [] + parameters: + - $ref: "#/components/parameters/variousChannelTypeCode" + - $ref: "#/components/parameters/bankNumber" + - $ref: "#/components/parameters/branchNumber" + - $ref: "#/components/parameters/accountNumber" + - $ref: "#/components/parameters/partySerialId" + - $ref: "#/components/parameters/partyShortId" + - $ref: "#/components/parameters/partyIdTypeCode" + - $ref: "#/components/parameters/countryId" + requestBody: + required: true + content: + application/json: + schema: + oneOf: + - $ref: "#/components/schemas/GenerateOtpRequestIsracard" + - $ref: "#/components/schemas/GenerateOtpRequestCal" + - $ref: "#/components/schemas/GenerateOtpRequestMax" + discriminator: + propertyName: cardIssuingSpCode + mapping: + "1": "#/components/schemas/GenerateOtpRequestIsracard" + "2": "#/components/schemas/GenerateOtpRequestMax" + "3": "#/components/schemas/GenerateOtpRequestCal" + examples: + cal_sms: + summary: "כאל – SMS" + value: + activityTypeCode: 101 + cardIssuingSpCode: 3 + creditCardSerialId: "abcdef_1234_abcd_5678_90ab_cdef_1234" + cardIdServiceProvider: "1234567890123456789" + smsByVoice: 0 + orderId: "a3e9f7d2-4b5c-11ee-be56-0242ac120002" + isracard_ivr: + summary: "ישראכרט – IVR" + value: + activityTypeCode: 101 + cardIssuingSpCode: 1 + creditCardSerialId: "abcdef_1234_abcd_5678_90ab_cdef_1234" + cardSuffix: "1234" + birthDate: "15/04/1998" + smsByVoice: 1 + orderId: "a3e9f7d2-4b5c-11ee-be56-0242ac120002" + alpha2CountryCode: "IL" + max_route: + summary: "MAX – ניתוב" + value: + activityTypeCode: 101 + cardIssuingSpCode: 2 + creditCardSerialId: "abcdef_1234_abcd_5678_90ab_cdef_1234" + cardIdServiceProvider: "1234567890123456789" + smsByVoice: 0 + orderId: "a3e9f7d2-4b5c-11ee-be56-0242ac120002" + responses: + "200": + description: "הצלחה – נוצר OTP ונמסר מספר טלפון; ללא errors" + content: + application/json: + schema: + $ref: "#/components/schemas/GenerateOtpResponse" + examples: + cal_success: + summary: "כאל – מספר גלוי" + value: + orderId: "a3e9f7d2-4b5c-11ee-be56-0242ac120002" + otpToken: "OTP123TOKEN" + phoneNumber: "0521234567" + isracard_success: + summary: "ישראכרט – מספר במסכה" + value: + orderId: "a3e9f7d2-4b5c-11ee-be56-0242ac120002" + otpToken: "OTP123TOKEN" + phoneNumber: "050******7" + "400": + description: "בקשה שגויה – שדות חסרים/ולידציה/שגיאת המרה" + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorEnvelope" + examples: + missing_field: + summary: "חסר alpha2CountryCode בישראכרט (id=7)" + value: + orderId: "a3e9f7d2-4b5c-11ee-be56-0242ac120002" + errors: + - id: "7" + message: "Invalid request field [alpha2CountryCode]" + mismatch_conversion: + summary: "partySerialId בכותרת אינו מספרי (id=19)" + value: + errors: + - id: "19" + message: "Cannot assign field [partySerialId] due to a mismatch conversion" + "401": + description: "לא מורשה – הרשאת CA חסרה/פגה (id=5)" + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorEnvelope" + examples: + unauthorized: + value: + errors: + - id: "5" + message: "Authorization not valid/expired" + "404": + description: "נתיב חיצוני לא אותר/כישלון בפנייה (id=20)" + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorEnvelope" + examples: + external_not_found: + value: + errors: + - id: "20" + message: "The server was not able to retrieve the requested page" + "408": + description: "טיימאאוט מתפעלת (≤5000ms) (id=8)" + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorEnvelope" + examples: + timeout: + value: + errors: + - id: "8" + message: "The service is temporarily unavailable" + "409": + description: "התנגשות – מיפוי שגיאות מתפעלת לסטטוס קוד עסקי" + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorEnvelope" + examples: + isracard_no_phone: + summary: "ישראכרט send – undefined_parameter ⇒ StatusCode=4" + value: + orderId: "a3e9f7d2-4b5c-11ee-be56-0242ac120002" + StatusCode: 4 + errors: [] + isracard_attempts_exceeded: + summary: "ישראכרט token/send – 423 ⇒ StatusCode=3" + value: + orderId: "a3e9f7d2-4b5c-11ee-be56-0242ac120002" + StatusCode: 3 + errors: [] + "500": + description: "שגיאה פנימית/מתפעלת – (id=6)" + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorEnvelope" + examples: + internal_error: + value: + errors: + - id: "6" + message: "Internal Server Error" + + /verify-otp: + post: + tags: ["Verify"] + summary: "אימות OTP (otpByToken)" + description: > + אימות OTP לפי חברה מתפעלת: + - כאל (cardIssuingSpCode=3): authenticate לקבלת jwt (ott), ולאחר מכן getEncryptedKey לקבלת encryptionKey. + - ישראכרט (cardIssuingSpCode=1): validate לקבלת tek (encryptionKey) ו-authorizationToken (ott). + - MAX (cardIssuingSpCode=2): ניתוב לנקודת הקצה; תשובת MAX משוקפת. + ולידציות: + • activityTypeCode: מספרים בלבד. + • cardIssuingSpCode: אחד מ־[1,2,3]. + • otpPassword: מספרים בלבד (שמירת אפסים מובילים). + • otpToken: נדרש. + • orderId: UUID. + שגיאות: + • 400 id=7 — חסרים/ולידציה; 400 id=19 — שגיאת המרה. + • 401 id=5 — הרשאה CA חסרה/פגה. + • 403 + StatusCode=33 — ישראכרט: פג תוקף סיסמה (provider 401). + • 408 id=8 — טיימאאוט מתפעלת. + • 409 + StatusCode=7/8 — נסיונות/OTP שגוי (ישראכרט). + • 500 id=6 — שגיאה פנימית/סדרות 40X/50X לפי מדיניות. + security: + - CAAuth: [] + parameters: + - $ref: "#/components/parameters/variousChannelTypeCode" + - $ref: "#/components/parameters/bankNumber" + - $ref: "#/components/parameters/branchNumber" + - $ref: "#/components/parameters/accountNumber" + - $ref: "#/components/parameters/partySerialId" + - $ref: "#/components/parameters/partyShortId" + - $ref: "#/components/parameters/partyIdTypeCode" + - $ref: "#/components/parameters/countryId" + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/VerifyOtpRequest" + examples: + cal_ok: + summary: "כאל – אימות תקין" + value: + activityTypeCode: 101 + cardIssuingSpCode: 3 + otpPassword: "123456" + otpToken: "OTP123TOKEN" + orderId: "a3e9f7d2-4b5c-11ee-be56-0242ac120002" + isracard_ok_leading_zeros: + summary: "ישראכרט – שימור אפסים מובילים" + value: + activityTypeCode: 101 + cardIssuingSpCode: 1 + otpPassword: "000123" + otpToken: "OTP123TOKEN" + orderId: "a3e9f7d2-4b5c-11ee-be56-0242ac120002" + responses: + "200": + description: "הצלחה – אומת OTP והוחזרו ott/encryptionKey; ללא errors" + content: + application/json: + schema: + $ref: "#/components/schemas/VerifyOtpResponse" + examples: + cal_success: + summary: "כאל – jwt + encryptionKey" + value: + orderId: "a3e9f7d2-4b5c-11ee-be56-0242ac120002" + ott: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." + encryptionKey: "K3Y-ABCDEF-123456" + isracard_success: + summary: "ישראכרט – authorizationToken + tek" + value: + orderId: "a3e9f7d2-4b5c-11ee-be56-0242ac120002" + ott: "AUTHTOKEN-XYZ-2048" + encryptionKey: "TEK-WBD-001" + "400": + description: "בקשה שגויה – שדות חסרים/ולידציה/שגיאת המרה" + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorEnvelope" + examples: + missing_otpPassword: + summary: "חסר otpPassword (id=7)" + value: + errors: + - id: "7" + message: "Invalid request field [otpPassword]" + invalid_uuid_orderId: + summary: "orderId אינו UUID (id=7)" + value: + errors: + - id: "7" + message: "Invalid request field [orderId]" + "401": + description: "לא מורשה – הרשאת CA חסרה/פגה (id=5)" + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorEnvelope" + "403": + description: "אסור – מיפוי מתפעלת (ישראכרט 401 ⇒ StatusCode=33)" + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorEnvelope" + examples: + isracard_expired: + value: + orderId: "a3e9f7d2-4b5c-11ee-be56-0242ac120002" + StatusCode: 33 + errors: [] + "404": + description: "נתיב חיצוני לא אותר/כישלון בפנייה (id=20)" + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorEnvelope" + "408": + description: "טיימאאוט מתפעלת (≤5000ms) (id=8)" + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorEnvelope" + examples: + cal_auth_timeout: + summary: "טיימאאוט כאל – Authenticate" + value: + errors: + - id: "8" + message: "The service is temporarily unavailable" + "409": + description: "התנגשות – OTP שגוי/חריגה במספר ניסיונות (ישראכרט)" + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorEnvelope" + examples: + invalid_otp_attempt: + summary: "ישראכרט validate – responseCode=invalid_otp_attempt ⇒ StatusCode=7" + value: + orderId: "a3e9f7d2-4b5c-11ee-be56-0242ac120002" + StatusCode: 7 + errors: [] + too_many_attempts: + summary: "ישראכרט validate – 423 ⇒ StatusCode=8" + value: + orderId: "a3e9f7d2-4b5c-11ee-be56-0242ac120002" + StatusCode: 8 + errors: [] + "500": + description: "שגיאה פנימית/מתפעלת – (id=6)" + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorEnvelope" + +components: + securitySchemes: + CAAuth: + type: apiKey + in: header + name: Authorization + description: "כותרת הרשאה CA רמה 2 (ערך תקין נדרש לכל הקריאות)." + parameters: + variousChannelTypeCode: + name: variousChannelTypeCode + in: header + required: true + description: "קוד ערוץ שירות (שמירת אפסים מובילים)." + schema: + type: string + pattern: "^[0-9]{1,5}$" + example: "10001" + bankNumber: + name: bankNumber + in: header + required: true + description: "מספר בנק (3 ספרות; שמירת אפסים מובילים)." + schema: + type: string + pattern: "^[0-9]{3}$" + example: "012" + branchNumber: + name: branchNumber + in: header + required: true + description: "מספר סניף (3 ספרות)." + schema: + type: string + pattern: "^[0-9]{3}$" + example: "123" + accountNumber: + name: accountNumber + in: header + required: true + description: "מספר חשבון (7 ספרות)." + schema: + type: string + pattern: "^[0-9]{7}$" + example: "1234567" + partySerialId: + name: partySerialId + in: header + required: true + description: "ספרור לקוח (11 ספרות). אם אינו מספרי ⇒ 400 id=19." + schema: + type: string + pattern: "^[0-9]{11}$" + example: "12345678901" + partyShortId: + name: partyShortId + in: header + required: true + description: "מזהה לקוח (9 ספרות)." + schema: + type: string + pattern: "^[0-9]{9}$" + example: "012345678" + partyIdTypeCode: + name: partyIdTypeCode + in: header + required: true + description: "סוג מסמך מזהה (מספרים בלבד)." + schema: + type: string + pattern: "^[0-9]{1,5}$" + example: "1" + countryId: + name: countryId + in: header + required: true + description: "קוד ארץ (3 ספרות; לדוגמה 212⇒IL)." + schema: + type: string + pattern: "^[0-9]{3}$" + example: "212" + schemas: + GenerateOtpRequestBase: + type: object + properties: + activityTypeCode: + type: integer + description: "קוד סוג בקשה פנימי (מספרים בלבד; לדוגמה 101)." + example: 101 + cardIssuingSpCode: + type: integer + description: "קוד חברה מתפעלת: 1=ישראכרט, 2=MAX, 3=כאל." + enum: [1, 2, 3] + creditCardSerialId: + type: string + description: "מזהה כרטיס פועלים (פורמט ESB hex עם '_' – xxxxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx)." + pattern: "^[0-9a-f]{6}_[0-9a-f]{4}(?:_[0-9a-f]{4}){5}$" + example: "abcdef_1234_abcd_5678_90ab_cdef_1234" + smsByVoice: + type: integer + description: "שיטת מסירה: 0=SMS, 1=IVR." + enum: [0, 1] + orderId: + type: string + format: uuid + description: "מזהה בקשה (UUID)." + example: "a3e9f7d2-4b5c-11ee-be56-0242ac120002" + required: ["activityTypeCode", "cardIssuingSpCode", "creditCardSerialId", "smsByVoice", "orderId"] + GenerateOtpRequestCal: + allOf: + - $ref: "#/components/schemas/GenerateOtpRequestBase" + - type: object + properties: + cardIssuingSpCode: + type: integer + enum: [3] + cardIdServiceProvider: + type: string + description: "מזהה כרטיס מתפעלת (19 ספרות; חובה לכאל)." + pattern: "^[0-9]{19}$" + example: "1234567890123456789" + required: ["cardIdServiceProvider"] + GenerateOtpRequestMax: + allOf: + - $ref: "#/components/schemas/GenerateOtpRequestBase" + - type: object + properties: + cardIssuingSpCode: + type: integer + enum: [2] + cardIdServiceProvider: + type: string + description: "מזהה כרטיס מתפעלת (19 ספרות; נדרש ל־MAX)." + pattern: "^[0-9]{19}$" + example: "1234567890123456789" + required: ["cardIdServiceProvider"] + GenerateOtpRequestIsracard: + allOf: + - $ref: "#/components/schemas/GenerateOtpRequestBase" + - type: object + properties: + cardIssuingSpCode: + type: integer + enum: [1] + cardSuffix: + type: string + description: "4 ספרות אחרונות של הכרטיס (חובה לישראכרט)." + pattern: "^[0-9]{4}$" + example: "1234" + birthDate: + type: string + description: "תאריך לידה בפורמט dd/MM/yyyy (חובה לישראכרט)." + pattern: "^\\d{2}/\\d{2}/\\d{4}$" + example: "15/04/1998" + alpha2CountryCode: + type: string + description: "קוד ארץ ISO Alpha-2 (חובה לישראכרט; לדוגמה IL)." + pattern: "^[A-Z]{2}$" + example: "IL" + required: ["cardSuffix", "birthDate", "alpha2CountryCode"] + GenerateOtpResponse: + type: object + description: "תשובת הצלחה להקמת OTP." + properties: + orderId: + type: string + format: uuid + description: "מזהה הבקשה כפי שהתקבל בקלט." + otpToken: + type: string + description: "מזהה OTP כפי שהתקבל מהמתפעלת." + phoneNumber: + type: string + description: "מספר הטלפון אליו נשלח הקוד (בישראכרט – מחרוזת באורך 10, maskedCellphoneNumber)." + StatusCode: + type: integer + description: "קוד סטטוס עסקי (אופציונלי; בשגיאות מיפוי מתפעלת)." + errors: + type: array + items: + $ref: "#/components/schemas/ErrorItem" + description: "רשימת שגיאות (במצב הצלחה אמורה להיות ריקה או לא להופיע)." + required: ["orderId", "otpToken", "phoneNumber"] + VerifyOtpRequest: + type: object + properties: + activityTypeCode: + type: integer + description: "קוד סוג בקשה פנימי." + example: 101 + cardIssuingSpCode: + type: integer + description: "קוד חברה מתפעלת: 1=ישראכרט, 2=MAX, 3=כאל." + enum: [1, 2, 3] + otpPassword: + type: string + description: "קוד OTP (מספרים בלבד; נשמרים אפסים מובילים)." + pattern: "^[0-9]+$" + example: "000123" + otpToken: + type: string + description: "מזהה OTP שהוחזר בשלב ההקמה." + example: "OTP123TOKEN" + orderId: + type: string + format: uuid + description: "מזהה בקשה (UUID)." + example: "a3e9f7d2-4b5c-11ee-be56-0242ac120002" + required: ["activityTypeCode", "cardIssuingSpCode", "otpPassword", "otpToken", "orderId"] + VerifyOtpResponse: + type: object + description: "תשובת הצלחה לאימות OTP." + properties: + orderId: + type: string + format: uuid + description: "מזהה הבקשה כפי שהתקבל בקלט." + ott: + type: string + description: "מזהה תהליך שנוצר ע״י המתפעלת (CAL: jwt; ישראכרט: authorizationToken)." + encryptionKey: + type: string + description: "מפתח הצפנה (CAL: encryptionKey מ־GetEncryptedKey; ישראכרט: tek)." + StatusCode: + type: integer + description: "קוד סטטוס עסקי (אופציונלי; בשגיאות מיפוי מתפעלת)." + errors: + type: array + items: + $ref: "#/components/schemas/ErrorItem" + description: "רשימת שגיאות (במצב הצלחה אמורה להיות ריקה או לא להופיע)." + required: ["orderId", "ott", "encryptionKey"] + ErrorItem: + type: object + properties: + id: + type: string + description: "מזהה השגיאה לפי נספח." + example: "7" + message: + type: string + description: "הודעת השגיאה." + example: "Invalid request field [@@]" + ErrorEnvelope: + type: object + description: "מבנה תשובה בשגיאה." + properties: + orderId: + type: string + format: uuid + description: "מזהה בקשה (אם זמין)." + StatusCode: + type: integer + description: "קוד סטטוס עסקי (במיפויי שגיאות מתפעלת)." + errors: + type: array + items: + $ref: "#/components/schemas/ErrorItem" + description: "רשימת שגיאות גלובלית." + data: + type: object + description: "מיפוי שדה קלט לרשימת שגיאות." + additionalProperties: + type: array + items: + $ref: "#/components/schemas/ErrorItem" + required: ["errors"] + +x-tlsMinimumVersion: "1.2" +x-integrations: + cal: + baseUrl: "https://tst-api.cal-online.co.il/PartnerAuthentication.Api" + sendOtp: + method: "POST" + path: "/api/SendOtp/sendOTP" + headers: + - "x-access-token: <תקין>" + requestMapping: + CustomerDetails.idNumber: "partyShortId (HEADER)" + CustomerDetails.CustomerIdType: "partyIdTypeCode (HEADER)" + cardInfo.cardId: "cardIdServiceProvider (BODY)" + message.smsTemplate: "0" + message.smsSender: "" + message.smsByVoice: "smsByVoice (BODY)" + timeoutMs: 5000 + successCriteria: "HTTP 200 + StatusCode=1" + responseMapping: + otpToken: "result.token" + phoneNumber: "result.phoneNumber" + authenticate: + method: "POST" + path: "/api/Authenticate/authenticate" + headers: + - "x-access-token: <תקין>" + body: + token: "otpToken" + password: "otpPassword" + timeoutMs: 5000 + successCriteria: "HTTP 200 + StatusCode=1" + responseMapping: + ott: "result.jwt" + getEncryptedKey: + method: "POST" + path: "/api/GetEncryptedKey/getEncryptedKey" + headers: + - "x-access-token: <תקין>" + - "authorization: " + timeoutMs: 5000 + successCriteria: "HTTP 200 + StatusCode=1" + responseMapping: + encryptionKey: "result.encryptionKey" + isracard: + baseUrl: "https://preprod.api.isracard.co.il/isracard/preprod" + tokenByIdAndDob: + method: "POST" + path: "/authorization/token/v1.2.0/byIdAndDateOfBirth" + bodyMapping: + tokenPostRequest.requestId: "orderId" + tokenPostRequest.requestTimeStamp: "yyyy-MM-dd-HH.mm.ss.SSSSSS (Asia/Jerusalem)" + tokenPostRequest.idNumber: "partyShortId (HEADER)" + tokenPostRequest.idCode: "partyIdTypeCode (HEADER)" + tokenPostRequest.cardLastFourDigits: "cardSuffix" + tokenPostRequest.companyCode: "B (קבוע)" + tokenPostRequest.dateOfBirth: "CYYMMDD (מירוץ מתאריך לידה)" + tokenPostRequest.activityType: "activityTypeCode" + tokenPostRequest.alpha2CountryCode: "alpha2CountryCode (מומר מ-countryId=212⇒IL)" + tokenPostRequest.bankCode: "012 (קבוע)" + timeoutMs: 5000 + successCriteria: "HTTP 200" + responseMapping: + token: "tokenPostResponse.token" + sendOtpByToken: + method: "POST" + path: "/authorization/otpByToken/v1.3.0/send" + bodyMapping: + requestGeneralHeader.requestId: "orderId" + tokenRequest.authorizationToken: "" + deliveryMethod: "smsByVoice (0=SMS,1=IVR)" + timeoutMs: 5000 + successCriteria: "HTTP 200" + responseMapping: + otpToken: "" + phoneNumber: "SendOtpResponse.PhoneNumber.maskedCellphoneNumber (אורך 10)" + errorMapping: + "404 + undefined_parameter": "409 + StatusCode=4" + "423": "409 + StatusCode=3" + "40X/50X": "500 + id=6" + validateOtpByToken: + method: "POST" + path: "/authorization/otpByToken/v1.4.0/validate" + bodyMapping: + requestGeneralHeader.requestId: "orderId" + tokenRequest.authorizationToken: "otpToken" + tokenRequest.otp: "otpPassword" + timeoutMs: 5000 + successCriteria: "HTTP 200" + responseMapping: + ott: "TokenResponse.authorizationToken" + encryptionKey: "TokenResponse.tek" + errorMapping: + "200 + responseCode=invalid_otp_attempt": "409 + StatusCode=7" + "423": "409 + StatusCode=8" + "401": "403 + StatusCode=33" + "40X/50X": "500 + id=6" + +x-errorCatalog: + - { id: "1", httpCode: 200, message: "Success" } + - { id: "4", httpCode: 400, message: "Missing field\\ incorrect input" } + - { id: "5", httpCode: 401, message: "Authorization not valid/expired" } + - { id: "6", httpCode: 500, message: "Internal Server Error" } + - { id: "7", httpCode: 400, message: "Invalid request field [@@]" } + - { id: "8", httpCode: 408, message: "The service is temporarily unavailable" } + - { id: "19", httpCode: 400, message: "Cannot assign field [] due to a mismatch conversion" } + - { id: "20", httpCode: 404, message: "The server was not able to retrieve the requested page" } + - { id: "21", httpCode: 500, message: "Failed to create a record" } + - { id: "22", httpCode: 500, message: "Failed to update a record" } +