Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥

StoreKit2を使った課金システムのフルリニューアル

yuhei
September 03, 2023

 StoreKit2を使った課金システムのフルリニューアル

yuhei

September 03, 2023
Tweet

Other Decks in Programming

Transcript

  1. ࣗݾ঺հ • גࣜձࣾCAM த్Ͱೖࣾ • iOS ΤϯδχΞ 5೥໨ • CAMͰ͸ɺLDHɺΞΠυϧɺ઎͍ɺ৽

    R25ͳͲɺΤϯλϝࣄۀʹैࣄ • λοϓϧʹδϣΠϯͯ͠໿1೥ ҏ౻ ༔ฏ
  2. ओͳ಺༰ • λοϓϧʹ͍ͭͯ • λοϓϧͷ՝ۚʹ͍ͭͯ • ϑϧϦχϡʔΞϧͷഎܠ • ϑϧϦχϡʔΞϧ·Ͱͷ௕ظϓϥϯ •

    StoreKit2 • όοΫΤϯυଆͷରԠ • ϦϦʔε࣌ʹରԠͯ͠Α͔ͬͨ͜ͱ • ϦϦʔεޙʹ໌Β͔ʹͳࣦͬͨഊ...
  3. ϑϧϦχϡʔΞϧͷഎܠ • ՝ۚͷϚΠΫϩαʔϏεԽʢෳࡶͩͬͨγεςϜΛγϯϓϧʹ͍ͨ͠ʣ • ՝ۚج൫ͷ৐Γ׵͑ʢαΠόʔΤʔδΣϯτͷ՝ۚج൫Λ࢖͍͍ͨʣ • App Store Server Notifications

    ͷಋೖʢVersion 2ʣ ΞϓϦ಺՝ۚʹ͓͍ͯߪೖɺࣗಈߋ৽ɺαϒεΫఀࢭͳͲͷΠϕϯτΛαʔόʔʹ ϦΞϧλΠϜͰ௨஌Ͱ͖Δػೳɻ όοΫΤϯυଆ
  4. ϑϧϦχϡʔΞϧͷ௕ظϓϥϯʢ໿4ϲ݄ؒʣ ՝ۚͷϚΠΫϩαʔϏεԽ KMPɺBFFԽ ※ StoreKit1 ͷঢ়ଶ Step1 Step2 Step3 StoreKit2ͷಋೖ

    ͓ࢼ͠ΦϑΝʔ ϓϩϞʔγϣϯΦϑΝʔ ͷಋೖ େ͖ͳࢪࡦɺ͔͠΋՝ۚͷͨΊɺ3ͭʹ෼͚ͨ
  5. StoreKit2 - γϯϓϧͳίʔυ ϓϩμΫτͷߪೖ - Product.purchase() • Կ΋४උ͸ඞཁͳ͍ɻͨͬͨɺ1 ߦͷίʔυͰߪೖ։࢝ɻ •

    ߪೖ঎඼ͷݕূ͸ΞϓϦଆͰɻ • τϥϯβΫγϣϯ͸ಉؔ͡਺಺Ͱ ׬ྃͰ͖Δɻ • try catch ͰΤϥʔ΋ଈ࠲ʹऔಘͰ ͖Δɻ • Delegate ͳ͠ɻ • ίʔϧόοΫؔ਺΋ͳ͘ͳΔɻ
  6. StoreKit2 - γϯϓϧͳίʔυ ߪೖ঎඼ͷ෮ݩ࣌ͷτϥϯβΫγϣϯᶄ - Transaction.unfinished • ߪೖ࣌ʹApp Storeͷܾࡁ͸׬ ͕ྃͨ͠ɺαʔόʔଆͷܾࡁޙ

    ॲཧʹࣦഊͨ͠έʔεͳͲͰɺ ະॲཧͷτϥϯβΫγϣϯΛऔ ಘͰ͖Δɻ • ͪ͜Β΋ઃఆը໘ʹ͋Δʮߪೖ ಺༰ͷ෮ݩʯϝχϡʔʹ࣮૷͠ ͍ͯΔɻ
  7. StoreKit2 - γϯϓϧͳίʔυ τϥϯβΫγϣϯॲཧͷ஫ҙ఺ʂᶃ λοϓϧͰ͸ɺ෮ݩ࣌ʹҎԼͷ2छྨͷτϥϯβΫγϣϯΛ֬ೝͯ͠Δɻ ᶃ Transaction.currentEntitlements ᶄ Transaction.unfinished ԿΒ͔ͷཧ༝Ͱߪೖ঎඼ͷτϥϯβΫγϣϯΛ׬ྃͰ͖ͳ͔ͬͨͱ͖ɺ֘౰ͷτϥϯβΫγϣϯ

    ͸ Transaction.currentEntitlements Ͱ͸ͳ͘ɺTransaction.unfinished ʹଘࡏ͍ͯͨ͠ɻ ։ൃॳظஈ֊Ͱ͸ Transaction.currentEntitlements ʹར༻Մೳ঎඼͕͢΂ͯଘࡏ͢Δͱࢥ͕ͬͨɺ ςετΛ௨ͯ͡ɺະ׬ྃͷτϥϯβΫγϣϯ͸ Transaction.currentEntitlements ʹؚ·Ε͍ͯͳ͍ ͜ͱ͕Θ͔ͬͨɻ
  8. StoreKit2 - γϯϓϧͳίʔυ τϥϯβΫγϣϯॲཧͷ஫ҙ఺ʂᶄ ͦͷͨΊɺαʔόʔଆͰ͸APIΛϩοΫͯ͠ɺαʔόʔଆͷ࿈ଓܾͨ͠ࡁޙॲཧ͕ൃੜ͠ͳ͍Α͏ ʹରࡦͨ͠ɻ ঎඼Λߪೖͨ͠ͱ͖ɺαʔόʔଆͰܾࡁޙॲཧΛ͢Δ͕ɺ ॏෳͯ͠৽نߪೖͷॲཧͯ͠͠·͍ͬͯͨɻ Appleͷެࣜαϯϓϧίʔυʹ͸ɺߪೖʹΑΔτϥϯβΫγϣϯ͸ listen͠ͳ͍ͱॻ͍͕ͯ͋ͬͨ...

    // Iterate through any transactions that don't come from a direct call to `purchase()`. https://developer.apple.com/documentation/storekit/in-app_purchase/implementing_a_store_in_your_app_using_the_storekit_api A. ߪೖ௚ޙ B. ΞϓϦىಈ࣌ʹ listen ͨ͠ Transactions.updates
  9. StoreKit2 - γϯϓϧͳίʔυ Ϩγʔτ͕ෆཁʹͳͬͨʂ- ফ໣ܕ • Ϩγʔτͷ୅ΘΓʹɺ jwsRepresentation Λαʔόʔʹ ૹΔɻ

    • base64ʹΤϯίʔυ͞Ε͍ͯΔ ͷͰɺσίʔυ͢Ε͹ transactionId ͳͲΛऔಘͰ͖Δɻ • ߪೖ੒ޭޙͷฦΓ஋ͰऔಘͰ͖Δ ஋ɻ
  10. StoreKit2 - γϯϓϧͳίʔυ Ϩγʔτ͕ෆཁʹͳͬͨʂ- αϒεΫϦϓγϣϯ • Ϩγʔτͷ୅ΘΓʹɺ originalTransactionId Λαʔόʔʹ ૹΔɻ

    • λοϓϧͷαʔόʔଆͰ͸ɺ originalTransactionId Λجʹ App Store Server API Λ࢖ͬͯɺ τϥϯβΫγϣϯͷৄࡉ৘ใΛऔಘ ͢Δɻ • ͪ͜Β΋ɺߪೖ੒ޭޙͷฦΓ஋Ͱऔ ಘͰ͖Δ஋ɻ
  11. StoreKit2 - ΦϑΝʔ ͓ࢼ͠ΦϑΝʔ - ஫ҙ఺ʂ isEligibleForIntroOffer == true Ͱ΋ɺ

    ಉ͡αϒεΫάϧʔϓ಺Ͱɺར༻தͷαϒεΫ͕͋Δͱ͓ࢼ͠ΦϑΝʔΛద༻Ͱ͖ͳ͍ɻ ͦͷͨΊλοϓϧͰ͸ɺProduct.SubscriptionInfo.status Λऔಘͯ͠ɺ ݱࡏར༻தͷαϒεΫ͕ଘࡏ͢Δ͔νΣοΫ͍ͯ͠Δɻ true ͚ͩͲɺ͓ࢼ͠ΛఏڙͰ͖ͳ͍ͷͰ஫ҙʂ
  12. StoreKit2 - ΦϑΝʔ Ϩγʔτͷத਎Λൈਮʢ๨Εͳ͍Α͏ʹϝϞʣ • ແྉ͓ࢼ͠ΦϑΝʔ "is_trial_period": "true", "is_in_intro_offer_period": "false",

    • ༗ྉ͓ࢼ͠ΦϑΝʔ "is_trial_period": "false", "is_in_intro_offer_period": "true", ͓ࢼ͠ΦϑΝʔ - Ϩγʔτͷத਎
  13. StoreKit2 - ΦϑΝʔ • ϓϩϞʔγϣϯΦϑΝʔ৘ใͷऔಘʢ࠷େ10݅ͷొ࿥͕Մೳʣ Product.subscription?.promotionalOffers.first(where: { $0.id == offerId

    }) • ϓϩϞʔγϣϯΦϑΝʔΛఏڙՄೳ͔ʁ Product.SubscriptionInfo.status(for: subscriptionGroupId)?.isEmpty λοϓϧͰ͸ɺಉ͡αϒεΫάϧʔϓ಺ͷߪೖܦݧͰ൑அͨ͠ɻ ※ϕετϓϥΫςΟε͕͋Ε͹ڭ͍͖͍͑ͯͨͩͨͰ͢ɻ ϓϩϞʔγϣϯΦϑΝʔ
  14. ʮappBundleId + '\u2063' + keyIdentifier + '\u2063' + productIdentifier +

    '\u2063' + offerIdentifier + '\u2063' + appAccountToken + '\u2063' + nonce + '\u2063' + timestampʯ ʮappBundleId + '\u2063' + keyIdentifier + '\u2063' + productIdentifier + '\u2063' + offerIdentifier + '\u2063' + '' + '\u2063' + nonce + '\u2063' + timestampʯ StoreKit2 - ΦϑΝʔ ϓϩϞʔγϣϯΦϑΝʔΛߪೖ͢Δͱ͖ɺαʔόʔଆͰ signature Λੜ੒ͯ͠ɺ iOSଆͰ Product.purchase ࣌ʹ signature Λ෇༩͢Δඞཁ͕͋Δɻ ͜ͷͱ͖ɺΦϓγϣφϧͷ appAccountToken ͕ෆཁͳ৔߹͸ɺۭจࣈͱͯ͠ઃఆ͢Δɻ ※ۭจࣈ΋ແ͍ঢ়ଶͰ signature Λ࡞੒ͨ͠ΒߪೖͰ͖ͣΤϥʔʹͳΔɻ ϓϩϞʔγϣϯΦϑΝʔͷॺ໊࡞੒Ͱ͸·ͬͨ͜ͱʢsignatureʣ [Link] https://developer.apple.com/documentation/storekit/in-app_purchase/original_api_for_in-app_purchase/subscriptions_and_offers/ generating_a_signature_for_promotional_offers
  15. όοΫΤϯυଆͷରԠ App Store Server API • αϒεΫ৘ใͷऔಘ αϒεΫͷܾࡁޙॲཧͷͱ͖ɺoriginalTransactionId ͔Βৄࡉ৘ใΛऔಘ͢ΔͨΊʹɺ Լه

    API Λར༻ͨ͠ɻ https://api.storekit.itunes.apple.com/inApps/v1/subscriptions/{transactionId} https://developer.apple.com/documentation/appstoreserverapi/get_all_subscription_statuses • τϥϯβΫγϣϯཤྺ αϒεΫͷΞοϓάϨʔυ/μ΢ϯάϨʔυͷࡍʹɺաڈͷߪೖ৘ใ͕ඞཁͩͬͨͨΊɺ Լه API Λར༻ͨ͠ɻ https://api.storekit.itunes.apple.com/inApps/v1/history/{transactionId} https://developer.apple.com/documentation/appstoreserverapi/get_transaction_history
  16. ϦϦʔε࣌ʹରԠͯ͠Α͔ͬͨ͜ͱ ஈ֊తϦϦʔε • App Store Connect ͔ΒΞϓϦΛ ϦϦʔε͢Δͱ͖ɺʮஈ֊తϦϦ ʔεʯΛར༻ͨ͠ɻ •

    λοϓϧͰ͸௨ৗ࣌΋ஈ֊తϦϦ ʔεΛ࣮ࢪ͍ͯ͠Δ͕ɺ՝ۚؔ࿈ ͷϦϦʔε࣌͸ɺΧελϚʔαϙ ʔτ΁ͷ໰͍߹Θͤঢ়گͳͲݟͳ ͕Βɺ͍ͭ΋ΑΓ༨༟Λ࣋ͬͯ 100%։์ʹͨ͠ɻ
  17. ϦϦʔε࣌ʹରԠͯ͠Α͔ͬͨ͜ͱ Τϥʔϩάͷग़ྗ - Datadog • Datadog Λར༻ͯ͠ɺ՝ۚؔ࿈ͷΤ ϥʔΛग़ྗͨ͠ɻϢʔβʔ͔Βͷ໰ ͍߹Θͤ࣌ͷௐࠪʹ໾ʹཱͬͨɻ •

    εϜʔζͳௐࠪͷͨΊʹɺͪΐͬͱ ΍Γ͗͢ʁ͘Β͍ৄࡉͳΤϥʔ಺༰ ΛૹΔ͜ͱΛ͓͢͢Ίɻ • Τϥʔ͕ٸܹʹ૿͑ͨࡍ͸ɺSlack ΁௨஌͕ಧ͘Α͏ʹ Monitors Λར ༻ͨ͠ɻ
  18. ϦϦʔε࣌ʹରԠͯ͠Α͔ͬͨ͜ͱ ΤϥʔϝοηʔδʹΤϥʔ ID • ֤छ՝ۚؔ࿈ͷΤϥʔΛ ·ͱΊͯ؅ཧͯ͠ɺϢʔ βʔʹදࣔ͢ΔΤϥʔϝ οηʔδʹIDΛ෇༩͠ ͨɻ •

    Ϣʔβʔ͔Βͷ໰͍߹Θ ͤ࣌ʹɺΤϥʔϝοηʔ δͷεΫγϣ΋͓ئ͍͠ ͍ͯΔͨΊɺID͕ෆ۩߹ ௐࠪʹ໾ཱͬͨɻ