App Store Server API Golang Client
The App Store Server API is a REST API that you call from your server to request and provide information about your customers' in-app purchases.
The App Store Server API is independent of the app’s installation status on the customers’ devices. The App Store server returns information based on a customer’s in-app purchase history regardless of whether the customer installs, removes, or reinstalls the app on their devices.
go get github.com/Jonathan-Mckenzie/appstore
Log in to App Store Connect and complete the following steps:
- Select Users and Access, and then select the Keys tab.
- Select In-App Purchase under the Key Type.
- Click Generate API Key or the Add (+) button.
- Enter a name for the key. The name is for your reference only and isn’t part of the key itself. Click Generate.
- Click Download API Key next to the new API key. And store your private key in a secure place.
import(
"github.com/Jonathan-Mckenzie/appstore"
)
// ACCOUNTPRIVATEKEY is the key file generated from previous step
const ACCOUNTPRIVATEKEY = `
-----BEGIN PRIVATE KEY-----
FAKEACCOUNTKEYBASE64FORMAT
-----END PRIVATE KEY-----
`
func main() {
c := &appstore.StoreConfig{
KeyContent: []byte(ACCOUNTPRIVATEKEY),
KeyID: "FAKEKEYID",
BundleID: "fake.bundle.id",
Issuer: "xxxxx-xx-xx-xx-xxxxxxxxxx",
Sandbox: false,
}
transactionId := "FAKETRANSACTIONID"
a := appstore.NewStoreClient(c)
response, err := a.GetTransactionInfo(context.TODO(), transactionId)
transantions, err := a.ParseSignedTransactions([]{response.SignedTransactionInfo})
if transactions[0].TransactionId == transactionId {
// the transaction is valid
}
}
-
Validate the receipt
- One option could be to validate the receipt with the App Store server through
GetTransactionInfo
API, and then check thetransactionId
in the response matches the one you are looking for.
- One option could be to validate the receipt with the App Store server through
-
Error handling
- handler error per apple store server api error document
- error definition
import(
"github.com/Jonathan-Mckenzie/appstore"
)
// ACCOUNTPRIVATEKEY is the key file generated from previous step
const ACCOUNTPRIVATEKEY = `
-----BEGIN PRIVATE KEY-----
FAKEACCOUNTKEYBASE64FORMAT
-----END PRIVATE KEY-----
`
func main() {
c := &appstore.StoreConfig{
KeyContent: []byte(ACCOUNTPRIVATEKEY),
KeyID: "FAKEKEYID",
BundleID: "fake.bundle.id",
Issuer: "xxxxx-xx-xx-xx-xxxxxxxxxx",
Sandbox: false,
}
invoiceOrderId := "FAKEORDERID"
a := appstore.NewStoreClient(c)
rsp, err := a.LookupOrderID(context.TODO(), invoiceOrderId)
orders, err := a.ParseSignedTransactions(rsp.SignedTransactions)
}
import(
"github.com/Jonathan-Mckenzie/appstore"
)
// ACCOUNTPRIVATEKEY is the key file generated from previous step
const ACCOUNTPRIVATEKEY = `
-----BEGIN PRIVATE KEY-----
FAKEACCOUNTKEYBASE64FORMAT
-----END PRIVATE KEY-----
`
func main() {
c := &appstore.StoreConfig{
KeyContent: []byte(ACCOUNTPRIVATEKEY),
KeyID: "FAKEKEYID",
BundleID: "fake.bundle.id",
Issuer: "xxxxx-xx-xx-xx-xxxxxxxxxx",
Sandbox: false,
}
originalTransactionId := "FAKEORDERID"
a := appstore.NewStoreClient(c)
query := &url.Values{}
query.Set("productType", "AUTO_RENEWABLE")
query.Set("productType", "NON_CONSUMABLE")
gotRsp, err := a.GetTransactionHistory(context.TODO(), originalTransactionId, query)
for _, rsp := range gotRsp {
trans, err := a.ParseSignedTransactions(rsp.SignedTransactions)
}
}
import(
"github.com/Jonathan-Mckenzie/appstore"
)
// ACCOUNTPRIVATEKEY is the key file generated from previous step
const ACCOUNTPRIVATEKEY = `
-----BEGIN PRIVATE KEY-----
FAKEACCOUNTKEYBASE64FORMAT
-----END PRIVATE KEY-----
`
func main() {
c := &appstore.StoreConfig{
KeyContent: []byte(ACCOUNTPRIVATEKEY),
KeyID: "FAKEKEYID",
BundleID: "fake.bundle.id",
Issuer: "xxxxx-xx-xx-xx-xxxxxxxxxx",
Sandbox: false,
}
originalTransactionId := "FAKEORDERID"
a := appstore.NewStoreClient(c)
gotRsp, err := a.GetRefundHistory(context.TODO(), originalTransactionId)
for _, rsp := range gotRsp {
trans, err := a.ParseSignedTransactions(rsp.SignedTransactions)
}
}
import (
"github.com/Jonathan-Mckenzie/appstore"
"github.com/golang-jwt/jwt/v4"
)
func main() {
c := &appstore.StoreConfig{
KeyContent: []byte(ACCOUNTPRIVATEKEY),
KeyID: "FAKEKEYID",
BundleID: "fake.bundle.id",
Issuer: "xxxxx-xx-xx-xx-xxxxxxxxxx",
Sandbox: false,
}
tokenStr := "SignedRenewalInfo Encode String" // or SignedTransactionInfo string
a := appstore.NewStoreClient(c)
token, err := a.ParseNotificationV2(tokenStr)
claims, ok := token.Claims.(jwt.MapClaims)
for key, val := range claims {
fmt.Printf("Key: %v, value: %v\n", key, val) // key value of TransactionInfo
}
}
import (
"github.com/Jonathan-Mckenzie/appstore"
"github.com/golang-jwt/jwt/v4"
)
func main() {
c := &appstore.StoreConfig{
KeyContent: []byte(ACCOUNTPRIVATEKEY),
KeyID: "FAKEKEYID",
BundleID: "fake.bundle.id",
Issuer: "xxxxx-xx-xx-xx-xxxxxxxxxx",
Sandbox: false,
}
tokenStr := "JWSTransactionDecodedPayload Encode String"
a := appstore.NewStoreClient(c)
jws, err := a.ParseNotificationV2WithClaim(tokenStr)
// access the fields of JWSTransactionDecodedPayload from jws directly
}
App Store Server API 1.8
appstore is licensed under the MIT.