מקרה בוחן · מרקטפלייס ותשלומים · 2026

קופה אחת שמשלמת לכל ספק בנפרד

רוכשי דירות חדשות של יזמית נדל״ן ישראלית גדולה יכולים עכשיו לרהט ולשדרג את הבית מספקים נבחרים, בחנות אחת בעברית. הם מזינים כרטיס אשראי פעם אחת, והמערכת מפצלת את התשלום בין הספקים, מסנכרנת כל לילה את הקטלוגים של כולם, ונותנת לצוות של היזמית מערכת ניהול אחת לכל זה.

⁦.NET 8⁩ / ⁦ASP.NET Core⁩EF Core · SQL ServerReact · TypeScript · VitePayment marketplace APIWindows Service workerS3 · SMTP · SMS · CRM
לקוח
יזמית נדל״ן למגורים ישראלית גדולה (חסוי)
התפקיד שלי
ראש צוות, ארכיטקט ומפתח בפועל, בכל שלוש האפליקציות
לוח זמנים
יולי–אוגוסט 2026 · כ־⁠5 שבועות עד מערכת מלאה בסביבת QA
סטטוס
נמסר · עלייה לאוויר אצל הלקוח
במבט אחד
1 עד Nהזנת כרטיס אחת, ואחריה חיוב נפרד לחלק של כל ספק
≈5שבועות עד כל המודולים המתוכננים מקצה לקצה, מול תכנית של 10 שבועות
5,000 עד 1שורות התראה על עמודה חסרה אחת בפיד, עכשיו מקובצות לפי סיבה
0שדות מה־⁠callback של התשלום שנחשבים אמינים. כל עסקה נקראת מחדש מהספק.
404בדיקות אוטומטיות ב־⁠Backend
90נקודות קצה ב־⁠API ציבורי וב־⁠API ניהול
25בדיקות פיד מקודדות, לפידים ב־⁠Excel, HTML ו־⁠CSV
3אפליקציות (Backend, חנות ומערכת ניהול) ב־⁠30 ימים קלנדריים של קומיטים
הבעיה

הרבה ספקים, רוכש אחד, כרטיס אחד

היזמית רצתה להציע לרוכשי הדירות שלה קטלוג נבחר: מטבחים, תאורה, מכשירי חשמל ועבודות גמר, שנמכרים על ידי ספקים עצמאיים, במחירים ששונים לפני מסירת הדירה ואחריה. זה יוצר שלוש בעיות בבת אחת. כל ספק מפרסם את המוצרים שלו בגיליון או בטבלת אינטרנט משלו, ולכן צריך לבנות את הקטלוג מחדש כל לילה מקבצים שמשתנים, בלי לאבד את השינויים שהצוות של היזמית עשה. הרוכשים צריכים להתחבר מול ה־⁠CRM של היזמית ולראות רק את מה שרלוונטי לדירה שלהם. ועסקה אצל ספק התשלום שייכת למוכר אחד בלבד, כך שסל עם שלושה ספקים לא יכול להיות חיוב אחד פשוט.

מה היה באחריותי

מהתכנית ועד מערכת עובדת ב־⁠QA

  • כתבתי את תכנית הפיתוח של ה־⁠Backend מתוך האפיון של הלקוח, וקבעתי את הארכיטקטורה השכבתית: שני APIs מעל ליבה משותפת, ו־⁠worker נפרד לסנכרון.
  • פיתחתי בעצמי את רוב ה־⁠Backend, מערכת הניהול והחנות, והובלתי את הצוות בסבבי הבדיקות מול הבודקים והמנהל.
  • תכננתי עם ספק התשלום את זרימת פיצול התשלום, ואימתתי אותה מההתחלה ועד הסוף בסביבת ה־⁠sandbox שלהם לפני שהכנסתי אותה למוצר.
  • בניתי את מנוע הפידים: שלושה קוראים, 25 בדיקות מקודדות, עדכון שמכבד שינויים מקומיים, מחיקה לוגית ודוח כשל בעברית.
  • אבחנתי את תקלות האינטגרציה (שרת הדואר, קבצי פיד פגומים, callbacks כפולים) ותיעדתי כל אחת לצוות התפעול.
ארכיטקטורה

שני APIs, ליבה משותפת אחת ו־⁠worker בצד

התרשים רחב מהמסך: החליקו הצידה לצפייה בכולו →

ה־⁠API הציבורי וה־⁠API הניהולי רצים כשני hosts נפרדים, כך שהצד שמול הרוכשים לא חושף אף נקודת קצה של ניהול. שניהם, וגם ה־⁠worker, רושמים את אותה ליבה דרך קריאת רישום משותפת אחת, ולכן החוקים העסקיים לא יכולים להתפצל ביניהם. כל שירות חיצוני יושב מאחורי interface, והגדרה ריקה בוחרת stub שנכשל בצורה בטוחה, וכך מחשבי פיתוח לא נוגעים בתשלומים, SMS או דואר אמיתיים.

החלטות תכנון

הפיד הוא המקור, הסל הוא האמת

אישור מסגרת אחד, חיוב לכל ספק

הכרטיס של הרוכש מאושר פעם אחת על סכום הסל, מול המוכר של הפלטפורמה עצמה. אחרי האישור נוצרת ההזמנה, והחלק של כל ספק נגבה בנפרד מול חשבון המוכר שלו. חיוב שנכשל משאיר את ההזמנה ב־⁠Pending להתאמה, ולא מוחק הזמנה שהרוכש כבר שילם עליה. המחיר: כל ספק צריך KYC מלא אצל ספק התשלום, ולכן דגל אחד מאפשר לחזור לחיוב של כל הסל ולהתחשבנות עם הספקים מחוץ למערכת.

לא סומכים על ה־⁠callback

ה־⁠callback של התשלום אנונימי, וכל אחד יכול לשלוח אותו. הוא משמש רק כהתראה: השרת קורא את העסקה מחדש מספק התשלום, מתאים את האסמכתא שהוא עצמו הנפיק לסל, בודק שהסכום שווה לסכום הסל, ובמשלוח חוזר מחזיר את ההזמנה הקיימת. פרטי ההזמנה נשמרים על הסל לפני ההפניה לתשלום, כך שה־⁠callback אף פעם לא צריך לשאת אותם.

שינויים מקומיים לצד הפיד, לא בתוכו

הצוות יכול לדרוס חמישה שדות של מוצר ספק (תיאור, שני המחירים, סטטוס פעיל וקטגוריה). הדריסות נשמרות בטבלה נפרדת, ובכל סנכרון ובכל עריכה הן מחושבות לעמודות Effective*. החנות קוראת רק את העמודות האלה, השינוי חל מיד, והוא שורד את הייבוא של הלילה הבא. המחיר: כל מסלול כתיבה חייב להפעיל את החישוב, והבדיקות אוכפות את זה.

מחיקה לוגית ותמונת מצב לכל הזמנה

מוצר שנעלם מהפיד מוסתר ולא נמחק, ואם הוא חוזר הוא חוזר עם הדריסות שלו. כל הזמנה שומרת תמונת מצב מלאה של פריטים, מחירים, ספקים, וריאנטים וכתובות, כך שהיסטוריית ההזמנות נשארת נכונה גם כשהקטלוג משתנה.

ה־⁠worker הוא Windows Service ולא אתר

הסנכרון הלילי רץ כתהליך עצמאי עם הגדרות משלו, מחוץ ל־⁠IIS, כך ש־⁠app pool שממחזר את עצמו או נרדם לא יכול לדלג על לילה. ייבואים של אותו ספק רצים אחד אחרי השני ונשמרים בטרנזקציה אחת, כך שסנכרון ידני שמתנגש בריצה הלילית לא יכול להכניס מוצר פעמיים או להשאיר חצי קטלוג.

יומן הנדסי

מה נשבר ואיך תוקן

רוב העבודה הקשה הייתה בקצוות: ספק התשלום, שרת הדואר של הלקוח, וקבצי ספקים שאף אחד לא שולט בהם. מבחר:

22 ביולי

דפי תוכן יכלו להכיל סקריפט

תוכן עשיר שהוזן במערכת הניהול הוצג בחנות כ־⁠HTML גולמי, פתח ל־⁠Stored XSS.

ניקוי ה־⁠HTML של התוכן לפני ההצגה, באותו שבוע שבו החנות נכנסה לריפו.

22 ביולי

מחיקה רכה שברה ייחודיות

אינדקסים ייחודיים על שמות ו־⁠slugs ספרו גם שורות שנמחקו, כך שקטגוריה מחוקה חסמה קטגוריה חדשה באותו שם.

מעבר לאינדקסים ייחודיים מסוננים שמתעלמים משורות מחוקות, ותיקון באגים מאומתים שנמצאו בסקירה מההתחלה ועד הסוף של 7 זרימות ניהול.

⁦2–5⁩ באוגוסט

הדואר נחסם, והאבחנה הראשונה הייתה שגויה

שרת הדואר של הלקוח התחיל לדחות את האפליקציה כשולח לא מורשה. האבחנה הראשונה, תעודת TLS חסרה, התבררה כשגויה.

הסיבה האמיתית הייתה כתובת ה־⁠IP של השרת: ברגע שהיא נוספה לרשימת ההיתרים, הדואר יצא בלי שום תעודה. תיעדתי למה שאר ההגדרות חייבות להישאר ריקות, הוספתי סקריפט בדיקת SMTP שעוצר לפני השליחה, ונקודת קצה לאבחון (למנהלים בלבד) ששולחת דרך המסלול האמיתי ומדווחת מי ענה.

⁦3–4⁩ באוגוסט

עסקה אחת, מוכר אחד

ספק התשלום מקשר כל עסקה למוכר אחד בדיוק, ולכן סל עם כמה ספקים לא יכול להיות חיוב אחד.

סיכמתי עם ספק התשלום זרימה דו־שלבית (אישור מסגרת ואז multi-capture) והרצתי אותה מההתחלה ועד הסוף ב־⁠sandbox: אישור אחד ושני חיובים לשני ספקים. ההרצה מדדה את מה שהתיעוד השאיר פתוח: סכומים באגורות, אישור מסגרת שמחזיק 168 שעות, מגבלה של 10 קריאות ל־⁠10 שניות, ועסקת מקור שנשארת ”authorized” אחרי חיוב חלקי.

4 באוגוסט

אותו תשלום, פעמיים

ספק התשלום שולח callback מחדש עד 3 פעמים, ולכן תשלום אחד יכול להגיע יותר מפעם אחת.

אינדקס ייחודי על מזהה העסקה ו־⁠callback אידמפוטנטי: משלוח חוזר מחזיר את ההזמנה שכבר קיימת.

6 באוגוסט

קיר של שגיאות זהות

פיד שחסרה בו עמודת חובה אחת יצר שגיאה לכל שורה. אלפי שורות זהות הסתירו כל תקלה אחרת בריצה, ועד שמישהו הסתכל, הקובץ של הספק כבר השתנה.

דוח הכשל בעברית מקבץ עכשיו את השגיאות לפי סיבה, עם מספר שורות ודוגמאות של מזהי מוצר, וכל ריצה שומרת עותק משלה של קובץ המקור ומקשרת אליו מהדוח.

⁦11–17⁩ באוגוסט

התחברות בטלפון, בלי לחשוף מי רוכש

הלקוח העביר את התחברות הרוכשים מתעודת זהות למספר טלפון. חיפוש טלפון לפני שנשלח קוד יכול לשמש כדי לגלות מי רוכש.

מעבר לזיהוי לפי טלפון ב־⁠Backend ובחנות, ומגבלת ניסיונות ונעילה לכל מספר בשלב החיפוש, בנפרד מהמגבלה על ניחוש הקוד.

18 באוגוסט

קובץ פגום ברח מהייבוא

ב־⁠QA, גיליון פגום זרק חריגה של ה־⁠framework ששמה זהה לשם של חריגת הפיד של המנוע עצמו. היא חמקה מה־⁠handler: לא נכתב דוח, לא יצאה התראה, ו־⁠stack trace הגיע לתשובת ה־⁠API.

תפיסה מפורשת של החריגה. קובץ פגום מייצר עכשיו דוח סנכרון כושל והתראה, והקטלוג הקיים נשאר באוויר.

צעד אחרי צעד

הזנת כרטיס אחת, שלושה ספקים

המחשה של זרימת התשלום עם סכומים וספקים בדויים. אין כאן נתונים או קוד של הלקוח. עברו בין השלבים כדי לראות איפה כל בדיקה קורית.

תוצאה

איפה זה נחת

תחום
לפני
אחרי
תשלום לספקים
עסקה אחת לכל מוכר; התחשבנות ידנית עם הספקים מחוץ למערכת
הזנת כרטיס אחת, חיוב אוטומטי לכל ספק, וסטטוס לכל פיצול לצורך התאמה
תחזוקת קטלוג
הקלדה ידנית של גיליונות הספקים (כ־⁠⁦1–2⁩ שעות לספק בכל עדכון, הערכה)
ייבוא לילי של פידים ב־⁠Excel, HTML ו־⁠CSV עם 25 בדיקות מקודדות, וסנכרון לפי דרישה
התראת כשל בפיד
שורה לכל שורה שגויה, אלפים בגלל עמודה חסרה אחת
שורה אחת לכל סיבה, עם ספירה, דוגמאות וקובץ המקור השמור
שינויי מחיר מקומיים
נדרסים בייבוא הבא
חמישה שדות ניתנים לדריסה, חלים מיד ונשמרים בכל סנכרון
Callback של התשלום
נקודת קצה ציבורית שכל אחד יכול לשלוח אליה
אימות מחדש מול ספק התשלום, התאמה לסל ולסכום, אידמפוטנטי
תקלות דואר
עד יום עבודה במרדף אחרי הסיבה הלא נכונה (הערכה)
בדיקה בלחיצה אחת במערכת הניהול שמצביעה על השכבה שנכשלה
אספקה
תכנית של 10 שבועות
כל המודולים המתוכננים מההתחלה ועד הסוף ב־⁠QA תוך כ־⁠5 שבועות; העלייה לאוויר ממתינה לצד הלקוח

מה שנשאר פתוח במסירה, כולו בצד הלקוח: KYC לחשבון המוכר של כל ספק, אחוז העמלה, וכתובת callback ציבורית שרשומה אצל ספק התשלום.

טכנולוגיות

מחסנית טכנולוגית

Backend
⁦.NET 8⁩, ⁦ASP.NET Core⁩, EF Core, AutoMapper, JWT, NLog
נתונים
SQL Server, 25 טבלאות, 22 migrations, אינדקסים ייחודיים מסוננים
צד לקוח
React 18, TypeScript, Vite, Redux Toolkit, Ant Design, i18next (680 מחרוזות בעברית)
פידים
ClosedXML, קוראי טבלת HTML ו־⁠CSV, worker כ־⁠Windows Service
אינטגרציות
API מרקטפלייס של ספק תשלום, CRM, שני שערי SMS, שרת SMTP, S3
איכות
404 בדיקות xUnit, ענפי dev / QA / staging / prod, לוגים בפורמט SIEM

שיחת אבחון חינם · 30 דקות · ללא התחייבות

הביאו תהליך אחד. קבלו תוכנית ומספר לשפר.

כתבו בכמה שורות: איזה תהליך או מערכת, מה כואב היום (זמן, טעויות, עלויות או פיילוט AI שנתקע) ומי עובד עם זה. אחרי שיחה קצרה מקבלים תוך כ־3 ימים תוכנית כתובה והצעת מחיר סגורה.

לשיחת אבחון חינםafif.mansour@gmail.com

נפתח מייל מוכן מראש · מענה תוך יום עסקים

ה־AI קורא. הקוד סופר.

כל הפרויקטים