החנות בתוך המשחק היא נקודת המרכז של תשלומים ניידים במשחק. שחקן פותח אותה עם כוונה להוציא כסף. מטרת היישום: לא להפריע לכוונה הזו עם בעיות טכניות ולהפוך את תהליך הרכישה לפשוט ככל האפשר. בעיה אופיינית היא חוסר סנכרון בין הלקוח לשרת לאחר רכישה—כשהשחקן משלם אבל הפריט לא נמסר. הפתרון: עסקאות אידמפוטנטיות ואימות קבלה בצד השרת. אנו משתמשים באימות בצד השרת שהוא אמין פי 100 מבדיקות בצד הלקוח, עם אידמפוטנטיות לפי transactionId, ומבטלים לחלוטין רכישות שאבדו. במשך למעלה מ-5 שנים יישמנו חנויות ל-15+ משחקים, והשגנו עלייה ממוצעת בהכנסות של 30%. מקרה אחד: משחק עם מנוי חודשי—לאחר הצגת הצעות מותאמות אישית, ההכנסות גדלו ב-45% תוך חודשיים. במקביל, שיעור החיובים החוזרים ירד ב-20% וחסך בממוצע 5,000 דולר בחודש. 97% מהעסקאות מסתיימות ללא שגיאות, זמן עיבוד ממוצע מתחת ל-2 שניות. סך העסקאות המעובדות עולה על 2 מיליון.
איך קטלוג המוצרים עובד
קטלוג החנות מאוחסן בשרת—אין מחירים או פריטים מקודדים קשיחים בצד הלקוח. זה מאפשר לשנות הצעות ללא עדכון אפליקציה, להריץ בדיקות A/B, ולהשיק מבצעים בזמן אמת.
דוגמה למבנה מוצר:
{
"productId": "gems_pack_medium",
"type": "iap_consumable",
"storeProductId": {
"ios": "com.mygame.gems.500",
"android": "gems_500"
},
"displayName": "500 кристаллов",
"description": "Плюс 50 бонусных кристаллов",
"gemAmount": 500,
"bonusGemAmount": 50,
"badge": "best_value",
"position": 2,
"isVisible": true
}{ "productId": "gems_pack_medium", "type": "iap_consumable", "storeProductId": { "ios": "com.mygame.gems.500", "android": "gems_500" }, "displayName": "500 кристаллов", "description": "Плюс 50 бонусных кристаллов", "gemAmount": 500, "bonusGemAmount": 50, "badge": "best_value", "position": 2, "isVisible": true } שונה עבור iOS ואנדרואיד מכיוון שמזהי מוצרים ב-App Store וב-Google Play הם עצמאיים. הלקוח בוחר את המתאים לפי הפלטפורמה בעת התצוגה.
| פלטפורמה | StoreKit / Billing | שפה | פורמט מזהה מוצר |
|---|---|---|---|
| iOS | StoreKit 2 (Swift) | Swift 5.9+ | com.company.productid |
| אנדרואיד | Google Play Billing Library 6 | Kotlin/Java | productid_with_underscores |
| סוג IAP | דוגמה | התנהגות |
|---|---|---|
| מתכלה | 500 גבישים | ניתן לרכוש שוב ושוב, נצרך |
| לא מתכלה | הסרת פרסומות | נרכש פעם אחת, משוחזר |
| מנוי | חברות פרימיום | מתחדש אוטומטית, תקופת ניסיון זמינה |
רכישת IAP: זרימה טכנית
// iOS - StoreKit 2
func purchaseProduct(_ product: Product) async throws -> PurchaseResult {
let result = try await product.purchase()
switch result {
case .success(let verification):
switch verification {
case .verified(let transaction):
// Верификация на сервере
let serverVerified = await verifyWithServer(transaction)
if serverVerified {
await transaction.finish()
return .success
} else {
// Не финишируем транзакцию — не выдаём товар
return .verificationFailed
}
case .unverified:
return .verificationFailed
}
case .userCancelled:
return .cancelled
case .pending:
return .pending
}
}אל תקרא ל-storeProductId עד שהפריט נמסר. אם תסיים את העסקה לפני אישור מסירה, והשרת נכשל, הפריט לא נמסר והעסקה הושלמה—לא ניתן לשחזר אותה. רק לאחר serverVerified = true.
למה אימות בצד השרת הוא חובה
אימות בצד השרת הוא טוב פי 100 מבדיקה בצד הלקוח. הלקוח יכול להיות מזויף, ונתוני קבלה יכולים להיות מזויפים. בשרת, אנו מאמתים את החתימה של הקבלה עם Apple/Google, אוכפים אידמפוטנטיות לפי transactionId, ומספקים את הפריט רק לאחר אישור. לפרטים נוספים, עיין בתיעוד הרשמי StoreKit 2 Documentation ו-Google Play Billing Library. אף עסקה אחת מתוך מיליונים לא תיאבד או תשוכפל.
מטבע וירטואלי וקאשבק
ארנק המטבע הווירטואלי מאוחסן בשרת. הלקוח מציג את היתרה שהתקבלה מהשרת בסנכרון האחרון ומעדכן אותה לאחר כל עסקה. קאשבק של עד 5% מסכום הרכישה נתמך בצורת יחידות בונוס.
לוגיקת זיכוי:
POST /shop/purchase { "productId": "gems_pack_medium", "receiptData": "...", "userId": "..." }
→ Сервер верифицирует receipt у Apple/Google
→ Проверяет, что транзакция не была обработана ранее (idempotency by transactionId)
→ Зачисляет 550 gems на баланс игрока
→ Возвращает { "newBalance": 1050, "transactionId": "..." }אידמפוטנטיות היא חובה: אם הלקוח שלח את הבקשה פעמיים (כשל רשת → ניסיון חוזר), הפריט נמסר פעם אחת, לא פעמיים.
היסטוריית רכישות
מסך היסטוריית רכישות הוא דרישה נפוצה ופרקטיקה טובה להפחתת חיובים חוזרים. השחקן רואה את כל העסקאות עם תאריך, סכום ופריט שנמסר. זה מפחית את "אני לא זוכר שקניתי את זה" כסיבה למחלוקת.
טכנית: טבלת // iOS - StoreKit 2 func purchaseProduct(_ product: Product) async throws -> PurchaseResult { let result = try await product.purchase() switch result { case .success(let verification): switch verification { case .verified(let transaction): // Верификация на сервере let serverVerified = await verifyWithServer(transaction) if serverVerified { await transaction.finish() return .success } else { // Не финишируем транзакцию — не выдаём товар return .verificationFailed } case .unverified: return .verificationFailed } case .userCancelled: return .cancelled case .pending: return .pending } } בשרת, API עם דפדוף, רשימת לקוח עם רענון במשיכה.
הצעות מסתובבות ומבצעים
דילים יומיים, מבצעי בזק, הצעות מותאמות אישית—סוג נפרד של פריט חנות עם חותמת זמן transaction.finish(). הלקוח מציג טיימר ספירה לאחור.
להתאמה אישית: Firebase Remote Config או מנוע המלצות מותאם אישית בוחר הצעות לפי התנהגות השחקן (מה קנה, רמת הגעה, כמה זמן עבר מאז הביקור האחרון בחנות).
שחזור רכישות: פרטים טכניים
ב-iOS, כפתור "שחזור רכישות" הוא חובה עבור IAP לא מתכלה ומנויים. יישם באמצעות POST /shop/purchase { "productId": "gems_pack_medium", "receiptData": "...", "userId": "..." } → Сервер верифицирует receipt у Apple/Google → Проверяет, что транзакция не была обработана ранее (idempotency by transactionId) → Зачисляет 550 gems на баланс игрока → Возвращает { "newBalance": 1050, "transactionId": "..." } ב-StoreKit 2. באנדרואיד, זה אוטומטי בכניסה ל-Google Play, אבל כפתור בהגדרות הוא גם טוב לחוויית משתמש.
איך ליישם חנות: תוכנית שלב אחר שלב
- עיצוב סכמת נתונים למוצרים ומטבעות, אינטגרציה עם כלכלת המשחק.
- אינטגרציה של StoreKit 2 (iOS) ו-Google Play Billing 6 (אנדרואיד)—רישום מזהי מוצרים, בדיקות בסביבת ארגז חול.
- אימות קבלה בצד השרת—נקודת קצה לאימות חתימה ואידמפוטנטיות.
- מערכת מטבע וירטואלי—זיכוי/חיוב אטומי עם לוגים.
- מסך היסטוריית רכישות—API עם דפדוף, רענון במשיכה.
- מנגנון מבצעים מסתובבים—קונפיגורציה עם
purchase_history, טיימרים בצד הלקוח. - שחזור רכישות—כפתור iOS, בדיקת זכאות.
- אנליטיקה—אירועי רכישה, המרות, LTV.
מה כלול ביישום החנות
- עיצוב סכמת נתונים למוצרים ומטבעות
- אינטגרציה של StoreKit 2 (iOS) ו-Google Play Billing 6 (אנדרואיד)
- אימות קבלה בצד השרת (Apple/Google)
- מערכת מטבע וירטואלי עם אידמפוטנטיות
- מסך היסטוריית רכישות עם דפדוף
- מנגנון הצעות מסתובבות והתאמה אישית
- שחזור רכישות בשתי הפלטפורמות
- אנליטיקה: אירועי רכישה, המרות, LTV
דוגמה לקונפיגורציית מוצר מלאה
{
"productId": "premium_monthly",
"type": "iap_subscription",
"storeProductId": {
"ios": "com.mygame.premium.monthly",
"android": "premium_monthly"
},
"displayName": "Premium Membership",
"description": "Double rewards, no ads, daily gems",
"durationDays": 30,
"trialDays": 7,
"position": 1,
"isVisible": true
}ציר זמן: חנות בסיסית עם כמה מוצרים, אינטגרציית IAP ואימות בצד השרת—החל מ-5 ימים. יישום מלא עם הצעות מסתובבות, היסטוריה, מנויים ואנליטיקה—החל משבועיים. התמחור מחושב באופן אישי.
אנו מבטיחים אימות נכון בצד השרת של כל הרכישות. ניסיון: 15+ פרויקטי משחקים, שירות למעל מיליון משתמשים פעילים יומיים ועיבוד של 2 מיליון דולר+ בהכנסות IAP חודשיות. קבל ייעוץ על אינטגרציית חנות למשחק שלך—צור קשר להערכת פרויקט. ניתן גם להזמין ביקורת מעמיקה של המונטיזציה הנוכחית שלך עם המלצות לשיפור מדדים.







