/

/

WWDC22 Overview: How...

WWDC22 Overview: How To iIntegrate and Migrate In-App Purchases to App Store Server API

Suren

Jun 10, 2022

Hey everyone, today we’re going to continue our WWDC22 blog post series on what’s new with in-app purchases. We’ve already covered some of the updates: enhancements to StoreKit 2 and App Store Server API. 

Today, we’ll focus on the next updates that were announced during the session Explore in-app purchase integration and migration. The session is divided into two chapters – App Store Server API and App Store Server Notifications Version 2.

In this article, I’ll mostly refer to the first part of the video. We’ll talk about App Store Server API – powerful, secure, and with efficient server-to-server endpoints, then we’ll explain how to migrate to it.

The main idea behind this API is pretty clear: to give you the all data you need about in-app purchases. 

App Store API was introduced on WWDC 2021. These are two great sessions that I highly recommend to watch; however, they won’t affect your understanding of today’s topic. 

What we will cover: 

  • How to use the App Store Server API

  • How to sign JSON Web Tokens

  • How to verify signed transactions

  • How to migrate from verifyReceipt 

So, let’s get going!

WWDC22 overview

Using the App Store Server API

Signing JSON Web Tokens

JSON Web Token is needed for Apple to authenticate you when calling the App Store Server API. This token should be used as an authorization header in each of your server’s requests.
JWT consist of: header, payload, and the signature.

How to construct JSON Web Token for your app?

On the picture below you can see the structure of the JWT, header and payload.

The token itself can be divided into three parts, separated by periods:

  1. The base64 encoded header

  2. The base64 encoded payload

  3. The signature, which is composed of the base64 encoded header + base64 encoded payload, signed using your signing secret.

Header 

The header consists of metadata that represents the information on how to sign your data. 

Pay attention to the key ID field (kid) – this is your private key ID from the App Store Connect. This key ID should correspond to the key that you use for JWT signature.

Payload 

Payload keeps all the data about your application. To learn more about this field please read the official documentation from Apple

For additional info on how to get your API key please read this article

Once you receive all the data that you need for the JWT, you need to sign the JWT ​​using the certificate that corresponds to the key ID.

Let’s take a closer look at an example (pseudocode). Please note that the final code will look different depending on the programming language, the chosen tools, and libraries with which you will implement it. But the logic behind remains the same.

import jwtLibrary;

var privateKey = readFile(“/path/to/private_key.key)
var token = jwtLibrary.sign(payload, privateKey, header)

One your preferred library generates token, you can paste it into cURL that will get subscription statuses by `originalTransactionId`.

This is an example:

curl -v -S -H 'Content-Type: application/json' \
	-H 'Accept: application/json' \
	-H 'Authorization: Bearer ${token}' \
	https://api.storekit.itunes.apple.com/inApps/v1/subscriptions/${originalTransactionId}

Don’t forget to:

  • replace ${token} with the parameter that you’ve generated in example above. 

  • replace ${originalTransactionId} – the Id, with which one you’d like to get the data.

Verifying signed transactions

Let’s discuss how to verify the transactions that you receive from Apple and that were signed by the App Store. 

Signed transactions are JSON and are cryptographically signed, so if someone would try to replace it between App Store and your server, you can easily detect it. 

These transactions are signed in the JWS format – Json Web Signature (do not confuse this with JWT, which was discussed above). By verifying this object you receive the data from the App Store and can ensure that it was not tampered by anyone. 

How can I verify a signed transaction?

  1. Decode base64 header

  2. By `alg claim` in this base64 header you could understand which algorithm you should use. It will be used for the JWS verification. 

  3. Verify certificate chain in the x5c claim

Now, once we verified this data, we are on the safe side – no one tampered our data. 

You can learn more about JWS here. Also, please read the App Store Server API documentation to learn more about JWSTransaction.

What is the x5c chain? 

This is a chain of certificates, the successful verification of which means that the data can be trusted and is signed by Apple. 

What is important for the certificate chain is the order. At the beginning you’ll get the root certificate. The root certificate may be followed by additional certificates from the chain. Each following certificate is signed by the previous one. The last certificate in this chain is referred to as the leaf certificate. The first certificate is referred to as the root certificate, and is self-signed. 

This certificate should match to the root certificate you obtain from the Apple’s Certificate Authority. If it does not, then the verification chain will be defined as failed. 

The last certificate (leaf certificate) is used for JWS signing. 

Let’s take a look at the JWS header: 

At the beginning of the first line, in the `alg` field, there is the name of the algorithm that is used for the JWS signing. Next, in the `x5c`, there is a chain of certificates listed in order. 

Let’s look a bit more closely at what x5c certificate chain generation looks like. 

At the beginning, we take a root certificate from the Apple’s Certificate Authority. Next, we sign the intermediate certificate. There might be several certificates in this chain, and as we discussed above, each following certificate is signed by previous one. In the example below we consider the one intermediate certificate. Then, this intermediate certificate signs the leaf certificate. 

Ok, we’ve described the way this chain generates. Now it’s time to move on to the next chapter – how you can verify it. 

This part is simple – you just need to reverse the process.

First, make sure that the leaf certificate is signed by intermediate one. Then, that intermediate certificate should be signed by the root certificate. And the root certificate should match the one one of Apple’s Certificate Authorities. If all steps are successful, the chain is verified and counted as valid. 

Let’s discuss a specific method of chain certificate verification. 

This is the command fot x5c chain using OpenSSL verification: 

`openssl verify -trusted AppleRootCA-G3.pem -untrusted AppleWWDRCAG6.pem leaf.pem`

The command `verify` initiates the process of certificate verification. 

With `-trusted` we send the certificate that we trust and that will be used for the verification of the following certificates. This should be root certificate that was obtained from Apple’s Certificate Authority.

With `-untrusted` we send a certificate that wasn’t verified yet, but that we’d like to verify. 

As a first parameter we use the WWDR certificate that received from the Apple’s Certificate Authority and signed by root certificate. This should match to the second certificate from the x5c chain. The last parameter is a leaf certificate that was signed by the previous certificate. In case of successful verification, you’ll receive a success code, and in case of failed verification, you’ll receive an error code. If verification is unsuccessful, the data shouldn’t be used. 

More information about the `verify` command in `openssl` is here.

The information on `openssl` is here.

Migration from verifyReceipt to App Store Server API

In this part, we’ll explore the several corner cases. 

How to check the subscription status of the particular user

Previously, you had to call verifyReceipt and define the status by checking several fields from the response. Now, with App Store Server API you can call GET /inApps/v1/subscriptions/{originalTransactionId}  and receive all the needed data, such as subscription status, renewal info and other pieces of data in one response. 

How to receive the latest transactions of the user 

The next case described is when you’d like to get the latest transactions of the user to check what he purchased, whether the subscription is auto renewed, or whether there were changes like upgrades, downgrades, or plan switches.

As in the previous example, with the previous API version you had to call verifyReceipt and get the data from the responseBody.Receipt.In_app and responseBody.Latest_receipt_info fields. 

With the new App Store Server API you can refer to the GET /inApps/v1/history/{originalTransactionId} endpoint that covers all needed data. 
And last but not least – the new appAccountToken field that fetches UUID. We’ve covered this field in our previous article, but just to remind you: this field lets oyu add the unique ID of the users from your system just to connect your user with their purchases. In the previous API version there was an analogue of this field –  applicationUsername – that fetched the string, but the official documentation recommended sending UUID into this field. And once you send the UUID format string into this field, you’ll see this parameter automatically in `appAccountToken`. The needed value will appear in StoreKit Transaction, App Store API, and App Store Server Notifications.

Conclusion

In this article, we explored the new capabilities of App Store Server API, how to integrate and migrate in-app subscriptions into API, and how to sign JSON Web Tokens and verify signed transactions.

If you still have any questions about the logic behind these updates, please feel free to reach out to us. Qonversion provides a complete cross-platform infrastructure that allows you to make and restore purchases, validate receipts, and provide your app with an accurate subscription status without the need to build your server. 

WWDC22 Overview: How To iIntegrate and Migrate In-App Purchases to App Store Server API

Suren

Jun 10, 2022

Hey everyone, today we’re going to continue our WWDC22 blog post series on what’s new with in-app purchases. We’ve already covered some of the updates: enhancements to StoreKit 2 and App Store Server API. 

Today, we’ll focus on the next updates that were announced during the session Explore in-app purchase integration and migration. The session is divided into two chapters – App Store Server API and App Store Server Notifications Version 2.

In this article, I’ll mostly refer to the first part of the video. We’ll talk about App Store Server API – powerful, secure, and with efficient server-to-server endpoints, then we’ll explain how to migrate to it.

The main idea behind this API is pretty clear: to give you the all data you need about in-app purchases. 

App Store API was introduced on WWDC 2021. These are two great sessions that I highly recommend to watch; however, they won’t affect your understanding of today’s topic. 

What we will cover: 

  • How to use the App Store Server API

  • How to sign JSON Web Tokens

  • How to verify signed transactions

  • How to migrate from verifyReceipt 

So, let’s get going!

WWDC22 overview

Using the App Store Server API

Signing JSON Web Tokens

JSON Web Token is needed for Apple to authenticate you when calling the App Store Server API. This token should be used as an authorization header in each of your server’s requests.
JWT consist of: header, payload, and the signature.

How to construct JSON Web Token for your app?

On the picture below you can see the structure of the JWT, header and payload.

The token itself can be divided into three parts, separated by periods:

  1. The base64 encoded header

  2. The base64 encoded payload

  3. The signature, which is composed of the base64 encoded header + base64 encoded payload, signed using your signing secret.

Header 

The header consists of metadata that represents the information on how to sign your data. 

Pay attention to the key ID field (kid) – this is your private key ID from the App Store Connect. This key ID should correspond to the key that you use for JWT signature.

Payload 

Payload keeps all the data about your application. To learn more about this field please read the official documentation from Apple

For additional info on how to get your API key please read this article

Once you receive all the data that you need for the JWT, you need to sign the JWT ​​using the certificate that corresponds to the key ID.

Let’s take a closer look at an example (pseudocode). Please note that the final code will look different depending on the programming language, the chosen tools, and libraries with which you will implement it. But the logic behind remains the same.

import jwtLibrary;

var privateKey = readFile(“/path/to/private_key.key)
var token = jwtLibrary.sign(payload, privateKey, header)

One your preferred library generates token, you can paste it into cURL that will get subscription statuses by `originalTransactionId`.

This is an example:

curl -v -S -H 'Content-Type: application/json' \
	-H 'Accept: application/json' \
	-H 'Authorization: Bearer ${token}' \
	https://api.storekit.itunes.apple.com/inApps/v1/subscriptions/${originalTransactionId}

Don’t forget to:

  • replace ${token} with the parameter that you’ve generated in example above. 

  • replace ${originalTransactionId} – the Id, with which one you’d like to get the data.

Verifying signed transactions

Let’s discuss how to verify the transactions that you receive from Apple and that were signed by the App Store. 

Signed transactions are JSON and are cryptographically signed, so if someone would try to replace it between App Store and your server, you can easily detect it. 

These transactions are signed in the JWS format – Json Web Signature (do not confuse this with JWT, which was discussed above). By verifying this object you receive the data from the App Store and can ensure that it was not tampered by anyone. 

How can I verify a signed transaction?

  1. Decode base64 header

  2. By `alg claim` in this base64 header you could understand which algorithm you should use. It will be used for the JWS verification. 

  3. Verify certificate chain in the x5c claim

Now, once we verified this data, we are on the safe side – no one tampered our data. 

You can learn more about JWS here. Also, please read the App Store Server API documentation to learn more about JWSTransaction.

What is the x5c chain? 

This is a chain of certificates, the successful verification of which means that the data can be trusted and is signed by Apple. 

What is important for the certificate chain is the order. At the beginning you’ll get the root certificate. The root certificate may be followed by additional certificates from the chain. Each following certificate is signed by the previous one. The last certificate in this chain is referred to as the leaf certificate. The first certificate is referred to as the root certificate, and is self-signed. 

This certificate should match to the root certificate you obtain from the Apple’s Certificate Authority. If it does not, then the verification chain will be defined as failed. 

The last certificate (leaf certificate) is used for JWS signing. 

Let’s take a look at the JWS header: 

At the beginning of the first line, in the `alg` field, there is the name of the algorithm that is used for the JWS signing. Next, in the `x5c`, there is a chain of certificates listed in order. 

Let’s look a bit more closely at what x5c certificate chain generation looks like. 

At the beginning, we take a root certificate from the Apple’s Certificate Authority. Next, we sign the intermediate certificate. There might be several certificates in this chain, and as we discussed above, each following certificate is signed by previous one. In the example below we consider the one intermediate certificate. Then, this intermediate certificate signs the leaf certificate. 

Ok, we’ve described the way this chain generates. Now it’s time to move on to the next chapter – how you can verify it. 

This part is simple – you just need to reverse the process.

First, make sure that the leaf certificate is signed by intermediate one. Then, that intermediate certificate should be signed by the root certificate. And the root certificate should match the one one of Apple’s Certificate Authorities. If all steps are successful, the chain is verified and counted as valid. 

Let’s discuss a specific method of chain certificate verification. 

This is the command fot x5c chain using OpenSSL verification: 

`openssl verify -trusted AppleRootCA-G3.pem -untrusted AppleWWDRCAG6.pem leaf.pem`

The command `verify` initiates the process of certificate verification. 

With `-trusted` we send the certificate that we trust and that will be used for the verification of the following certificates. This should be root certificate that was obtained from Apple’s Certificate Authority.

With `-untrusted` we send a certificate that wasn’t verified yet, but that we’d like to verify. 

As a first parameter we use the WWDR certificate that received from the Apple’s Certificate Authority and signed by root certificate. This should match to the second certificate from the x5c chain. The last parameter is a leaf certificate that was signed by the previous certificate. In case of successful verification, you’ll receive a success code, and in case of failed verification, you’ll receive an error code. If verification is unsuccessful, the data shouldn’t be used. 

More information about the `verify` command in `openssl` is here.

The information on `openssl` is here.

Migration from verifyReceipt to App Store Server API

In this part, we’ll explore the several corner cases. 

How to check the subscription status of the particular user

Previously, you had to call verifyReceipt and define the status by checking several fields from the response. Now, with App Store Server API you can call GET /inApps/v1/subscriptions/{originalTransactionId}  and receive all the needed data, such as subscription status, renewal info and other pieces of data in one response. 

How to receive the latest transactions of the user 

The next case described is when you’d like to get the latest transactions of the user to check what he purchased, whether the subscription is auto renewed, or whether there were changes like upgrades, downgrades, or plan switches.

As in the previous example, with the previous API version you had to call verifyReceipt and get the data from the responseBody.Receipt.In_app and responseBody.Latest_receipt_info fields. 

With the new App Store Server API you can refer to the GET /inApps/v1/history/{originalTransactionId} endpoint that covers all needed data. 
And last but not least – the new appAccountToken field that fetches UUID. We’ve covered this field in our previous article, but just to remind you: this field lets oyu add the unique ID of the users from your system just to connect your user with their purchases. In the previous API version there was an analogue of this field –  applicationUsername – that fetched the string, but the official documentation recommended sending UUID into this field. And once you send the UUID format string into this field, you’ll see this parameter automatically in `appAccountToken`. The needed value will appear in StoreKit Transaction, App Store API, and App Store Server Notifications.

Conclusion

In this article, we explored the new capabilities of App Store Server API, how to integrate and migrate in-app subscriptions into API, and how to sign JSON Web Tokens and verify signed transactions.

If you still have any questions about the logic behind these updates, please feel free to reach out to us. Qonversion provides a complete cross-platform infrastructure that allows you to make and restore purchases, validate receipts, and provide your app with an accurate subscription status without the need to build your server. 

WWDC22 Overview: How To iIntegrate and Migrate In-App Purchases to App Store Server API

Suren

Jun 10, 2022

Hey everyone, today we’re going to continue our WWDC22 blog post series on what’s new with in-app purchases. We’ve already covered some of the updates: enhancements to StoreKit 2 and App Store Server API. 

Today, we’ll focus on the next updates that were announced during the session Explore in-app purchase integration and migration. The session is divided into two chapters – App Store Server API and App Store Server Notifications Version 2.

In this article, I’ll mostly refer to the first part of the video. We’ll talk about App Store Server API – powerful, secure, and with efficient server-to-server endpoints, then we’ll explain how to migrate to it.

The main idea behind this API is pretty clear: to give you the all data you need about in-app purchases. 

App Store API was introduced on WWDC 2021. These are two great sessions that I highly recommend to watch; however, they won’t affect your understanding of today’s topic. 

What we will cover: 

  • How to use the App Store Server API

  • How to sign JSON Web Tokens

  • How to verify signed transactions

  • How to migrate from verifyReceipt 

So, let’s get going!

WWDC22 overview

Using the App Store Server API

Signing JSON Web Tokens

JSON Web Token is needed for Apple to authenticate you when calling the App Store Server API. This token should be used as an authorization header in each of your server’s requests.
JWT consist of: header, payload, and the signature.

How to construct JSON Web Token for your app?

On the picture below you can see the structure of the JWT, header and payload.

The token itself can be divided into three parts, separated by periods:

  1. The base64 encoded header

  2. The base64 encoded payload

  3. The signature, which is composed of the base64 encoded header + base64 encoded payload, signed using your signing secret.

Header 

The header consists of metadata that represents the information on how to sign your data. 

Pay attention to the key ID field (kid) – this is your private key ID from the App Store Connect. This key ID should correspond to the key that you use for JWT signature.

Payload 

Payload keeps all the data about your application. To learn more about this field please read the official documentation from Apple

For additional info on how to get your API key please read this article

Once you receive all the data that you need for the JWT, you need to sign the JWT ​​using the certificate that corresponds to the key ID.

Let’s take a closer look at an example (pseudocode). Please note that the final code will look different depending on the programming language, the chosen tools, and libraries with which you will implement it. But the logic behind remains the same.

import jwtLibrary;

var privateKey = readFile(“/path/to/private_key.key)
var token = jwtLibrary.sign(payload, privateKey, header)

One your preferred library generates token, you can paste it into cURL that will get subscription statuses by `originalTransactionId`.

This is an example:

curl -v -S -H 'Content-Type: application/json' \
	-H 'Accept: application/json' \
	-H 'Authorization: Bearer ${token}' \
	https://api.storekit.itunes.apple.com/inApps/v1/subscriptions/${originalTransactionId}

Don’t forget to:

  • replace ${token} with the parameter that you’ve generated in example above. 

  • replace ${originalTransactionId} – the Id, with which one you’d like to get the data.

Verifying signed transactions

Let’s discuss how to verify the transactions that you receive from Apple and that were signed by the App Store. 

Signed transactions are JSON and are cryptographically signed, so if someone would try to replace it between App Store and your server, you can easily detect it. 

These transactions are signed in the JWS format – Json Web Signature (do not confuse this with JWT, which was discussed above). By verifying this object you receive the data from the App Store and can ensure that it was not tampered by anyone. 

How can I verify a signed transaction?

  1. Decode base64 header

  2. By `alg claim` in this base64 header you could understand which algorithm you should use. It will be used for the JWS verification. 

  3. Verify certificate chain in the x5c claim

Now, once we verified this data, we are on the safe side – no one tampered our data. 

You can learn more about JWS here. Also, please read the App Store Server API documentation to learn more about JWSTransaction.

What is the x5c chain? 

This is a chain of certificates, the successful verification of which means that the data can be trusted and is signed by Apple. 

What is important for the certificate chain is the order. At the beginning you’ll get the root certificate. The root certificate may be followed by additional certificates from the chain. Each following certificate is signed by the previous one. The last certificate in this chain is referred to as the leaf certificate. The first certificate is referred to as the root certificate, and is self-signed. 

This certificate should match to the root certificate you obtain from the Apple’s Certificate Authority. If it does not, then the verification chain will be defined as failed. 

The last certificate (leaf certificate) is used for JWS signing. 

Let’s take a look at the JWS header: 

At the beginning of the first line, in the `alg` field, there is the name of the algorithm that is used for the JWS signing. Next, in the `x5c`, there is a chain of certificates listed in order. 

Let’s look a bit more closely at what x5c certificate chain generation looks like. 

At the beginning, we take a root certificate from the Apple’s Certificate Authority. Next, we sign the intermediate certificate. There might be several certificates in this chain, and as we discussed above, each following certificate is signed by previous one. In the example below we consider the one intermediate certificate. Then, this intermediate certificate signs the leaf certificate. 

Ok, we’ve described the way this chain generates. Now it’s time to move on to the next chapter – how you can verify it. 

This part is simple – you just need to reverse the process.

First, make sure that the leaf certificate is signed by intermediate one. Then, that intermediate certificate should be signed by the root certificate. And the root certificate should match the one one of Apple’s Certificate Authorities. If all steps are successful, the chain is verified and counted as valid. 

Let’s discuss a specific method of chain certificate verification. 

This is the command fot x5c chain using OpenSSL verification: 

`openssl verify -trusted AppleRootCA-G3.pem -untrusted AppleWWDRCAG6.pem leaf.pem`

The command `verify` initiates the process of certificate verification. 

With `-trusted` we send the certificate that we trust and that will be used for the verification of the following certificates. This should be root certificate that was obtained from Apple’s Certificate Authority.

With `-untrusted` we send a certificate that wasn’t verified yet, but that we’d like to verify. 

As a first parameter we use the WWDR certificate that received from the Apple’s Certificate Authority and signed by root certificate. This should match to the second certificate from the x5c chain. The last parameter is a leaf certificate that was signed by the previous certificate. In case of successful verification, you’ll receive a success code, and in case of failed verification, you’ll receive an error code. If verification is unsuccessful, the data shouldn’t be used. 

More information about the `verify` command in `openssl` is here.

The information on `openssl` is here.

Migration from verifyReceipt to App Store Server API

In this part, we’ll explore the several corner cases. 

How to check the subscription status of the particular user

Previously, you had to call verifyReceipt and define the status by checking several fields from the response. Now, with App Store Server API you can call GET /inApps/v1/subscriptions/{originalTransactionId}  and receive all the needed data, such as subscription status, renewal info and other pieces of data in one response. 

How to receive the latest transactions of the user 

The next case described is when you’d like to get the latest transactions of the user to check what he purchased, whether the subscription is auto renewed, or whether there were changes like upgrades, downgrades, or plan switches.

As in the previous example, with the previous API version you had to call verifyReceipt and get the data from the responseBody.Receipt.In_app and responseBody.Latest_receipt_info fields. 

With the new App Store Server API you can refer to the GET /inApps/v1/history/{originalTransactionId} endpoint that covers all needed data. 
And last but not least – the new appAccountToken field that fetches UUID. We’ve covered this field in our previous article, but just to remind you: this field lets oyu add the unique ID of the users from your system just to connect your user with their purchases. In the previous API version there was an analogue of this field –  applicationUsername – that fetched the string, but the official documentation recommended sending UUID into this field. And once you send the UUID format string into this field, you’ll see this parameter automatically in `appAccountToken`. The needed value will appear in StoreKit Transaction, App Store API, and App Store Server Notifications.

Conclusion

In this article, we explored the new capabilities of App Store Server API, how to integrate and migrate in-app subscriptions into API, and how to sign JSON Web Tokens and verify signed transactions.

If you still have any questions about the logic behind these updates, please feel free to reach out to us. Qonversion provides a complete cross-platform infrastructure that allows you to make and restore purchases, validate receipts, and provide your app with an accurate subscription status without the need to build your server. 

WWDC22 Overview: How To iIntegrate and Migrate In-App Purchases to App Store Server API

Suren

Jun 10, 2022

Hey everyone, today we’re going to continue our WWDC22 blog post series on what’s new with in-app purchases. We’ve already covered some of the updates: enhancements to StoreKit 2 and App Store Server API. 

Today, we’ll focus on the next updates that were announced during the session Explore in-app purchase integration and migration. The session is divided into two chapters – App Store Server API and App Store Server Notifications Version 2.

In this article, I’ll mostly refer to the first part of the video. We’ll talk about App Store Server API – powerful, secure, and with efficient server-to-server endpoints, then we’ll explain how to migrate to it.

The main idea behind this API is pretty clear: to give you the all data you need about in-app purchases. 

App Store API was introduced on WWDC 2021. These are two great sessions that I highly recommend to watch; however, they won’t affect your understanding of today’s topic. 

What we will cover: 

  • How to use the App Store Server API

  • How to sign JSON Web Tokens

  • How to verify signed transactions

  • How to migrate from verifyReceipt 

So, let’s get going!

WWDC22 overview

Using the App Store Server API

Signing JSON Web Tokens

JSON Web Token is needed for Apple to authenticate you when calling the App Store Server API. This token should be used as an authorization header in each of your server’s requests.
JWT consist of: header, payload, and the signature.

How to construct JSON Web Token for your app?

On the picture below you can see the structure of the JWT, header and payload.

The token itself can be divided into three parts, separated by periods:

  1. The base64 encoded header

  2. The base64 encoded payload

  3. The signature, which is composed of the base64 encoded header + base64 encoded payload, signed using your signing secret.

Header 

The header consists of metadata that represents the information on how to sign your data. 

Pay attention to the key ID field (kid) – this is your private key ID from the App Store Connect. This key ID should correspond to the key that you use for JWT signature.

Payload 

Payload keeps all the data about your application. To learn more about this field please read the official documentation from Apple

For additional info on how to get your API key please read this article

Once you receive all the data that you need for the JWT, you need to sign the JWT ​​using the certificate that corresponds to the key ID.

Let’s take a closer look at an example (pseudocode). Please note that the final code will look different depending on the programming language, the chosen tools, and libraries with which you will implement it. But the logic behind remains the same.

import jwtLibrary;

var privateKey = readFile(“/path/to/private_key.key)
var token = jwtLibrary.sign(payload, privateKey, header)

One your preferred library generates token, you can paste it into cURL that will get subscription statuses by `originalTransactionId`.

This is an example:

curl -v -S -H 'Content-Type: application/json' \
	-H 'Accept: application/json' \
	-H 'Authorization: Bearer ${token}' \
	https://api.storekit.itunes.apple.com/inApps/v1/subscriptions/${originalTransactionId}

Don’t forget to:

  • replace ${token} with the parameter that you’ve generated in example above. 

  • replace ${originalTransactionId} – the Id, with which one you’d like to get the data.

Verifying signed transactions

Let’s discuss how to verify the transactions that you receive from Apple and that were signed by the App Store. 

Signed transactions are JSON and are cryptographically signed, so if someone would try to replace it between App Store and your server, you can easily detect it. 

These transactions are signed in the JWS format – Json Web Signature (do not confuse this with JWT, which was discussed above). By verifying this object you receive the data from the App Store and can ensure that it was not tampered by anyone. 

How can I verify a signed transaction?

  1. Decode base64 header

  2. By `alg claim` in this base64 header you could understand which algorithm you should use. It will be used for the JWS verification. 

  3. Verify certificate chain in the x5c claim

Now, once we verified this data, we are on the safe side – no one tampered our data. 

You can learn more about JWS here. Also, please read the App Store Server API documentation to learn more about JWSTransaction.

What is the x5c chain? 

This is a chain of certificates, the successful verification of which means that the data can be trusted and is signed by Apple. 

What is important for the certificate chain is the order. At the beginning you’ll get the root certificate. The root certificate may be followed by additional certificates from the chain. Each following certificate is signed by the previous one. The last certificate in this chain is referred to as the leaf certificate. The first certificate is referred to as the root certificate, and is self-signed. 

This certificate should match to the root certificate you obtain from the Apple’s Certificate Authority. If it does not, then the verification chain will be defined as failed. 

The last certificate (leaf certificate) is used for JWS signing. 

Let’s take a look at the JWS header: 

At the beginning of the first line, in the `alg` field, there is the name of the algorithm that is used for the JWS signing. Next, in the `x5c`, there is a chain of certificates listed in order. 

Let’s look a bit more closely at what x5c certificate chain generation looks like. 

At the beginning, we take a root certificate from the Apple’s Certificate Authority. Next, we sign the intermediate certificate. There might be several certificates in this chain, and as we discussed above, each following certificate is signed by previous one. In the example below we consider the one intermediate certificate. Then, this intermediate certificate signs the leaf certificate. 

Ok, we’ve described the way this chain generates. Now it’s time to move on to the next chapter – how you can verify it. 

This part is simple – you just need to reverse the process.

First, make sure that the leaf certificate is signed by intermediate one. Then, that intermediate certificate should be signed by the root certificate. And the root certificate should match the one one of Apple’s Certificate Authorities. If all steps are successful, the chain is verified and counted as valid. 

Let’s discuss a specific method of chain certificate verification. 

This is the command fot x5c chain using OpenSSL verification: 

`openssl verify -trusted AppleRootCA-G3.pem -untrusted AppleWWDRCAG6.pem leaf.pem`

The command `verify` initiates the process of certificate verification. 

With `-trusted` we send the certificate that we trust and that will be used for the verification of the following certificates. This should be root certificate that was obtained from Apple’s Certificate Authority.

With `-untrusted` we send a certificate that wasn’t verified yet, but that we’d like to verify. 

As a first parameter we use the WWDR certificate that received from the Apple’s Certificate Authority and signed by root certificate. This should match to the second certificate from the x5c chain. The last parameter is a leaf certificate that was signed by the previous certificate. In case of successful verification, you’ll receive a success code, and in case of failed verification, you’ll receive an error code. If verification is unsuccessful, the data shouldn’t be used. 

More information about the `verify` command in `openssl` is here.

The information on `openssl` is here.

Migration from verifyReceipt to App Store Server API

In this part, we’ll explore the several corner cases. 

How to check the subscription status of the particular user

Previously, you had to call verifyReceipt and define the status by checking several fields from the response. Now, with App Store Server API you can call GET /inApps/v1/subscriptions/{originalTransactionId}  and receive all the needed data, such as subscription status, renewal info and other pieces of data in one response. 

How to receive the latest transactions of the user 

The next case described is when you’d like to get the latest transactions of the user to check what he purchased, whether the subscription is auto renewed, or whether there were changes like upgrades, downgrades, or plan switches.

As in the previous example, with the previous API version you had to call verifyReceipt and get the data from the responseBody.Receipt.In_app and responseBody.Latest_receipt_info fields. 

With the new App Store Server API you can refer to the GET /inApps/v1/history/{originalTransactionId} endpoint that covers all needed data. 
And last but not least – the new appAccountToken field that fetches UUID. We’ve covered this field in our previous article, but just to remind you: this field lets oyu add the unique ID of the users from your system just to connect your user with their purchases. In the previous API version there was an analogue of this field –  applicationUsername – that fetched the string, but the official documentation recommended sending UUID into this field. And once you send the UUID format string into this field, you’ll see this parameter automatically in `appAccountToken`. The needed value will appear in StoreKit Transaction, App Store API, and App Store Server Notifications.

Conclusion

In this article, we explored the new capabilities of App Store Server API, how to integrate and migrate in-app subscriptions into API, and how to sign JSON Web Tokens and verify signed transactions.

If you still have any questions about the logic behind these updates, please feel free to reach out to us. Qonversion provides a complete cross-platform infrastructure that allows you to make and restore purchases, validate receipts, and provide your app with an accurate subscription status without the need to build your server. 

Start Now for Free

Or book a demo with our team to learn more about Qonversion

Start Now for Free

Or book a demo with our team to learn more about Qonversion

Start Now for Free

Or book a demo with our team to learn more about Qonversion

Read more

Read more