ነጻ ፈተነ ምቕራብ ተጠቀምቲ ንፕሪምየም ባህርያት ናይ ኣፕካ ንኽፍትኑ ንምትብባዕ ብሉጽ መገዲ ኮይኑ፡ ናብ ዝኸፍሉ ተኸታተልቲ ናይ ምቕያር ዕድሎም ይውስኽ። ኣፕል ምስ StoreKit 2 ኣቢሉ፡ ሓደ ተጠቃሚ ንመእተዊ ቅድመ-ምድላዋት ብቑዕ ምዃኑ ንምፍላጥ ዝሕግዙ ዝተማዕበሉ መሳርሒታት ኣተኣታትዩ ኣሎ። ኣብዚ ጽሑፍ፡ ብቑዕነት ተጠቃሚ ንምርግጋጽ፡ ብቑንጣሮ ኮድ ዝተማልአ፡ ኣብ ኣፕካ ነጻ ፈተነታት ኣብ ምትግባር ክንመርሓካ ኢና። ብተወሳኺ ንብቑዓትን ዘይብቑዓትን ተጠቀምቲ ናይ ፈተነ ስናርዮታት ክንሽፍን ኢና። ከምኡ'ውን ኣብ ምሉእ እቲ ጽሑፍ ፋሕ ኢሎም ዘለዉ " ፕሮ ቲፕስ " ምክትታልኩም ኣረጋግጹ፣ ኣብኡ ድማ ካብ ተመኩሮይ ገለ ውልቃዊ ርድኢታት የካፍለኩም!
ቅድሚ ኮዲንግ ምጅማርካ፡ ኣብ App Store Connect ናይ ውሽጢ ኣፕ ዕድጊ ቅጥዕታትካ ምውቃርካ ኣረጋግጽ፤
ነዚ ቀሊል ክገብሮ እየ ነቲ ናይ ኮድ ስኒፐት ብምርኣይካ፣ ንተጠቃሚ ናይ ፈተነ ብቕዓት ብኸመይ ክትሕስቦ ከም እትደሊ
ነቲ ነጻ ናይ ፈተነ ቅድመ-ምድላው ንምርኣይን ንናይ ተጠቃሚ ርክባት ንምሕላውን SwiftUI ትርኢት ፍጠር። ኣብ ቁንጣሮ ኮድ ብዙሕ ርእይቶታት ክገድፍ እየ ንዓኻትኩም ንኽመላለሰኩም።
import StoreKit2 // StoreManager is responsible to communicate with Storekit Framework provided by Apple for monetization class StoreManager: ObservableObject { @Published var message: String = "" // We will use this property to display the right message to the user @Published var products: [Product] = [] // This will be responsible to store the products fetched that we defined // in App Store Connect // Fetch products from the App Store func fetchProducts() { Task { do { // product_id is the id that you would have defined in App Store Connect. let storeProducts = try await Product.products(for: ["product_id"]) products = storeProducts } catch { message = "Failed to fetch products: \(error.localizedDescription)" } } } // Initiate purchase func purchase() { guard let product = products.first else { // There is a possibility of products not being fetched from App Store Connect. // Pro Tip: From experience, even though we defined the products on App Store Connect, it is possible // that the products are not found post attempting to fetch. So, it is important to handle this case. message = "No product available." return } Task { do { let result = try await product.purchase() switch result { case .success(let verification): switch verification { case .verified: message = "Purchase successful!" case .unverified: message = "Could not verify the purchase." } case .userCancelled: message = "Purchase cancelled." case .pending: message = "Purchase is pending." @unknown default: message = "Unknown result." } } catch { message = "Purchase failed: \(error.localizedDescription)" } } } // Check if the user is eligible for a free trial func checkTrialEligibility() async -> Bool { guard let product = products.first else { return false } do { // So when you define a auto renewable subscriptions, there are usually bond in a group. The group can again be // found in App Store Connect let eligibility = try await product.subscription?.isEligibleForIntroOffer(for groupID: 111111) return eligibility ?? false } catch { message = "Error checking trial eligibility: \(error.localizedDescription)" return false } } }
import SwiftUI import StoreKit struct SubscriptionView: View { @StateObject private var storeManager = StoreManager() @State private var isEligibleForFreeTrial = false var body: some View { VStack { Text("Unlock Premium Features") .font(.title) .padding() Text("Get a 7-day free trial of our premium subscription.") .multilineTextAlignment(.center) .padding() Button(action: { storeManager.purchase() }) { // Based on user status, we can display the text Text(isEligibleForFreeTrial ? "Start Free Trial" : "Start Subscription") .bold() .frame(width: 200, height: 50) .background(Color.blue) .foregroundColor(.white) .cornerRadius(10) } Text(storeManager.message) .padding() } .onAppear { storeManager.fetchProducts() checkTrialEligibility() } } private func checkTrialEligibility() { Task { isEligibleForFreeTrial = await storeManager.checkTrialEligibility() } } }
ኣፕል ኣብ Xcode StoreKit Testing ብምጥቃም ዝተፈላለዩ ናይ ተጠቃሚ ኩነታት (ንኣብነት፡ ንነጻ ፈተነ ብቑዓት ወይ ዘይብቑዓት) ንምፍታን ድልዱላት መሳርሒታት ይህብ :
ናብ ፋይል > ሓድሽ > ፋይል... > ፋይል ውቅር ስቶርኪት ኣብ ኤክስኮድ ኪድ።
ናይ ምዝገባ ፍርያትካ ኣዳልዉ፣ ናይ ፈተነ ግዜን ናይ ብቕዓት ኩነታትን ሓዊስካ።
Pro Tip : ካብ App Store Connect ናይ configuration ፋይል ንምትእስሳር ሓድሽ ናይ ውቅር ፋይል ክትፈጥር እውን ትኽእል ኢኻ በዚ መንገዲ ድማ ኩሎም ፍርያት ምድላው ኣየድልየካን እዩ።
ዝተፈላለዩ ስናርዮታት ምምሳል፤
ንነጻ ፈተነ ብቑዕ፤
ንሓደ ነጻ ናይ ፈተነ ተጠቃሚ ንምምሳል፡ ኣብቲ ትራንዛክሽን ኣካያዲ ዝኾነ ትራንዛክሽን ከምዘይህልወካ ኣረጋግጽ።
ነቲ ናይ ትራንዛክሽን ኣካያዲ ንምርኣይ። ናብ ዲባግ → ስቶርኪት → ትራንዛክሽን ምምሕዳር ኪድ
ንነጻ ፈተነ ብቑዕ ዘይኮነ፤
ንነጻ ፈተነ ብቑዕ ዘይኮነ ተጠቃሚ ንምምሳል። ካብቲ ትራንዛክሽን ማናጀር ኣብቲ ትራንዛክሽን ማናጀር ብኢድካ ምዝገባ ክትውስኽ ትኽእል ኢኻ። ኣብቲ ናይ ትራንዛክሽን ኣመሓዳሪ ስክሪን ኣብ ዘሎ add ዝብል ቁልፊ ክትጥውቕ ትኽእል ኢኻ ድሕሪኡ ነቲ ክትውስኾ እትደሊ ትራንዛክሽን ክትመርጽ ትኽእል። ኣብዚ፡ ንተጠቃሚ ወርሓዊ ምዝገባ ክውቅሮ ይፍትን ኣለኹ። ነቲ ትራንዛክሽን ድሕሪ ምውሳኽን ነቲ ኣፕ እንደገና ድሕሪ ምዝዋርን፡ እቲ ናይ ፈተነ ብቕዓት ከም ሓሶት ምልክት ክግበረሉ ክትሪኦ ይግባእ።
ፕሮ ምኽሪ፦ ምስቲ ዕድጊ UUID እውን ከተካትት ትኽእል ኢኻ፣ ነዚ ዓውዲ ተጠቒምካ ናይቲ ተጠቃሚ መለለዪ ክትዕቅቦ ትኽእል ኢኻ። በዚ መንገዲ ኣየናይ ተጠቃሚ ኣብ ኣፕካ ዕድጊ ከም ዝገበረ ከተረጋግጽ ትኽእል። እዚ ሓበሬታ ድሒሩ ካብ ታሪኽ ትራንዛክሽን ተጠቃሚ ክውሰድ ይኽእል።
ሳንድቦክስ ፈተነ ንናይ ኣፕካ ኣብ ውሽጢ ኣፕ ዝግበር ዕድጊታትን ምዝገባን ኣብ ሃዋህው ምፍራይ ኣፕ ስቶር ዝመስል ሃዋህው ክትፍትኖ የኽእለካ ኣብ ርእሲኡ ድማ ሓደ ክልተ ወሰናስን ጉዳያት ከም ዝተቛረጸ ዕድጊ፡ ምክፋል ስድራቤት፡ ከምኡ’ውን ካብ... app ወይ ኣብ ካልእ መሳርሒ። ከምኡ ውን የኽእለካ
ቅድሚ ዝኾነ ነገር ግን፡ ከመይ ጌርካ ሳንድቦክስ ቴስቲንግ ትሰርዕን ትጥቀመሉን እንሆ፤
ሳንድቦክስ ቴስተር ኣካውንት ምፍጣር፤
ብናይ ሳንድቦክስ ቴስተር ኣካውንት ምእታው፤
ኣፕካ ኣብ ሳንድቦክስ ሞድ ኣካይድ፤
ዝተፈላለዩ ስናርዮታት ፈትኑ፤
ፕሮ ምኽሪ፦ ሓደ ናይ ኣፕል ኣካውንት ብዙሕ ንጡፍ ምዝገባ ክህልዎ ስለዘይክእል ክልተ ዝተፈላለዩ ተጠቀምቲ ሓደ ዓይነት ኣፕል ኣይዲ ተጠቒሞም ኣብቲ ኣፕ ዝተፈላለየ ዕድጊ ክገብሩ ኣይክእሉን እዮም። ነዚ ናይ ተጠቃሚ ጉዳይ ንዓኻ ኣፕ ምፍታሽካ ኣረጋግጽ።
https://developer.apple.com/documentation/storekit ዝብል ጽሑፍ ኣሎ።
https://developer.apple.com/documentation/xcode/ኣብ-xcode-ምፍታን-ስቶርኪት-ምቕማጥ/
https://developer.apple.com/ኣፕ-ስቶር-ምትእስሳር/