RevenueCat مقابل Adapty
خدمات إدارة الاشتراكات SaaS لـ iOS + Android — RevenueCat (رائد السوق) مقابل Adapty (تركيز على الـ paywall واختبار A/B). تكافؤ الميزات، التسعير، التكامل.
استأجر بنية اشتراكات متعددة المتاجر كـ SDK + خادم خلفي
إطار عمل Apple من الطرف الأول، لكنك تكتب جانب الخادم بنفسك
العتبة واضحة: إذا كان الإيراد المتتبَّع شهريًا (MTR) أقل من $2,500، فإن RevenueCat مجاني عمليًا؛ وما تقارنه هناك ليس نسبة 1%، بل تكلفة صفر — بنيتك الخاصة تبقى دائمًا أغلى مقارنة بذلك. في منتج يُباع فقط عبر App Store، بمنتج واحد، وحسّاس من ناحية KVKK، يمكن الدفاع عن StoreKit 2 الخالص. إذا كنت تبيع عبر متاجر متعددة، فإن إبقاء 18 نوعًا من إشعارات RTDN متزامنة بالتوازي مع إشعارات App Store V2 يصبح مكلفًا؛ وكقاعدة عامة تقريبية، أعد وزن القرار عندما يتجاوز MTR $50,000.
| الفئة | RevenueCat | StoreKit 2 (kendi altyapın) |
|---|---|---|
| الأداء | 8/10 | 8/10 |
| سهولة التعلّم | 8/10 | 5/10 |
| النظام البيئي | 8/10 | 6/10 |
| المجتمع | 6/10 | 5/10 |
| سوق العمل | 5/10 | 6/10 |
| الاستدامة المستقبلية | 8/10 | 8/10 |
// RevenueCat - فحص الاستحقاق وإجراء الشراء (iOS SDK 5.x)
import RevenueCat
func configureRevenueCat() {
Purchases.logLevel = .debug
Purchases.configure(withAPIKey: "appl_XXXXXXXXXXXX")
}
func unlockProIfEntitled() async {
do {
let customerInfo = try await Purchases.shared.customerInfo()
if customerInfo.entitlements["pro"]?.isActive == true {
print("استحقاق Pro مُفعّل")
}
} catch {
print("خطأ customerInfo: \(error)")
}
}
func purchasePro() async {
do {
let offerings = try await Purchases.shared.offerings()
guard let package = offerings.current?.availablePackages.first else { return }
let result = try await Purchases.shared.purchase(package: package)
if result.customerInfo.entitlements["pro"]?.isActive == true {
print("تم الشراء بنجاح، Pro مُفعّل")
}
} catch {
print("خطأ في الشراء: \(error)")
}
}// StoreKit 2 - الاستماع للمعاملات وفحص الاستحقاق (بنيتك الخاصة)
import StoreKit
func listenForTransactions() -> Task<Void, Error> {
Task.detached {
for await result in Transaction.updates {
switch result {
case .verified(let transaction):
await grantEntitlement(for: transaction)
await transaction.finish()
case .unverified(_, let error):
print("فشل التحقق: \(error)")
}
}
}
}
func checkCurrentEntitlement() async -> Bool {
for await result in Transaction.currentEntitlements {
guard case .verified(let transaction) = result else { continue }
if transaction.productID == "pro_monthly" {
return true
}
}
return false
}
func purchase(product: Product) async throws {
let result = try await product.purchase()
switch result {
case .success(let verification):
guard case .verified(let transaction) = verification else { return }
await grantEntitlement(for: transaction)
await transaction.finish()
case .userCancelled, .pending:
break
@unknown default:
break
}
}
func grantEntitlement(for transaction: Transaction) async {
// أرسل JWS إلى الخادم، وتحقّق بشكل متقاطع عبر App Store Server API
}العتبة واضحة: إذا كان الإيراد المتتبَّع شهريًا (MTR) أقل من $2,500، فإن RevenueCat مجاني عمليًا؛ وما تقارنه هناك ليس نسبة 1%، بل تكلفة صفر — بنيتك الخاصة تبقى دائمًا أغلى مقارنة بذلك. في منتج يُباع فقط عبر App Store، بمنتج واحد، وحسّاس من ناحية KVKK، يمكن الدفاع عن StoreKit 2 الخالص. إذا كنت تبيع عبر متاجر متعددة، فإن إبقاء 18 نوعًا من إشعارات RTDN متزامنة بالتوازي مع إشعارات App Store V2 يصبح مكلفًا؛ وكقاعدة عامة تقريبية، أعد وزن القرار عندما يتجاوز MTR $50,000.
احصل على استشارة مجانيةإذا كان الإيراد المتتبَّع شهريًا (MTR) أقل من $2,500، فإن RevenueCat مجاني عمليًا ويتولى مهام التحقق من جانب الخادم لمتاجر متعددة، وWebhook، وإدارة الاسترجاع — في هذه الحالة يكون RevenueCat منطقيًا غالبًا. في تطبيق أحادي المنصة، بمنتج واحد بسيط، ولا يريد تسليم بيانات الإيراد لطرف ثالث، يُعد StoreKit 2 الخالص خيارًا يمكن الدفاع عنه. أما في منتج متعدد المتاجر وينمو باستمرار، فكتابة بنيتك الخاصة تصبح عادةً أغلى تكلفة.