Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.
Avatar for yuhei yuhei
September 03, 2023

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

Avatar for yuhei

yuhei

September 03, 2023
Tweet

More Decks by yuhei

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͕ෆ۩߹ ௐࠪʹ໾ཱͬͨɻ