{"id":35948,"date":"2022-05-20T17:25:24","date_gmt":"2022-05-20T21:25:24","guid":{"rendered":"https:\/\/mjtsai.com\/blog\/?p=35948"},"modified":"2023-05-29T10:16:10","modified_gmt":"2023-05-29T14:16:10","slug":"new-receipt-validation-sample-code","status":"publish","type":"post","link":"https:\/\/mjtsai.com\/blog\/2022\/05\/20\/new-receipt-validation-sample-code\/","title":{"rendered":"New Receipt Validation Sample Code"},"content":{"rendered":"<p><a href=\"https:\/\/developer.apple.com\/documentation\/appstorereceipts\/validating_receipts_on_the_device\">Apple<\/a> (via <a href=\"https:\/\/twitter.com\/weichsel\/status\/1527653035933040641\">Thomas Zoechling<\/a>):<\/p>\n<blockquote cite=\"https:\/\/developer.apple.com\/documentation\/appstorereceipts\/validating_receipts_on_the_device\"><p>The following example code illustrates how to retrieve an identifier in macOS for validating an App Store receipt. Use the data returned to by the <code>copy_mac_address<\/code> function to validate the App Store receipt.<\/p><p>In the following Swift code, the <code>io_service<\/code> function uses <a href=\"https:\/\/developer.apple.com\/documentation\/iokit\">IOKit<\/a> to retrieve network interfaces as an optional IOKit object. The <code>copy_mac_address<\/code> function looks up an appropriate network interface and returns the hardware address from the IOKit object as optional <a href=\"https:\/\/developer.apple.com\/documentation\/corefoundation\/cfdata-rv9\">CFData<\/a>.<\/p><\/blockquote>\n<p>Apple&rsquo;s sample code for this had been broken at least since Catalina. I still think there should just be an API for validating and parsing receipts, instead of encouraging developers to either reinvent the wheel or incorporate open source code of questionable quality.<\/p>\n\n<p>Previously:<\/p>\n<ul>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2020\/11\/25\/ios-apps-not-available-in-the-mac-app-store\/\">iOS Apps Not Available in the Mac App Store<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2019\/10\/16\/receipt-validation-and-airplay-2\/\">Receipt Validation and AirPlay 2<\/a><\/li>\n<\/ul>\n\n<p id=\"new-receipt-validation-sample-code-update-2022-06-08\">Update (2022-06-08): macOS 13 <a href=\"https:\/\/twitter.com\/grgarside\/status\/1533892820003606531\">adds<\/a> <a href=\"https:\/\/developer.apple.com\/documentation\/storekit\/apptransaction\">AppTransaction<\/a>.<\/p>\n\n<p id=\"new-receipt-validation-sample-code-update-2022-06-10\">Update (2022-06-10): <a href=\"https:\/\/twitter.com\/siracusa\/status\/1535046805943091230\">John Siracusa<\/a>:<\/p>\n<blockquote cite=\"https:\/\/twitter.com\/siracusa\/status\/1535046805943091230\">\n<p>Still no simple Apple API to validate Mac App Store receipts, though, right?<\/p>\n<\/blockquote>\n\n<p><a href=\"https:\/\/twitter.com\/rosyna\/status\/1535047832293388288\">Rosyna Keller<\/a>:<\/p>\n<blockquote cite=\"https:\/\/twitter.com\/rosyna\/status\/1535047832293388288\">\n<p>No. And I&rsquo;m not sire there will be on as it&rsquo;s a semi-antithesis of DRM checking: have your check in multiple places that can&rsquo;t be stubbed out by one change to the binary especially if it would apply to every binary.<\/p>\n<\/blockquote>\n\n<p><a href=\"https:\/\/twitter.com\/siracusa\/status\/1535075237351628800\">John Siracusa<\/a>:<\/p>\n<blockquote cite=\"https:\/\/twitter.com\/siracusa\/status\/1535075237351628800\">\n<p>I just don&rsquo;t want to have to statically link OpenSSL into my dinky app and then copy\/paste a bunch of code I don&rsquo;t understand. I&rsquo;m not trying to stop someone with a hex editor. I&rsquo;m trying to stop casual piracy.<\/p>\n<\/blockquote>\n\n<p><a href=\"https:\/\/twitter.com\/rosyna\/status\/1535054338934001664\">Rosyna Keller<\/a>:<\/p>\n<blockquote cite=\"https:\/\/twitter.com\/rosyna\/status\/1535054338934001664\">\n<p>This <a href=\"https:\/\/developer.apple.com\/documentation\/storekit\/supporting_business_model_changes_by_using_the_app_transaction\">new API<\/a> is for making feature selections betterer based on date purchased without needing to roll a new app entry on the App Store for the new version.<\/p>\n<\/blockquote>","protected":false},"excerpt":{"rendered":"<p>Apple (via Thomas Zoechling): The following example code illustrates how to retrieve an identifier in macOS for validating an App Store receipt. Use the data returned to by the copy_mac_address function to validate the App Store receipt.In the following Swift code, the io_service function uses IOKit to retrieve network interfaces as an optional IOKit object. [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"apple_news_api_created_at":"2022-05-20T21:25:28Z","apple_news_api_id":"dcbb7ead-75c7-4ed9-af75-4adfff46146c","apple_news_api_modified_at":"2023-05-29T14:16:13Z","apple_news_api_revision":"AAAAAAAAAAAAAAAAAAAAAw==","apple_news_api_share_url":"https:\/\/apple.news\/A3Lt-rXXHTtmvdUrf_0YUbA","apple_news_coverimage":0,"apple_news_coverimage_caption":"","apple_news_is_hidden":false,"apple_news_is_paid":false,"apple_news_is_preview":false,"apple_news_is_sponsored":false,"apple_news_maturity_rating":"","apple_news_metadata":"\"\"","apple_news_pullquote":"","apple_news_pullquote_position":"","apple_news_slug":"","apple_news_sections":"\"\"","apple_news_suppress_video_url":false,"apple_news_use_image_component":false,"footnotes":""},"categories":[4],"tags":[2392,30,39,1666,2077,74,71,901],"class_list":["post-35948","post","type-post","status-publish","format-standard","hentry","category-programming-category","tag-app-store-receipt-validation","tag-mac","tag-macappstore","tag-macos-10-15","tag-macos-12","tag-opensource","tag-programming","tag-swift-programming-language"],"apple_news_notices":[],"_links":{"self":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/35948","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/comments?post=35948"}],"version-history":[{"count":3,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/35948\/revisions"}],"predecessor-version":[{"id":36176,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/35948\/revisions\/36176"}],"wp:attachment":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/media?parent=35948"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/categories?post=35948"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/tags?post=35948"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}