appstore

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 6, 2023 License: MIT Imports: 17 Imported by: 0

README

A Go client for the App Store Server API

The App Store Server API returns data signed using the JSON Web Signature (JWS) spec. This client implementation abstracts away JWS for a pleasant developer experience.

Testing

There aren't automated tests included in this repo because I haven't determined the proper way to do it, but I'm open to hearing how to remedy that.

I have tested the client using production data for these operations:

  • Look Up Order ID
  • Get All Subscription Statuses
  • Get Transaction History
  • Get Notification History
  • Get Refund History
  • Request a Test Notification (did not verify that a test notification came)
  • Get Test Notification Status

I did not test these operations, although they client is able to communicate with the API service fine:

  • Extend a Subscription Renewal Date
  • Extend Subscription Renewal Dates for All Active Subscribers
  • Get Status of Subscription Renewal Date Extensions

What’s next

  1. Reuse JSON Web Token (JWT) until expired. This client generates a new JWT for each HTTP request sent, however according to this tip in the App Store Connect API docs: "You do not need to generate a new token for every API request. To get better performance from the App Store Connect API, reuse the same signed token for multiple requests until it expires."
  2. Support App Store Server Notifications
  3. Support App Store Connect API

Contributing

You're welcome to share any bug reports, questions, and feedback (including pull requests).

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AppleAPIClaims

type AppleAPIClaims struct {
	jwt.RegisteredClaims
	BundleID string `json:"bid,omitempty"`
}

type CheckTestNotificationResponse

type CheckTestNotificationResponse struct {
	FirstSendAttemptResult string  `json:"firstSendAttemptResult"`
	SignedPayload          JWSData `json:"signedPayload"`

	Payload ResponseBodyV2DecodedPayload
}

func (*CheckTestNotificationResponse) DecodeJWS

func (p *CheckTestNotificationResponse) DecodeJWS(keyFunc jwt.Keyfunc, data []byte) error

type Client

type Client struct {
	// contains filtered or unexported fields
}

func NewClient

func NewClient(opts ...ClientOption) (*Client, error)

func (*Client) ExtendRenewalDate

func (c *Client) ExtendRenewalDate(ctx context.Context, originalTransactionID string,
	body ExtendRenewalDateRequest) (ExtendRenewalDateResponse, error)

func (*Client) GetMassExtendRenewalDateStatus

func (c *Client) GetMassExtendRenewalDateStatus(ctx context.Context, productID, requestID string) (MassExtendRenewalDateStatusResponse, error)

func (*Client) GetNotificationHistory

func (c *Client) GetNotificationHistory(ctx context.Context, start, end time.Time, opts ...notification.HistoryOption) (NotificationHistoryResponse, error)

func (*Client) GetRefundHistory

func (c *Client) GetRefundHistory(ctx context.Context, originalTransactionID string, opts ...refund.HistoryOption) (RefundHistoryResponse, error)

func (*Client) GetSubscriptionStatuses

func (c *Client) GetSubscriptionStatuses(ctx context.Context, originalTransactionID string) (StatusResponse, error)

func (*Client) GetTestNotificationStatus

func (c *Client) GetTestNotificationStatus(ctx context.Context, token string) (CheckTestNotificationResponse, error)

func (*Client) GetTransactionHistory

func (c *Client) GetTransactionHistory(ctx context.Context, originalTransactionID string, opts ...transaction.HistoryOption) (HistoryResponse, error)

func (*Client) LookupOrder

func (c *Client) LookupOrder(ctx context.Context, orderID string) (OrderLookupResponse, error)

func (*Client) MassExtendRenewalDates

func (*Client) RequestTestNotification

func (c *Client) RequestTestNotification(ctx context.Context) (SendTestNotificationResponse, error)

func (*Client) SendConsumptionInfo

func (c *Client) SendConsumptionInfo(ctx context.Context, originalTransactionID string, body ConsumptionRequest) error

type ClientOption

type ClientOption func(*Client)

func WithAppleCerts

func WithAppleCerts(intermCertPath, rootCertPath string) (ClientOption, error)

func WithClaimsAndKey

func WithClaimsAndKey(bundleID, issuerID, keyID, teamID string, keyPEM []byte) (ClientOption, error)

func WithSandbox

func WithSandbox() ClientOption

type ConsumptionRequest

type ConsumptionRequest struct {
	AccountTenure            int32  `json:"accountTenure"`
	AppAccountToken          string `json:"appAccountToken"`
	ConsumptionStatus        int32  `json:"consumptionStatus"`
	CustomerConsented        bool   `json:"customerConsented"`
	DeliveryStatus           int32  `json:"deliveryStatus"`
	LifetimeDollarsPurchased int32  `json:"lifetimeDollarsPurchased"`
	LifetimeDollarsRefunded  int32  `json:"lifetimeDollarsRefunded"`
	Platform                 int32  `json:"platform"`
	PlayTime                 int32  `json:"playTime"`
	SampleContentProvided    bool   `json:"sampleContentProvided"`
	UserStatus               int32  `json:"userStatus"`
}

type Error

type Error struct {
	ErrorCode    int    `json:"errorCode"`
	ErrorMessage string `json:"errorMessage"`
}

func (Error) Error

func (e Error) Error() string

type ExtendRenewalDateRequest

type ExtendRenewalDateRequest struct {
	ExtendByDays      int32  `json:"extendByDays"`
	ExtendReasonCode  int32  `json:"extendReasonCode"`
	RequestIdentifier string `json:"requestIdentifier"`
}

type ExtendRenewalDateResponse

type ExtendRenewalDateResponse struct {
	EffectiveDate         Millistamp `json:"effectiveDate"`
	OriginalTransactionId string     `json:"originalTransactionId"`
	Success               bool       `json:"success"`
	WebOrderLineItemId    string     `json:"webOrderLineItemId"`
}

func (*ExtendRenewalDateResponse) DecodeJWS

func (p *ExtendRenewalDateResponse) DecodeJWS(keyFunc jwt.Keyfunc, data []byte) error

type HistoryResponse

type HistoryResponse struct {
	AppAppleId         int64     `json:"appAppleId"`
	BundleId           string    `json:"bundleId"`
	Environment        string    `json:"environment"`
	HasMore            bool      `json:"hasMore"`
	Revision           string    `json:"revision"`
	SignedTransactions []JWSData `json:"signedTransactions"`

	Transactions []JWSTransactionDecodedPayload
}

func (*HistoryResponse) DecodeJWS

func (r *HistoryResponse) DecodeJWS(keyFunc jwt.Keyfunc, data []byte) error

type JWSData

type JWSData string

func (JWSData) Decode

func (j JWSData) Decode(keyFunc jwt.Keyfunc, claims jwt.Claims) error

type JWSDecoder

type JWSDecoder interface {
	DecodeJWS(jwt.Keyfunc, []byte) error
}

type JWSRenewalInfoDecodedPayload

type JWSRenewalInfoDecodedPayload struct {
	AutoRenewProductId     string `json:"autoRenewProductId"`
	AutoRenewStatus        int32  `json:"autoRenewStatus"`
	Environment            string `json:"environment"`
	ExpirationIntent       int32  `json:"expirationIntent"`
	IsInBillingRetryPeriod bool   `json:"isInBillingRetryPeriod"`
	OfferIdentifier        string `json:"offerIdentifier"`
	OfferType              int32  `json:"offerType"`
	OriginalTransactionId  string `json:"originalTransactionId"`
	PriceIncreaseStatus    int32  `json:"priceIncreaseStatus"`
	ProductId              string `json:"productId"`

	GracePeriodExpiresDate      *Millistamp `json:"gracePeriodExpiresDate"`
	RecentSubscriptionStartDate *Millistamp `json:"recentSubscriptionStartDate"`
	SignedDate                  *Millistamp `json:"signedDate"`
}

func (JWSRenewalInfoDecodedPayload) Valid

type JWSTransactionDecodedPayload

type JWSTransactionDecodedPayload struct {
	TransactionID               string `json:"transactionId,omitempty"`
	OriginalTransactionID       string `json:"originalTransactionId,omitempty"`
	WebOrderLineItemID          string `json:"webOrderLineItemId,omitempty"`
	BundleID                    string `json:"bundleId,omitempty"`
	ProductID                   string `json:"productId,omitempty"`
	SubscriptionGroupIdentifier string `json:"subscriptionGroupIdentifier,omitempty"`
	Quantity                    int    `json:"quantity,omitempty"`
	Type                        string `json:"type,omitempty"`
	InAppOwnershipType          string `json:"inAppOwnershipType,omitempty"`
	Environment                 string `json:"environment,omitempty"`

	PurchaseDate         *Millistamp `json:"purchaseDate"`
	OriginalPurchaseDate *Millistamp `json:"originalPurchaseDate"`
	ExpiresDate          *Millistamp `json:"expiresDate"`
	SignedDate           *Millistamp `json:"signedDate"`
}

func (JWSTransactionDecodedPayload) Valid

type LastTransactionsItem

type LastTransactionsItem struct {
	OriginalTransactionId string  `json:"originalTransactionId"`
	Status                int32   `json:"status"`
	SignedRenewalInfo     JWSData `json:"signedRenewalInfo"`
	SignedTransactionInfo JWSData `json:"signedTransactionInfo"`

	RenewalInfo     JWSRenewalInfoDecodedPayload
	TransactionInfo JWSTransactionDecodedPayload
}

type MassExtendRenewalDateRequest

type MassExtendRenewalDateRequest struct {
	RequestIdentifier      string   `json:"requestIdentifier"`
	ExtendByDays           int32    `json:"extendByDays"`
	ExtendReasonCode       int32    `json:"extendReasonCode"`
	ProductId              string   `json:"productId"`
	StorefrontCountryCodes []string `json:"storefrontCountryCodes"`
}

type MassExtendRenewalDateResponse

type MassExtendRenewalDateResponse struct {
	RequestIdentifier string `json:"requestIdentifier"`
}

func (*MassExtendRenewalDateResponse) DecodeJWS

func (p *MassExtendRenewalDateResponse) DecodeJWS(keyFunc jwt.Keyfunc, data []byte) error

type MassExtendRenewalDateStatusResponse

type MassExtendRenewalDateStatusResponse struct {
	RequestIdentifier string     `json:"requestIdentifier"`
	Complete          bool       `json:"complete"`
	CompleteDate      Millistamp `json:"completeDate"`
	FailedCount       int64      `json:"failedCount"`
	SucceededCount    int64      `json:"succeededCount"`
}

func (*MassExtendRenewalDateStatusResponse) DecodeJWS

func (p *MassExtendRenewalDateStatusResponse) DecodeJWS(keyFunc jwt.Keyfunc, data []byte) error

type Millistamp

type Millistamp struct{ time.Time }

func (*Millistamp) UnmarshalJSON

func (m *Millistamp) UnmarshalJSON(data []byte) error

type NotificationHistoryResponse

type NotificationHistoryResponse struct {
	NotificationHistory []*NotificationHistoryResponseItem `json:"notificationHistory"`
	HasMore             bool                               `json:"hasMore"`
	PaginationToken     string                             `json:"paginationToken"`
}

func (*NotificationHistoryResponse) DecodeJWS

func (p *NotificationHistoryResponse) DecodeJWS(keyFunc jwt.Keyfunc, data []byte) error

type NotificationHistoryResponseItem

type NotificationHistoryResponseItem struct {
	FirstSendAttemptResult string  `json:"firstSendAttemptResult"`
	SignedPayload          JWSData `json:"signedPayload"`

	Payload ResponseBodyV2DecodedPayload
}

type OrderLookupResponse

type OrderLookupResponse struct {
	Status             int32     `json:"status"`
	SignedTransactions []JWSData `json:"signedTransactions"`

	Transactions []JWSTransactionDecodedPayload
}

func (*OrderLookupResponse) DecodeJWS

func (r *OrderLookupResponse) DecodeJWS(keyFunc jwt.Keyfunc, data []byte) error

type RefundHistoryResponse

type RefundHistoryResponse struct {
	HasMore            bool      `json:"hasMore"`
	Revision           string    `json:"revision"`
	SignedTransactions []JWSData `json:"signedTransactions"`

	Transactions []JWSTransactionDecodedPayload
}

func (*RefundHistoryResponse) DecodeJWS

func (p *RefundHistoryResponse) DecodeJWS(keyFunc jwt.Keyfunc, data []byte) error

type ResponseBodyV2DecodedPayload

type ResponseBodyV2DecodedPayload struct {
	NotificationType string                               `json:"notificationType"`
	Subtype          string                               `json:"subtype"`
	Data             *ResponseBodyV2DecodedPayloadData    `json:"data,omitempty"`
	Summary          *ResponseBodyV2DecodedPayloadSummary `json:"summary,omitempty"`
	Version          string                               `json:"version"`
	NotificationUUID string                               `json:"notificationUUID"`

	// SignedDate *time.Time
	SignedDate Millistamp `json:"signedDate"`
}

func (ResponseBodyV2DecodedPayload) Valid

type ResponseBodyV2DecodedPayloadData

type ResponseBodyV2DecodedPayloadData struct {
	AppAppleId            int64   `json:"appAppleId"`
	BundleId              string  `json:"bundleId"`
	BundleVersion         string  `json:"bundleVersion"`
	Environment           string  `json:"environment"`
	SignedRenewalInfo     JWSData `json:"signedRenewalInfo"`
	SignedTransactionInfo JWSData `json:"signedTransactionInfo"`

	RenewalInfo     JWSRenewalInfoDecodedPayload
	TransactionInfo JWSTransactionDecodedPayload
}

func (*ResponseBodyV2DecodedPayloadData) DecodeJWS

func (p *ResponseBodyV2DecodedPayloadData) DecodeJWS(keyFunc jwt.Keyfunc, data []byte) error

type ResponseBodyV2DecodedPayloadSummary

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

type SendTestNotificationResponse

type SendTestNotificationResponse struct {
	TestNotificationToken string `json:"testNotificationToken"`
}

func (*SendTestNotificationResponse) DecodeJWS

func (p *SendTestNotificationResponse) DecodeJWS(keyFunc jwt.Keyfunc, data []byte) error

type StatusResponse

type StatusResponse struct {
	Data        []SubscriptionGroupIdentifierItem `json:"data"`
	Environment string                            `json:"environment"`
	AppAppleID  int64                             `json:"appAppleId"`
	BundleID    string                            `json:"bundleId"`
}

func (*StatusResponse) DecodeJWS

func (r *StatusResponse) DecodeJWS(keyFunc jwt.Keyfunc, data []byte) error

type SubscriptionGroupIdentifierItem

type SubscriptionGroupIdentifierItem struct {
	SubscriptionGroupIdentifier string                  `json:"subscriptionGroupIdentifier"`
	LastTransactions            []*LastTransactionsItem `json:"lastTransactions"`
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL