forked from Mirrors/go-iap
Merge pull request #38 from sanae10001/master
append new IAP receipt fields
This commit is contained in:
@@ -1,10 +1,22 @@
|
|||||||
package appstore
|
package appstore
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
// https://developer.apple.com/library/content/releasenotes/General/ValidateAppStoreReceipt/Chapters/ValidateRemotely.html
|
||||||
// The IAPRequest type has the request parameter
|
// The IAPRequest type has the request parameter
|
||||||
IAPRequest struct {
|
IAPRequest struct {
|
||||||
ReceiptData string `json:"receipt-data"`
|
ReceiptData string `json:"receipt-data"`
|
||||||
Password string `json:"password,omitempty"`
|
// Only used for receipts that contain auto-renewable subscriptions.
|
||||||
|
Password string `json:"password,omitempty"`
|
||||||
|
// Only used for iOS7 style app receipts that contain auto-renewable or non-renewing subscriptions.
|
||||||
|
// If value is true, response includes only the latest renewal transaction for any subscriptions.
|
||||||
|
ExcludeOldTransactions bool `json:"exclude-old-transactions"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// The ReceiptCreationDate type indicates the date when the app receipt was created.
|
||||||
|
ReceiptCreationDate struct {
|
||||||
|
CreationDate string `json:"receipt_creation_date"`
|
||||||
|
CreationDateMS string `json:"receipt_creation_date_ms"`
|
||||||
|
CreationDatePST string `json:"receipt_creation_date_pst"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// The RequestDate type indicates the date and time that the request was sent
|
// The RequestDate type indicates the date and time that the request was sent
|
||||||
@@ -44,18 +56,20 @@ type (
|
|||||||
|
|
||||||
// The InApp type has the receipt attributes
|
// The InApp type has the receipt attributes
|
||||||
InApp struct {
|
InApp struct {
|
||||||
Quantity string `json:"quantity"`
|
Quantity string `json:"quantity"`
|
||||||
ProductID string `json:"product_id"`
|
ProductID string `json:"product_id"`
|
||||||
TransactionID string `json:"transaction_id"`
|
TransactionID string `json:"transaction_id"`
|
||||||
OriginalTransactionID string `json:"original_transaction_id"`
|
OriginalTransactionID string `json:"original_transaction_id"`
|
||||||
IsTrialPeriod string `json:"is_trial_period"`
|
WebOrderLineItemID string `json:"web_order_line_item_id"`
|
||||||
AppItemID string `json:"app_item_id"`
|
|
||||||
VersionExternalIdentifier string `json:"version_external_identifier"`
|
IsTrialPeriod string `json:"is_trial_period"`
|
||||||
WebOrderLineItemID string `json:"web_order_line_item_id"`
|
ExpiresDate
|
||||||
|
|
||||||
PurchaseDate
|
PurchaseDate
|
||||||
OriginalPurchaseDate
|
OriginalPurchaseDate
|
||||||
ExpiresDate
|
|
||||||
CancellationDate
|
CancellationDate
|
||||||
|
CancellationReason string `json:"cancellation_reason"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// The Receipt type has whole data of receipt
|
// The Receipt type has whole data of receipt
|
||||||
@@ -66,22 +80,36 @@ type (
|
|||||||
BundleID string `json:"bundle_id"`
|
BundleID string `json:"bundle_id"`
|
||||||
ApplicationVersion string `json:"application_version"`
|
ApplicationVersion string `json:"application_version"`
|
||||||
DownloadID int64 `json:"download_id"`
|
DownloadID int64 `json:"download_id"`
|
||||||
|
VersionExternalIdentifier int64 `json:"version_external_identifier"`
|
||||||
OriginalApplicationVersion string `json:"original_application_version"`
|
OriginalApplicationVersion string `json:"original_application_version"`
|
||||||
InApp []InApp `json:"in_app"`
|
InApp []InApp `json:"in_app"`
|
||||||
|
ReceiptCreationDate
|
||||||
RequestDate
|
RequestDate
|
||||||
OriginalPurchaseDate
|
OriginalPurchaseDate
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A pending renewal may refer to a renewal that is scheduled in the future or a renewal that failed in the past for some reason.
|
||||||
|
PendingRenewalInfo struct {
|
||||||
|
SubscriptionExpirationIntent string `json:"expiration_intent"`
|
||||||
|
SubscriptionAutoRenewProductID string `json:"auto_renew_product_id"`
|
||||||
|
SubscriptionRetryFlag string `json:"is_in_billing_retry_period"`
|
||||||
|
SubscriptionAutoRenewStatus string `json:"auto_renew_status"`
|
||||||
|
SubscriptionPriceConsentStatus string `json:"price_consent_status"`
|
||||||
|
ProductID string `json:"product_id"`
|
||||||
|
}
|
||||||
|
|
||||||
// The IAPResponse type has the response properties
|
// The IAPResponse type has the response properties
|
||||||
// We defined each field by the current IAP response, but some fields are not mentioned
|
// We defined each field by the current IAP response, but some fields are not mentioned
|
||||||
// in the following Apple's document;
|
// in the following Apple's document;
|
||||||
// https://developer.apple.com/library/ios/releasenotes/General/ValidateAppStoreReceipt/Chapters/ReceiptFields.html
|
// https://developer.apple.com/library/ios/releasenotes/General/ValidateAppStoreReceipt/Chapters/ReceiptFields.html
|
||||||
// If you get other types or fileds from the IAP response, you should use the struct you defined.
|
// If you get other types or fileds from the IAP response, you should use the struct you defined.
|
||||||
IAPResponse struct {
|
IAPResponse struct {
|
||||||
Status int `json:"status"`
|
Status int `json:"status"`
|
||||||
Environment string `json:"environment"`
|
Environment string `json:"environment"`
|
||||||
Receipt Receipt `json:"receipt"`
|
Receipt Receipt `json:"receipt"`
|
||||||
LatestReceiptInfo []InApp `json:"latest_receipt_info"`
|
LatestReceiptInfo []InApp `json:"latest_receipt_info"`
|
||||||
LatestReceipt string `json:"latest_receipt"`
|
LatestReceipt string `json:"latest_receipt"`
|
||||||
|
PendingRenewalInfo []PendingRenewalInfo `json:"pending_renewal_info"`
|
||||||
|
IsRetryable bool `json:"is-retryable"`
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -50,6 +50,9 @@ func HandleError(status int) error {
|
|||||||
case 21003:
|
case 21003:
|
||||||
message = "The receipt could not be authenticated."
|
message = "The receipt could not be authenticated."
|
||||||
|
|
||||||
|
case 21004:
|
||||||
|
message = "The shared secret you provided does not match the shared secret on file for your account."
|
||||||
|
|
||||||
case 21005:
|
case 21005:
|
||||||
message = "The receipt server is not currently available."
|
message = "The receipt server is not currently available."
|
||||||
|
|
||||||
@@ -59,8 +62,15 @@ func HandleError(status int) error {
|
|||||||
case 21008:
|
case 21008:
|
||||||
message = "This receipt is from the production environment, but it was sent to the test environment for verification. Send it to the production environment instead."
|
message = "This receipt is from the production environment, but it was sent to the test environment for verification. Send it to the production environment instead."
|
||||||
|
|
||||||
|
case 21010:
|
||||||
|
message = "This receipt could not be authorized. Treat this the same as if a purchase was never made."
|
||||||
|
|
||||||
default:
|
default:
|
||||||
message = "An unknown error occurred"
|
if status >= 21100 && status <= 21199 {
|
||||||
|
message = "Internal data access error."
|
||||||
|
} else {
|
||||||
|
message = "An unknown error occurred"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return errors.New(message)
|
return errors.New(message)
|
||||||
|
|||||||
@@ -39,6 +39,13 @@ func TestHandleError(t *testing.T) {
|
|||||||
t.Errorf("got %v\nwant %v", actual, expected)
|
t.Errorf("got %v\nwant %v", actual, expected)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// status 21004
|
||||||
|
expected = errors.New("The shared secret you provided does not match the shared secret on file for your account.")
|
||||||
|
actual = HandleError(21004)
|
||||||
|
if !reflect.DeepEqual(actual, expected) {
|
||||||
|
t.Errorf("got %v\nwant %v", actual, expected)
|
||||||
|
}
|
||||||
|
|
||||||
// status 21005
|
// status 21005
|
||||||
expected = errors.New("The receipt server is not currently available.")
|
expected = errors.New("The receipt server is not currently available.")
|
||||||
actual = HandleError(21005)
|
actual = HandleError(21005)
|
||||||
@@ -60,6 +67,20 @@ func TestHandleError(t *testing.T) {
|
|||||||
t.Errorf("got %v\nwant %v", actual, expected)
|
t.Errorf("got %v\nwant %v", actual, expected)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// status 21010
|
||||||
|
expected = errors.New("This receipt could not be authorized. Treat this the same as if a purchase was never made.")
|
||||||
|
actual = HandleError(21010)
|
||||||
|
if !reflect.DeepEqual(actual, expected) {
|
||||||
|
t.Errorf("got %v\nwant %v", actual, expected)
|
||||||
|
}
|
||||||
|
|
||||||
|
// status 21100 - 21199
|
||||||
|
expected = errors.New("Internal data access error.")
|
||||||
|
actual = HandleError(21155)
|
||||||
|
if !reflect.DeepEqual(actual, expected) {
|
||||||
|
t.Errorf("got %v\nwant %v", actual, expected)
|
||||||
|
}
|
||||||
|
|
||||||
// status unknown
|
// status unknown
|
||||||
expected = errors.New("An unknown error occurred")
|
expected = errors.New("An unknown error occurred")
|
||||||
actual = HandleError(100)
|
actual = HandleError(100)
|
||||||
|
|||||||
Reference in New Issue
Block a user