Skip to content

Commit

Permalink
feat: added new fields into the types. also updated readme
Browse files Browse the repository at this point in the history
  • Loading branch information
izniburak committed Oct 4, 2023
1 parent 4f172dc commit 5bb8650
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 31 deletions.
14 changes: 12 additions & 2 deletions readme.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
# App Store Server Notifications in Golang [![](https://github.com/izniburak/appstore-notifications-go/actions/workflows/go.yml/badge.svg)](https://github.com/izniburak/appstore-notifications-go/actions) [![PkgGoDev](https://pkg.go.dev/badge/github.com/izniburak/appstore-notifications-go)](https://pkg.go.dev/github.com/izniburak/appstore-notifications-go)

***appstore-notifications-go*** package helps you to handle and process the Apple's [App Store Server Notifications](https://developer.apple.com/documentation/appstoreservernotifications) in Golang.
***appstore-notifications-go*** is a Golang package, which helps you to handle, parse and verify the Apple's [App Store Server Notifications](https://developer.apple.com/documentation/appstoreservernotifications).

> App Store Server Notifications is a service provided by Apple for its App Store. It's designed to notify developers about key events and changes related to their app's in-app purchases and subscriptions. By integrating this service into their server-side logic, developers can receive real-time (I think, almost real-time) updates about various events without having to repeatedly poll the Apple servers.
## Install
To install the package, you can use following command on your terminal in your project directory:

```bash
go get github.com/izniburak/appstore-notifications-go
Expand Down Expand Up @@ -38,9 +41,16 @@ func main() {
}

appStoreServerNotification := appstore.New(request.SignedPayload, rootCert)
fmt.Printf("App Store Server Notification is valid?: %t\n", appStoreServerNotification.isValid)
fmt.Printf("App Store Server Notification is valid?: %t\n", appStoreServerNotification.IsValid)
fmt.Printf("Product Id: %s\n", appStoreServerNotification.TransactionInfo.ProductId)
}
```
You can access the all data in the payload by using one of the 4 params in instance of the `AppStoreServerNotification`:

- _instance_***.Payload***: Access the [Payload](https://developer.apple.com/documentation/appstoreservernotifications/responsebodyv2decodedpayload).
- _instance_***.TransactionInfo***: Access the [Transaction Info](https://developer.apple.com/documentation/appstoreservernotifications/jwstransactiondecodedpayload).
- _instance_***.RenewalInfo***: Access the [Renewal Info](https://developer.apple.com/documentation/appstoreservernotifications/jwsrenewalinfodecodedpayload).
- _instance_***.IsValid***: Check the payload parsed and verified successfully.

## Contributing

Expand Down
81 changes: 55 additions & 26 deletions types.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ type AppStoreServerNotification struct {
Payload *NotificationPayload
TransactionInfo *TransactionInfo
RenewalInfo *RenewalInfo
isValid bool
IsValid bool
}

type AppStoreServerRequest struct {
Expand All @@ -21,47 +21,76 @@ type NotificationHeader struct {

type NotificationPayload struct {
jwt.StandardClaims
NotificationType string `json:"notificationType"`
Subtype string `json:"subtype"`
NotificationUUID string `json:"notificationUUID"`
NotificationVersion string `json:"notificationVersion"`
Data NotificationData `json:"data"`
NotificationType string `json:"notificationType"`
Subtype string `json:"subtype"`
NotificationUUID string `json:"notificationUUID"`
Version string `json:"version"`
Summary NotificationSummary `json:"summary"`
Data NotificationData `json:"data"`
}

type NotificationSummary struct {
RequestIdentifier string `json:"requestIdentifier"`
AppAppleId string `json:"appAppleId"`
BundleId string `json:"bundleId"`
ProductId string `json:"productId"`
Environment string `json:"environment"`
StoreFrontCountryCodes []string `json:"storefrontCountryCodes"`
FailedCount int64 `json:"failedCount"`
SucceededCount int64 `json:"succeededCount"`
}

type NotificationData struct {
AppAppleID int `json:"appAppleId"`
BundleID string `json:"bundleId"`
AppAppleId int `json:"appAppleId"`
BundleId string `json:"bundleId"`
BundleVersion string `json:"bundleVersion"`
Environment string `json:"environment"`
SignedRenewalInfo string `json:"signedRenewalInfo"`
SignedTransactionInfo string `json:"signedTransactionInfo"`
Status int32 `json:"status"`
}

type TransactionInfo struct {
jwt.StandardClaims
TransactionId string `json:"transactionId"`
OriginalTransactionID string `json:"originalTransactionId"`
WebOrderLineItemID string `json:"webOrderLineItemId"`
BundleID string `json:"bundleId"`
ProductID string `json:"productId"`
SubscriptionGroupIdentifier string `json:"subscriptionGroupIdentifier"`
PurchaseDate int `json:"purchaseDate"`
OriginalPurchaseDate int `json:"originalPurchaseDate"`
AppAccountToken string `json:"appAccountToken"`
BundleId string `json:"bundleId"`
Environment string `json:"environment"`
ExpiresDate int `json:"expiresDate"`
Type string `json:"type"`
InAppOwnershipType string `json:"inAppOwnershipType"`
IsUpgraded bool `json:"isUpgraded"`
OfferIdentifier string `json:"offerIdentifier"`
OfferType int32 `json:"offerType"`
OriginalPurchaseDate int `json:"originalPurchaseDate"`
OriginalTransactionId string `json:"originalTransactionId"`
ProductId string `json:"productId"`
PurchaseDate int `json:"purchaseDate"`
Quantity int32 `json:"quantity"`
RevocationDate int `json:"revocationDate"`
RevocationReason int32 `json:"revocationReason"`
SignedDate int `json:"signedDate"`
Environment string `json:"environment"`
StoreFront string `json:"storefront"`
StoreFrontId string `json:"storefrontId"`
SubscriptionGroupIdentifier string `json:"subscriptionGroupIdentifier"`
TransactionId string `json:"transactionId"`
TransactionReason string `json:"transactionReason"`
Type string `json:"type"`
WebOrderLineItemId string `json:"webOrderLineItemId"`
}

type RenewalInfo struct {
jwt.StandardClaims
OriginalTransactionID string `json:"originalTransactionId"`
ExpirationIntent int `json:"expirationIntent"`
AutoRenewProductId string `json:"autoRenewProductId"`
ProductID string `json:"productId"`
AutoRenewStatus int `json:"autoRenewStatus"`
IsInBillingRetryPeriod bool `json:"isInBillingRetryPeriod"`
SignedDate int `json:"signedDate"`
Environment string `json:"environment"`
AutoRenewProductId string `json:"autoRenewProductId"`
AutoRenewStatus int32 `json:"autoRenewStatus"`
Environment string `json:"environment"`
ExpirationIntent int32 `json:"expirationIntent"`
GracePeriodExpiresDate int `json:"gracePeriodExpiresDate"`
IsInBillingRetryPeriod bool `json:"isInBillingRetryPeriod"`
OfferIdentifier string `json:"offerIdentifier"`
OfferType int32 `json:"offerType"`
OriginalTransactionId string `json:"originalTransactionId"`
PriceIncreaseStatus int32 `json:"priceIncreaseStatus"`
ProductId string `json:"productId"`
RecentSubscriptionStartDate int `json:"recentSubscriptionStartDate"`
RenewalDate int `json:"renewalDate"`
SignedDate int `json:"signedDate"`
}
4 changes: 2 additions & 2 deletions v2.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (

func New(payload string, appleRootCert string) *AppStoreServerNotification {
asn := &AppStoreServerNotification{}
asn.isValid = false
asn.IsValid = false
asn.appleRootCert = appleRootCert
asn.parseJwtSignedPayload(payload)
return asn
Expand Down Expand Up @@ -155,5 +155,5 @@ func (asn *AppStoreServerNotification) parseJwtSignedPayload(payload string) {
asn.RenewalInfo = renewalInfo

// valid request
asn.isValid = true
asn.IsValid = true
}
7 changes: 6 additions & 1 deletion v2_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package v2

import (
"encoding/json"
"fmt"
"os"
"testing"
)
Expand All @@ -26,11 +27,15 @@ func TestServerNotificationV2(t *testing.T) {

appStoreServerNotification := New(request.SignedPayload, rootCert)

if !appStoreServerNotification.isValid {
if !appStoreServerNotification.IsValid {
t.Error("Payload is not valid")
}

if appStoreServerNotification.Payload.Data.Environment != "Sandbox" {
t.Errorf("got %s, want Sandbox", appStoreServerNotification.Payload.Data.Environment)
}

println(appStoreServerNotification.Payload.Data.BundleId)
println(appStoreServerNotification.TransactionInfo.ProductId)
fmt.Printf("Product Id: %s", appStoreServerNotification.RenewalInfo.ProductId)
}

0 comments on commit 5bb8650

Please sign in to comment.