{"id":137977,"date":"2021-07-08T00:00:00","date_gmt":"2021-07-08T00:00:00","guid":{"rendered":"https:\/\/adapty.io\/blog\/storekit-2-2\/"},"modified":"2021-07-08T00:00:00","modified_gmt":"2021-07-08T00:00:00","slug":"storekit-2","status":"publish","type":"post","link":"https:\/\/adapty.io\/zh\/blog\/storekit-2\/","title":{"rendered":"StoreKit 2 API\u7684\u65b0\u7279\u6027\u662f\u4ec0\u4e48\uff1f\u82f9\u679c\u5982\u4f55\u7b80\u5316\u5e94\u7528\u5185\u8d2d\u4e70\u7684\u6574\u5408"},"content":{"rendered":"\n

\u5728\u6700\u8fd1\u4e3e\u884c\u76842021\u5e74\u5168\u7403\u5f00\u53d1\u8005\u5927\u4f1a\u4e0a\uff0c\u82f9\u679c\u63a8\u51fa\u4e86\u65b0\u7248\u7684StoreKit 2\u3002\u8fd9\u662f\u4e00\u4e2a\u8d1f\u8d23\u5728iOS\u4e2d\u8fdb\u884c\u8d2d\u4e70\u7684\u6846\u67b6\u3002\u5e26\u6709\u5e94\u7528\u5185\u8d2d\u4e70\uff08in-app purchase\uff09\u529f\u80fd\u548c\u8ba2\u9605\u529f\u80fd\u7684\u5e94\u7528\u4efd\u989d\u7a33\u6b65\u589e\u957f\uff0c\u82f9\u679c\u901a\u8fc7\u53d1\u5e03StoreKit 2\u663e\u8457\u7b80\u5316\u4e86\u5e94\u7528\u5185\u8d2d\u4e70\u529f\u80fd\u5728\u5e94\u7528\uff08APP\uff09\u4e2d\u7684\u6574\u5408\u3002\u4eca\u5929\uff0c\u6211\u4eec\u5c06\u8003\u8651\u5728\u670d\u52a1\u5668\u7aef\u4f7f\u7528StoreKit 2\uff0c\u6362\u53e5\u8bdd\u8bf4\uff0c\u5c31\u662f\u5728App Store Server API\u7684\u5e2e\u52a9\u4e0b\u8fdb\u884c\u3002<\/p>\n\n\n\n

\u8bf7\u6c42\u8ba4\u8bc1<\/h2>\n\n\n\n

\u5728\u5f53\u524d\u7684API\u7248\u672c\u4e2d\uff0c\u60a8\u9700\u8981\u5171\u4eab\u5bc6\u94a5\u6765\u53d1\u9001\u8bf7\u6c42\u3002\u8fd9\u662f\u4e00\u4e2a\u60a8\u53ef\u4ee5\u5728App Store Connect\u4e2d\u83b7\u5f97\u7684\u79d8\u5bc6\u56fa\u5b9a\u5b57\u7b26\u4e32\u3002\u65b0\u7248\u672c\u7684API\u4f7f\u7528JSON Web Token\uff08JWT\uff09\u6807\u51c6\u8bf7\u6c42\u8ba4\u8bc1\u3002   <\/p>\n\n\n\n

\u5bc6\u94a5\u751f\u6210 <\/h3>\n\n\n\n

\u9996\u5148\uff0c\u521b\u5efa\u4e00\u4e2a\u79c1\u94a5<\/a>\uff0c\u8fd9\u4e2a\u79c1\u94a5\u5c06\u7528\u4e8e\u5bf9\u8bf7\u6c42\u8fdb\u884c\u6388\u6743\u3002\u6253\u5f00App Store Connect\uff0c\u524d\u5f80\u201cUsers and Access\u201d\u90e8\u5206\uff0c\u7136\u540e\u5230\u201cKeys\u201d\u9009\u9879\u5361\u3002\u9009\u62e9\u201cIn-App Purchase\u201d\u5bc6\u94a5\u7c7b\u578b\u3002\u4e0b\u8f7d\u4e00\u4e2a\u65b0\u5bc6\u94a5\u3002\u60a8\u8fd8\u9700\u8981\u5b83\u7684ID\u2014\u2014\u60a8\u53ef\u4ee5\u5c06\u5176\u590d\u5236\u5230App Store Connect API\u6807\u7b7e\u9875\u4e2d\u7684\u53d1\u884c\u8005ID\u6240\u5728\u9875\u9762\u3002<\/p>\n\n\n\n

\"Creating
\u521b\u5efa\u4e00\u4e2a\u7528\u4e8eApp Store Server API\u7684\u79c1\u94a5<\/em><\/figcaption><\/figure>\n\n\n\n

\u521b\u5efa\u4e00\u4e2a\u4ee4\u724c<\/h3>\n\n\n\n

\u4e0b\u4e00\u6b65\u662f\u521b\u5efa\u4e00\u4e2a\u5c06\u7528\u4e8e\u5bf9\u8bf7\u6c42\u8fdb\u884c\u6388\u6743\u7684\u4ee4\u724c\u3002\u8fd9\u4e2a\u8fc7\u7a0b\u5728\u6587\u6863<\/a>\u4e2d\u6709\u8be6\u7ec6\u63cf\u8ff0\uff0c\u6240\u4ee5\u6ca1\u6709\u7406\u7531\u5bf9\u5b83\u8fdb\u884c\u8fc7\u591a\u7684\u5173\u6ce8\u3002\u4e0b\u9762\u662f\u4e00\u4e2a\u73b0\u6210\u7684Python\u5b9e\u73b0\u793a\u4f8b\u3002\u503c\u5f97\u6ce8\u610f\u7684\u662f\uff0c\u4e3a\u6bcf\u4e2a\u65b0\u8bf7\u6c42\u751f\u6210\u65b0\u4ee4\u724c\u662f\u6ca1\u6709\u610f\u4e49\u7684\u3002\u5728\u521b\u5efa\u4ee4\u724c\u65f6\uff0c\u60a8\u5c06\u5176\u751f\u5b58\u671f\u8bbe\u7f6e\u4e3a\u81f3\u591a60\u5206\u949f\uff0c\u5e76\u5728\u6b64\u671f\u95f4\u4f7f\u7528\u76f8\u540c\u7684\u4ee4\u724c\u3002 <\/p>\n\n\n\n

<\/path><\/path><\/svg><\/span>
import<\/span> time<\/span>,<\/span> uuid<\/span><\/span>\nfrom<\/span> authlib<\/span>.<\/span>jose <\/span>import<\/span> jwt<\/span><\/span>\n<\/span>\nBUNDLE_ID <\/span>=<\/span> <\/span>'<\/span>com.adapty.sample_app<\/span>'<\/span><\/span>\nISSUER_ID <\/span>=<\/span> <\/span>'<\/span>4336a124-f214-4d40-883b-6db275b5e4aa<\/span>'<\/span><\/span>\nKEY_ID <\/span>=<\/span> <\/span>'<\/span>J65UYBDA74<\/span>'<\/span><\/span>\nPRIVATE_KEY <\/span>=<\/span> <\/span>'''<\/span><\/span>\n-----BEGIN PRIVATE KEY-----<\/span><\/span>\nMIGTAgMGByqGSMBHkAQQgR\/fR+3Lkg4...<\/span><\/span>\n-----END PRIVATE KEY-----<\/span><\/span>\n'''<\/span><\/span>\n<\/span>\nissue_time <\/span>=<\/span> <\/span>round<\/span>(<\/span>time<\/span>.<\/span>time<\/span>())<\/span><\/span>\nexpiration_time <\/span>=<\/span> issue_time <\/span>+<\/span> <\/span>60<\/span> <\/span>*<\/span> <\/span>60<\/span> <\/span># 1 hour expiration<\/span><\/span>\n<\/span>\n<\/span>\nheader <\/span>=<\/span> <\/span>{<\/span><\/span>\n <\/span>'<\/span>alg<\/span>'<\/span>:<\/span> <\/span>'<\/span>ES256<\/span>'<\/span>,<\/span><\/span>\n <\/span>'<\/span>kid<\/span>'<\/span>:<\/span> KEY_ID<\/span>,<\/span><\/span>\n <\/span>'<\/span>typ<\/span>'<\/span>:<\/span> <\/span>'<\/span>JWT<\/span>'<\/span><\/span>\n}<\/span><\/span>\n<\/span>\npayload <\/span>=<\/span> <\/span>{<\/span><\/span>\n <\/span>'<\/span>iss<\/span>'<\/span>:<\/span> ISSUER_ID<\/span>,<\/span><\/span>\n <\/span>'<\/span>iat<\/span>'<\/span>:<\/span> issue_time<\/span>,<\/span><\/span>\n <\/span>'<\/span>exp<\/span>'<\/span>:<\/span> expiration_time<\/span>,<\/span><\/span>\n <\/span>'<\/span>aud<\/span>'<\/span>:<\/span> <\/span>'<\/span>appstoreconnect-v1<\/span>'<\/span>,<\/span><\/span>\n <\/span>'<\/span>nonce<\/span>'<\/span>:<\/span> <\/span>str<\/span>(<\/span>uuid<\/span>.<\/span>uuid4<\/span>()),<\/span><\/span>\n <\/span>'<\/span>bid<\/span>'<\/span>:<\/span> BUNDLE_ID<\/span><\/span>\n}<\/span><\/span>\n<\/span>\ntoken_encoded <\/span>=<\/span> jwt<\/span>.<\/span>encode<\/span>(<\/span>header<\/span>,<\/span> payload<\/span>,<\/span> PRIVATE_KEY<\/span>)<\/span><\/span>\ntoken_decoded <\/span>=<\/span> token_encoded<\/span>.<\/span>decode<\/span>()<\/span><\/span>\n<\/span>\nauthorization_header <\/span>=<\/span> <\/span>{<\/span><\/span>\n <\/span>'<\/span>Authorization<\/span>'<\/span>:<\/span> <\/span>f<\/span>'Bearer <\/span>{<\/span>token_decoded<\/span>}<\/span>'<\/span><\/span>\n}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n

\u7b7e\u7f72\u7684\u4ea4\u6613<\/h2>\n\n\n\n

\u5728API\u7684\u65b0\u7248\u672c\u4e2d\uff0c\u6240\u6709\u4ea4\u6613\u90fd\u4ee5JSON Web\u7b7e\u540d\uff08JWS\uff09\u6807\u51c6\u8fd4\u56de\u3002\u8fd9\u662f\u4e00\u4e2a\u7531\u4e09\u90e8\u5206\u7ec4\u6210\u7684\u5b57\u7b26\u4e32\uff0c\u7531\u70b9\u5206\u5272\u3002  <\/p>\n\n\n\n

    \n
  1. Base64\u5934\u90e8\u3002<\/li>\n\n\n\n
  2. Base64\u4ea4\u6613\u6709\u6548\u8d1f\u8f7d\u3002<\/li>\n\n\n\n
  3. \u4ea4\u6613\u7b7e\u540d\u3002<\/li>\n<\/ol>\n\n\n\n
    <\/path><\/path><\/svg><\/span>
    Base<\/span>64<\/span>(header) + <\/span>"<\/span>.<\/span>"<\/span> + Base<\/span>64<\/span>(payload) + <\/span>"<\/span>.<\/span>"<\/span> + sign(Base<\/span>64<\/span>(header) + <\/span>"<\/span>.<\/span>"<\/span> + Base<\/span>64<\/span>(payload))<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n

    \u4ea4\u6613\u5934\u90e8<\/h3>\n\n\n\n

    \u9700\u8981\u4e00\u4e2a\u5934\u90e8\u6765\u786e\u4fdd\u4ea4\u6613\u662f\u771f\u5b9e\u7684\u3002Alg\u5bc6\u94a5\u5305\u542b\u52a0\u5bc6\u7b97\u6cd5\uff0cx5c\u5bc6\u94a5\u5305\u542b\u8bc1\u4e66\u94fe\u3002<\/p>\n\n\n\n

    <\/path><\/path><\/svg><\/span>
    {<\/span><\/span>\n  <\/span>"<\/span>kid<\/span>"<\/span>:<\/span> <\/span>"<\/span>AMP\/DEV<\/span>"<\/span>,<\/span><\/span>\n  <\/span>"<\/span>alg<\/span>"<\/span>:<\/span> <\/span>"<\/span>ES256<\/span>"<\/span>,<\/span><\/span>\n  <\/span>"<\/span>x5c<\/span>"<\/span>:<\/span> <\/span>[<\/span><\/span>\n    <\/span>"<\/span>MIIEO...<\/span>"<\/span>,<\/span><\/span>\n    <\/span>"<\/span>MIIDK...<\/span>"<\/span><\/span>\n  <\/span>]<\/span><\/span>\n}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n

    \u4ea4\u6613\u6709\u6548\u8d1f\u8f7d<\/h3>\n\n\n\n
    <\/path><\/path><\/svg><\/span>
    {<\/span><\/span>\n  <\/span>"<\/span>transactionId<\/span>"<\/span>:<\/span> <\/span>"<\/span>1000000831360853<\/span>"<\/span>,<\/span><\/span>\n  <\/span>"<\/span>originalTransactionId<\/span>"<\/span>:<\/span> <\/span>"<\/span>1000000806937552<\/span>"<\/span>,<\/span><\/span>\n  <\/span>"<\/span>webOrderLineItemId<\/span>"<\/span>:<\/span> <\/span>"<\/span>1000000063561721<\/span>"<\/span>,<\/span><\/span>\n  <\/span>"<\/span>bundleId<\/span>"<\/span>:<\/span> <\/span>"<\/span>com.adapty.sample_app<\/span>"<\/span>,<\/span><\/span>\n  <\/span>"<\/span>productId<\/span>"<\/span>:<\/span> <\/span>"<\/span>basic_subscription_1_month<\/span>"<\/span>,<\/span><\/span>\n  <\/span>"<\/span>subscriptionGroupIdentifier<\/span>"<\/span>:<\/span> <\/span>"<\/span>27636320<\/span>"<\/span>,<\/span><\/span>\n  <\/span>"<\/span>purchaseDate<\/span>"<\/span>:<\/span> <\/span>1624446341000<\/span>,<\/span><\/span>\n  <\/span>"<\/span>originalPurchaseDate<\/span>"<\/span>:<\/span> <\/span>1619686337000<\/span>,<\/span><\/span>\n  <\/span>"<\/span>expiresDate<\/span>"<\/span>:<\/span> <\/span>1624446641000<\/span>,<\/span><\/span>\n  <\/span>"<\/span>quantity<\/span>"<\/span>:<\/span> <\/span>1<\/span>,<\/span><\/span>\n  <\/span>"<\/span>type<\/span>"<\/span>:<\/span> <\/span>"<\/span>Auto-Renewable Subscription<\/span>"<\/span>,<\/span><\/span>\n  <\/span>"<\/span>appAccountToken<\/span>"<\/span>:<\/span> <\/span>"<\/span>fd12746f-2d3a-46c8-bff8-55b75ed06aca<\/span>"<\/span>,<\/span><\/span>\n  <\/span>"<\/span>inAppOwnershipType<\/span>"<\/span>:<\/span> <\/span>"<\/span>PURCHASED<\/span>"<\/span>,<\/span><\/span>\n  <\/span>"<\/span>signedDate<\/span>"<\/span>:<\/span> <\/span>1624446484882<\/span>,<\/span><\/span>\n  <\/span>"<\/span>offerType<\/span>"<\/span>:<\/span> <\/span>2<\/span>,<\/span><\/span>\n  <\/span>"<\/span>offerIdentifier<\/span>"<\/span>:<\/span> <\/span>"<\/span>basic_subscription_1_month.pay_as_you_go.3_months<\/span>"<\/span><\/span>\n}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n

    \u82f9\u679c\u6539\u53d8\u5e76\u6269\u5c55\u4e86\u4ea4\u6613\u683c\u5f0f\u3002\u5728\u6211\u770b\u6765\uff0c\u73b0\u5728\u7528\u5b83\u4eec\u5de5\u4f5c\u66f4\u65b9\u4fbf\u4e86\u3002\u60a8\u53ef\u4ee5\u5728\u6587\u6863<\/a>\u4e2d\u4e86\u89e3\u6709\u5173\u65b0\u683c\u5f0f\u7684\u8be6\u7ec6\u4fe1\u606f\u3002\u6211\u4f1a\u5728\u4e0b\u9762\u63cf\u8ff0\u4e00\u4e9b\u6700\u91cd\u8981\u7684\u53d8\u5316\u3002    <\/p>\n\n\n\n