{"id":137953,"date":"2021-07-08T00:00:00","date_gmt":"2021-07-08T00:00:00","guid":{"rendered":"https:\/\/adapty.io\/pt-storekit-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\/pt\/blog\/storekit-2\/","title":{"rendered":"As novidades sobre a API StoreKit 2 e como a Apple simplificou a integra\u00e7\u00e3o de compras no aplicativo"},"content":{"rendered":"\n

A Apple apresentou uma nova vers\u00e3o do StoreKit 2 durante a WWDC 2021, realizada recentemente. Trata-se de um framework respons\u00e1vel pela realiza\u00e7\u00e3o de compras (purchases) no iOS. Uma parte dos aplicativos (apps) com recursos de assinatura (subscription) e compra no aplicativo (in-app purchase) cresce continuamente, e a Apple simplificou significativamente a integra\u00e7\u00e3o das compras no aplicativo, lan\u00e7ando o StoreKit 2. Hoje, vamos avaliar o trabalho com o StoreKit 2 por parte do servidor, em outras palavras, com a ajuda da API do App Store Server.<\/p>\n\n\n\n

Solicitar autentica\u00e7\u00e3o<\/h2>\n\n\n\n

Na vers\u00e3o atua da API, voc\u00ea precisa do Segredo Compartilhado (Shared Secret) para enviar uma solicita\u00e7\u00e3o. Trata-se de uma string fixa secreta que pode ser obtida na App Store Connect. Uma nova vers\u00e3o da API usa o padr\u00e3o JSON Web Token (JWT) para autenticar a solicita\u00e7\u00e3o.   <\/p>\n\n\n\n

Gera\u00e7\u00e3o de chaves <\/h3>\n\n\n\n

Antes de tudo, crie uma chave privada<\/a> que ser\u00e1 usada para autorizar as solicita\u00e7\u00f5es. Abra a App Store Connect e navegue at\u00e9 a se\u00e7\u00e3o Usu\u00e1rios e Acesso, depois clique na aba Chaves. Selecione o tipo de chave para compras no aplicativo. Fa\u00e7a o download de uma nova chave. Voc\u00ea tamb\u00e9m vai precisar de sua ID – voc\u00ea pode copi\u00e1-la na mesma p\u00e1gina do Issue ID que pode ser encontrada na aba da API da App Store Connect.<\/p>\n\n\n\n

\"Creating
Cria\u00e7\u00e3o de uma chave privada para trabalhar com a API da App Store Server<\/figcaption><\/figure>\n\n\n\n

Como criar um token<\/h3>\n\n\n\n

O pr\u00f3ximo passo \u00e9 criar um token que ser\u00e1 usado para autorizar as solicita\u00e7\u00f5es. Este processo \u00e9 descrito detalhadamente na documenta\u00e7\u00e3o<\/a>, portanto n\u00e3o \u00e9 necess\u00e1rio dedicar muita aten\u00e7\u00e3o a ele neste artigo. Segue um exemplo de uma implementa\u00e7\u00e3o j\u00e1 feita no Python. Vale destacar que n\u00e3o faz sentido gerar um novo token para cada nova solicita\u00e7\u00e3o. Ao criar um token, voc\u00ea fixa sua vida \u00fatil em at\u00e9 60 minutos e usa o mesmo token durante esse per\u00edodo. <\/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

Transa\u00e7\u00f5es assinadas<\/h2>\n\n\n\n

Em uma nova vers\u00e3o da API, todas as transa\u00e7\u00f5es retornam no padr\u00e3o JSON Web Signature (JWS). \u00c9 uma string que consiste em tr\u00eas partes divididas por pontos.  <\/p>\n\n\n\n

    \n
  1. Cabe\u00e7alho base64.<\/li>\n\n\n\n
  2. Carga \u00fatil da transa\u00e7\u00e3o com base64.<\/li>\n\n\n\n
  3. Assinatura da transa\u00e7\u00e3o.<\/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

    Cabe\u00e7alho da transa\u00e7\u00e3o<\/h3>\n\n\n\n

    \u00c9 necess\u00e1rio fazer um cabe\u00e7alho para garantir que a transa\u00e7\u00e3o seja aut\u00eantica. A chave Alg cont\u00e9m um algoritmo de criptografia, a chave x5c cont\u00e9m uma cadeia de certificados.<\/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

    Carga \u00fatil da transa\u00e7\u00e3o<\/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

    A Apple mudou e ampliou o formato da transa\u00e7\u00e3o. Do meu ponto de vista, agora, ficou mais pr\u00e1tico trabalhar com eles. Voc\u00ea pode obter mais informa\u00e7\u00f5es sobre um novo formato na documenta\u00e7\u00e3o<\/a>. A seguir, detalharei as mudan\u00e7as mais importantes.    <\/p>\n\n\n\n