GithubHelp home page GithubHelp logo

awa / go-iap Goto Github PK

View Code? Open in Web Editor NEW
842.0 72.0 245.0 436 KB

go-iap verifies the purchase receipt via AppStore, GooglePlayStore, AmazonAppStore and Huawei HMS.

License: MIT License

Makefile 0.24% Go 99.76%
amazonappstrore iap appstore purchase-receipt iab billing googleplaystore hms

go-iap's Introduction

go-iap

unit test

go-iap verifies the purchase receipt via AppStore, GooglePlayStore or Amazon AppStore.

Current API Documents:

  • AppStore: GoDoc
  • AppStore Server API: GoDoc
  • GooglePlay: GoDoc
  • Amazon AppStore: GoDoc
  • Huawei HMS: GoDoc

Installation

go get github.com/awa/go-iap/appstore
go get github.com/awa/go-iap/playstore
go get github.com/awa/go-iap/amazon
go get github.com/awa/go-iap/hms

Quick Start

In App Purchase (via App Store)

import(
    "github.com/awa/go-iap/appstore"
)

func main() {
	client := appstore.New()
	req := appstore.IAPRequest{
		ReceiptData: "your receipt data encoded by base64",
	}
	resp := &appstore.IAPResponse{}
	ctx := context.Background()
	err := client.Verify(ctx, req, resp)
}

Note: The verifyReceipt API has been deprecated as of 5 Jun 2023. Please use App Store Server API instead.

In App Billing (via GooglePlay)

import(
    "github.com/awa/go-iap/playstore"
)

func main() {
	// You need to prepare a public key for your Android app's in app billing
	// at https://console.developers.google.com.
	jsonKey, err := ioutil.ReadFile("jsonKey.json")
	if err != nil {
		log.Fatal(err)
	}

	client := playstore.New(jsonKey)
	ctx := context.Background()
	resp, err := client.VerifySubscription(ctx, "package", "subscriptionID", "purchaseToken")
}

In App Purchase (via Amazon App Store)

import(
    "github.com/awa/go-iap/amazon"
)

func main() {
	client := amazon.New("developerSecret")

	ctx := context.Background()
	resp, err := client.Verify(ctx, "userID", "receiptID")
}

In App Purchase (via Huawei Mobile Services)

import(
    "github.com/awa/go-iap/hms"
)

func main() {
	// If "orderSiteURL" and/or "subscriptionSiteURL" are empty,
	// they will be default to AppTouch German.
	// Please refer to https://developer.huawei.com/consumer/en/doc/HMSCore-References-V5/api-common-statement-0000001050986127-V5 for details.
	client := hms.New("clientID", "clientSecret", "orderSiteURL", "subscriptionSiteURL")
	ctx := context.Background()
	resp, err := client.VerifySubscription(ctx, "purchaseToken", "subscriptionID", 1)
}

In App Store Server API

Note

  • The App Store Server API differentiates between a sandbox and a production environment based on the base URL:

  • If you're unsure about the environment, follow these steps:

    • Initiate a call to the endpoint using the production URL. If the call is successful, the transaction identifier is associated with the production environment.
    • If you encounter an error code 4040010, indicating a TransactionIdNotFoundError, make a call to the endpoint using the sandbox URL.
    • If this call is successful, the transaction identifier is associated with the sandbox environment. If the call fails with the same error code, the transaction identifier doesn't exist in either environment.
  • GetTransactionInfo

import(
	"github.com/awa/go-iap/appstore/api"
)

//  For generate key file and download it, please refer to https://developer.apple.com/documentation/appstoreserverapi/creating_api_keys_to_use_with_the_app_store_server_api
const ACCOUNTPRIVATEKEY = `
    -----BEGIN PRIVATE KEY-----
    FAKEACCOUNTKEYBASE64FORMAT
    -----END PRIVATE KEY-----
    `
func main() {
	c := &api.StoreConfig{
		KeyContent: []byte(ACCOUNTPRIVATEKEY),  // Loads a .p8 certificate
		KeyID:      "FAKEKEYID",                // Your private key ID from App Store Connect (Ex: 2X9R4HXF34)
		BundleID:   "fake.bundle.id",           // Your app’s bundle ID
		Issuer:     "xxxxx-xx-xx-xx-xxxxxxxxxx",// Your issuer ID from the Keys page in App Store Connect (Ex: "57246542-96fe-1a63-e053-0824d011072a")
		Sandbox:    false,                      // default is Production
	}
	transactionId := "FAKETRANSACTIONID"
	a := api.NewStoreClient(c)
	ctx := context.Background()
	response, err := a.GetTransactionInfo(ctx, transactionId)

	transantion, err := a.ParseSignedTransaction(response.SignedTransactionInfo)
	if err != nil {
	    // error handling
	}

	if transaction.TransactionId == transactionId {
		// the transaction is valid
	}
}
  • GetTransactionHistory
import(
	"github.com/awa/go-iap/appstore/api"
)

//  For generate key file and download it, please refer to https://developer.apple.com/documentation/appstoreserverapi/creating_api_keys_to_use_with_the_app_store_server_api
const ACCOUNTPRIVATEKEY = `
    -----BEGIN PRIVATE KEY-----
    FAKEACCOUNTKEYBASE64FORMAT
    -----END PRIVATE KEY-----
    `
func main() {
	c := &api.StoreConfig{
		KeyContent: []byte(ACCOUNTPRIVATEKEY),  // Loads a .p8 certificate
		KeyID:      "FAKEKEYID",                // Your private key ID from App Store Connect (Ex: 2X9R4HXF34)
		BundleID:   "fake.bundle.id",           // Your app’s bundle ID
		Issuer:     "xxxxx-xx-xx-xx-xxxxxxxxxx",// Your issuer ID from the Keys page in App Store Connect (Ex: "57246542-96fe-1a63-e053-0824d011072a")
		Sandbox:    false,                      // default is Production
	}
	originalTransactionId := "FAKETRANSACTIONID"
	a := api.NewStoreClient(c)
	query := &url.Values{}
	query.Set("productType", "AUTO_RENEWABLE")
	query.Set("productType", "NON_CONSUMABLE")
	ctx := context.Background()
	responses, err := a.GetTransactionHistory(ctx, originalTransactionId, query)

	for _, response := range responses {
		transantions, err := a.ParseSignedTransactions(response.SignedTransactions)
	}
}

Parse Notification from App Store

import (
	"github.com/awa/go-iap/appstore"
	"github.com/golang-jwt/jwt/v4"
)

func main() {
	tokenStr := "SignedRenewalInfo Encode String" // or SignedTransactionInfo string
	token := jwt.Token{}
	client := appstore.New()
	err := client.ParseNotificationV2(tokenStr, &token)

	claims, ok := token.Claims.(jwt.MapClaims)
	for key, val := range claims {
		fmt.Printf("Key: %v, value: %v\n", key, val) // key value of SignedRenewalInfo
	}
}

ToDo

  • Validator for In App Purchase Receipt (AppStore)
  • Validator for Subscription token (GooglePlay)
  • Validator for Purchase Product token (GooglePlay)
  • More Tests

Support

In App Purchase

This validator supports the receipt type for iOS7 or above.

In App Billing

This validator uses Version 3 API.

In App Purchase (Amazon)

This validator uses RVS for IAP v2.0.

In App Purchase (HMS)

This validator uses Version 2 API.

In App Store Server API

This validator uses Version 1.0+

License

go-iap is licensed under the MIT.

go-iap's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

go-iap's Issues

Missing notification type const DID_CHANGE_RENEWAL_STATUS

There is new notification status that Apple started sending, which is not in their official documentation (https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/StoreKitGuide/Chapters/Subscriptions.html), but is mentioned in this article: https://developer.apple.com/documentation/storekit/in-app_purchase/enabling_status_update_notifications

I also started receiving this notification type recently so it's legit.

How to send receipt-data?

I send from my app like this:

{"receipt-data":"MIISZAYJKoZIhvcNAQcCoIISVTCCElECAQExCzAJBgUrDgMCGgUAMIICBQYJ etc..."}

Is it right?

My code:

var IAPTest = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
err := r.ParseForm()
if err != nil {
	panic(err)
}

v := r.Form
var re string
for i := range v {
	re = i
}

fmt.Println("This is re: ", re)

client := appstore.New()
req := appstore.IAPRequest{
	ReceiptData: re,
}

resp := &appstore.IAPResponse{}
ctx := context.Background()
err2 := client.Verify(ctx, req, resp)

fmt.Println("client", client)
fmt.Println("req", req)
fmt.Println("resp", resp)
fmt.Println("ctx", ctx)
fmt.Println("err", err2)

And my response:

client &{https://buy.itunes.apple.com/verifyReceipt https://sandbox.itunes.apple.com/verifyReceipt 0x1a12f680}
req {{"receipt-data":"MIIWdgYJKoZIhvcNAQcCoIIWZzCCFmMCAQExCzAJBgUrDgMCGgUAMIIGFwYJK
resp &{21002  { 0    0   [] {  } {  } {  }} []  [] false}

Failed to go get github.com/awa/go-iap/playstore

I got the following error message

go/src/github.com/awa/go-iap/playstore/validator.go:26:68: undefined: androidpublisher.SubscriptionPurchasesAcknowledgeRequest go/src/github.com/awa/go-iap/playstore/validator.go:67:7: undefined: androidpublisher.SubscriptionPurchasesAcknowledgeRequest go/src/github.com/awa/go-iap/playstore/validator.go:75:10: ps.Acknowledge undefined (type *androidpublisher.PurchasesSubscriptionsService has no field or method Acknowledge)

The letter case of appstore.NotificationEnv constants

The appstore.NotificationEnv constants are currently "SANDBOX" and "PROD". I just noticed that Apple sends "Sandbox" - i.e. different letter case.

Apple's documentation contradicts itself on the same page: https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/StoreKitGuide/Chapters/Subscriptions.html

First, Table 6-3 says the values are "Sandbox" and "PROD".

Later it says "To determine if a status update notifications for a subscription event is in the test environment, check if the value of the environment key in the statusUpdateNotification JSON object equals SANDBOX."

Based on observation, I'm guessing the second paragraph has a bug and got the case wrong.

I think the appstore.NotificationEnvSandbox constant needs to be changed to "Sandbox"

Missing `latest_receipt` and `latest_receipt_info` definition in IAPResponseForIOS6?

Per this doc

`latest_receipt

Only returned for receipts containing auto-renewable subscriptions. For iOS 6 style transaction receipts, this is the base-64 encoded receipt for the most recent renewal. For iOS 7 style app receipts, this is the latest base-64 encoded app receipt.

latest_receipt_info

Only returned for receipts containing auto-renewable subscriptions. For iOS 6 style transaction receipts, this is the JSON representation of the receipt for the most recent renewal. For iOS 7 style app receipts, the value of this key is an array containing all in-app purchase transactions. This excludes transactions for a consumable product that have been marked as finished by your app.`

However, I cannot find those two fields defined in IAPResponseForIOS6?

Failed to parse iOS subscription test receipt?

When I try to verify subscription test receipt on iOS, I got the following error,

cannot unmarshal object into Go struct field IAPResponse.latest_receipt_info of type []appstore.InApp

Then I define another testResponse

IAPTestResponse struct {
	Status             int                  `json:"status"`
	Environment        Environment          `json:"environment"`
	Receipt            Receipt              `json:"receipt"`
	LatestReceiptInfo  InApp                `json:"latest_receipt_info"`
	LatestReceipt      string               `json:"latest_receipt"`
	PendingRenewalInfo []PendingRenewalInfo `json:"pending_renewal_info"`
	IsRetryable        bool                 `json:"is-retryable"`
}

which is used to json.Unmarshal, it seems work well now.

Anything I am missing?

apple store response is diffent

My response struct is :

IAPResponse struct {
Receipt struct {
AppItemID string json:"app_item_id"
Bid string json:"bid"
Bvrs string json:"bvrs"
ItemID string json:"item_id"
OriginalPurchaseDate string json:"original_purchase_date"
OriginalPurchaseDateMs string json:"original_purchase_date_ms"
OriginalPurchaseDatePst string json:"original_purchase_date_pst"
OriginalTransactionID string json:"original_transaction_id"
ProductID string json:"product_id"
PurchaseDate string json:"purchase_date"
PurchaseDateMs string json:"purchase_date_ms"
PurchaseDatePst string json:"purchase_date_pst"
Quantity string json:"quantity"
TransactionID string json:"transaction_id"
UniqueIdentifier string json:"unique_identifier"
UniqueVendorIdentifier string json:"unique_vendor_identifier"
VersionExternalIdentifier string json:"version_external_identifier"
} json:"receipt"
Status int json:"status"
}

How to encode ios receipt through base64?

Per doc, the ios receipt should be encoded by base64

req := appstore.IAPRequest{
	ReceiptData: "your receipt data encoded by base64",
}

Then I try it through

 base64.StdEncoding.EncodeToString([]byte(receipt))

and the value of receipt like

 "{\n\t\"signature\" = \"ZwXG56AezlHRTBhL8cTqA==\";\n\t\"purchase-info\" = \"RXRjL0dNVCI7Cn0=\";\n\t\"environment\" = \"Sandbox\";\n\t\"pod\" = \"100\";\n\t\"signing-status\" = \"0\";\n}"

However, I got the status of response is 21002, which is The data in the receipt-data property was malformed or missing

How to encode ios receipt by base64 or is there anything I am missing?

Thank you for this nice & compact library.

Thank you for this nice & compact library.

We're considering using this in our company.

I wanted to check if you have considered adding Roku support and if so, will you be willing to accept a PR if I send you one?

playstore: is oauth compulsory

Thanks for open sourcing the library!

I have a problem that if the oauth compulsory when I only want to call client.VerifyProduct.

Getting empty response body from Verify

Calling appstore.Verify is giving me EOF errors. On closer inspection, these are being thrown by https://github.com/dogenzaka/go-iap/blob/e9d5da1f8f6bff09e3f0ff777a44fe617e45ae52/appstore/validator.go#L112 as the body from the previous request is empty.

Inspecting the gorequest with AsCurlCommand() and running that as a curl command, the request succeeds with a valid (albeit large) response body every time.

Ultimately, what appears to be happening is when the receipt response is large (this can happen very quickly with iOS especially with autorenewing subscriptions) something isn't reading it properly. I don't know if this is in the std lib or gorequest, all I know is the string being passed to the json decoder is empty, and it's never empty when the same request is ran with curl.

Apple receipt field app_item_id type mismatch

As stated here Apple Receipt Fields "app_item_id" field should be a string but in the library it is mapped to int64. This causes an error during json decoding.

EDIT:
Apparently Apple is giving out different responses some has app_item_id as string and some has it as a number. In this case a custom type that implements Unmarshaler interface would be better suited for this. Something like the following:

	Receipt struct {
		ReceiptType                string        `json:"receipt_type"`
		AdamID                     int64         `json:"adam_id"`
		AppItemID                  NumericString `json:"app_item_id"`
		BundleID                   string        `json:"bundle_id"`
		ApplicationVersion         string        `json:"application_version"`
		DownloadID                 int64         `json:"download_id"`
		OriginalApplicationVersion string        `json:"original_application_version"`
		InApp                      []InApp       `json:"in_app"`
		RequestDate
		OriginalPurchaseDate
	}

        func (n NumericString) UnmarshalJSON(data []byte) error {
	        n = NumericString(string(data))
	        return nil
        }

invalid character '<' looking for beginning of value

When validating ios receipt data, some of the receipts are failing the client.Verify call with the following error

invalid character '<' looking for beginning of value

The data is the raw base64 encoded string that the app receives. Having passed the data through base64 decode using the following site https://www.base64decode.org/ it would appear that changing the charset from UTF-8 to ASCII means the receipt then decodes as expected, but given this is only happening for some receipts and not others I believe the issue is better fixed in this library.

Any thoughts on what might be causing this?

How to pass receipt in ios?

I want to do method in API to purchase products. How to do it? How to pass receipt from API? What does the recipe consist of?

package main

import (
  "github.com/awa/go-iap/appstore"
)

func main() {
  r := mux.NewRouter()
  r.Handle("/iaptest", IAPTest).Methods("GET")
  fmt.Println("Server is runned on port 3000")
  if err := http.ListenAndServe(":3000", handlers.LoggingHandler(os.Stdout, r)); err != nil {
	  log.Fatal(err)
  }
}
var IAPTest = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  client := appstore.New()
  req := appstore.IAPRequest{
	  ReceiptData: "your receipt data encoded by base64",
  }
  resp := &appstore.IAPResponse{}
  ctx := context.Background()
  err := client.Verify(ctx, req, resp)
})

`is_in_intro_offer_period` is missing at InApp model in appstore package

From apple developer reference there is a is_in_intro_offer_period and below is a sample response struct from my project

		"in_app": [
			{
				"quantity": "1",
				"product_id": "com.ghostcall.testsubscription.1monthpass",
				"transaction_id": "1000000463911073",
				"original_transaction_id": "1000000463911073",
				"purchase_date": "2018-10-27 18:02:50 Etc/GMT",
				"purchase_date_ms": "1540663370000",
				"purchase_date_pst": "2018-10-27 11:02:50 America/Los_Angeles",
				"original_purchase_date": "2018-10-27 18:02:50 Etc/GMT",
				"original_purchase_date_ms": "1540663370000",
				"original_purchase_date_pst": "2018-10-27 11:02:50 America/Los_Angeles",
				"expires_date": "2018-10-27 18:07:50 Etc/GMT",
				"expires_date_ms": "1540663670000",
				"expires_date_pst": "2018-10-27 11:07:50 America/Los_Angeles",
				"web_order_line_item_id": "1000000041021420",
				"is_trial_period": "false",
				"is_in_intro_offer_period": "false"
			}
		]

But the is_in_intro_offer_period is missing at InApp model in appstore package

Failed to go get ./... on TravisCI

go get ./...
# golang.org/x/net/context/ctxhttp
../../../golang.org/x/net/context/ctxhttp/ctxhttp.go:35: req.Cancel undefined (type *http.Request has no field or method Cancel)
make: *** [setup] Error 2

Appstore returning error as HTML

The appstore appears to be returning HTML from an API call resulting in the following error propagating from the client.Verify call (I believe its actually coming from the parseResponse method when attempting to decode JSON that is actually in HTML format. I have logged the same error from other API's that have returned HTML when JSON is expected in code I have written.

invalid character '<' looking for beginning of value

library version: 1.2.0/1.3.0
go version: 1.13.12

Needs new field of IAPResponse "unifined_reciept"

As per the official documentation, since 2021 3/10 the "latest_receipt" field is now an old field and requires "unified_reciept" as well NotificationUnifiedReciept.

ref:
https://developer.apple.com/documentation/appstoreservernotifications/responsebody

latest_receipt
byte
Removed. As of March 10, 2021 this object is no longer provided in production and sandbox environments. Use the latest_receipt field found in the unified_receipt object instead.

Error 401, permissiondenied

This works:

        key, err := ioutil.ReadFile("key.json")
	c(err, true) // check error
	conf, err := google.JWTConfigFromJSON(key, androidpublisher.AndroidpublisherScope)
	c(err, true) // check error...
	cli := conf.Client(context.Background())
	service, err := androidpublisher.New(cli)
	c(err, true)
	inapps := androidpublisher.NewInappproductsService(service)
	iplc := inapps.List(packageName)
	resp, err := iplc.Context(context.Background()).Do()
	c(err, true)
	return resp.Inappproduct

The same API library (publisher v2 or v3), checking purchase status not works:

        key, err := ioutil.ReadFile("key.json")
	c(err, true) //check error

	ctx := context.WithValue(context.Background(), oauth2.HTTPClient, &http.Client{Timeout: 10 * time.Second})
	conf, err := google.JWTConfigFromJSON(key, androidpublisher.AndroidpublisherScope)
	c(err, true)
	client := conf.Client(ctx)
	sr, err := androidpublisher.New(client)
	c(err, true)
	pr := androidpublisher.NewPurchasesProductsService(sr)
	pe, err := pr.Get(packageName, "sku", "purchase token (android sended to my server)").Context(ctx).Do()
	if err != nil {
		fmt.Println("Error:", err)
	}

Output:
Error: googleapi: Error 401: The current user has insufficient permissions to perform the requested operation., permissionDenied

Google App Engine compatibility

Introduction

Google App Engine is a sandboxed environment. We can't make calls to the outside world without using the net/http's Request to create a http.Client by:

import (
        "net/http"

        "google.golang.org/appengine"
        "google.golang.org/appengine/urlfetch"
)
ctx := appengine.NewContext(r)
client := urlfetch.Client(ctx)

Without doing that, the library doesn't work.

The way Stripe-Go-Library handles it is like this: https://github.com/stripe/stripe-go#google-appengine

Basically Stripe allows Google App Engine users the ability to feed in their own http Client and the library will then use that.

    ctx := appengine.NewContext(r)
    httpClient := urlfetch.Client(ctx)

    sc := client.New(key, stripe.NewBackends(httpClient))

The way I handle it is like this:

https://github.com/pjebs/optimus-go/blob/master/gae.go
https://github.com/pjebs/optimus-go/blob/master/standalone.go

My way may be a lot easier to implement.

In your code, everytime you refer to a http Client, you instead call: client() from the files above.

There will be no affect to the rest of your code.

More information

https://cloud.google.com/appengine/docs/go/issue-requests
https://cloud.google.com/appengine/docs/go/urlfetch/reference

Playstore VerifyProduct error

Hi.
I'm trying to validate product purchase but it returns "Error 400: Invalid Value, invalid".
Could you explain what I'm doing in wrong way?

Apple Api verifyReceipt return last_receipt_info as object instead of array, some time

I run the test for a lot of receipts in prod env and see that the field last_receipt_info is is both array and map. Some receipt apple return array, some else return object. I tested with the receipt the same app and the same subscription. I check on the documentation here https://developer.apple.com/documentation/appstorereceipts/responsebody and see they said that last_receipt_info is an array, but it is not sometimes.

How to cover this case.

transacionID not exist in subscription

When I purchased the first item, the validation that the appstore returned to me did not include the transactionID that the client sent me.
environment:SandBox

Post "https://buy.itunes.apple.com/verifyReceipt": EOF

Hey,

Thank you for this awesome package, we are using go-iap to verify apple receipts, and we have some failing requests with EOF errors in production, after checking the failed receipts I can verify that they are valid, and after a retry the verify request is passing with no issue, I think it might be related to empty response from apple side, any idea how to handle it?

We are using v1.3.8 here is a code snippet -

         iapReq := appstore.IAPRequest{
		ReceiptData: receiptData,
		Password:   password,
	}
	iapResp := &appstore.IAPResponse{}
	err := s.asc.Verify(ctx, iapReq, iapResp)

Thanks!

GoogleAPI error messages has been changed

So some tests fail now.

--- FAIL: TestCancelSubscription (0.09s)
    validator_test.go:166: got googleapi: Error 400: Invalid Value, invalid
        want googleapi: Error 404: No application was found for the given package name., applicationNotFound
--- FAIL: TestVerifyProduct (0.09s)
    validator_test.go:131: got googleapi: Error 400: Invalid Value, invalid
--- FAIL: TestVerifySubscription (0.09s)
    validator_test.go:103: got googleapi: Error 400: Invalid Value, invalid
        want googleapi: Error 404: No application was found for the given package name., applicationNotFound
--- FAIL: TestAcknowledgeSubscription (0.10s)
    validator_test.go:87: got googleapi: Error 400: Invalid Value, invalid
        want googleapi: Error 404: No application was found for the given package name., applicationNotFound
FAIL

Docker Image

Is there any plans to provide library as docker image ?

Don't add undocumented fields to appstore.Receipt struct

Some fields of appstore.Receipt are not mentioned in the Apple IAP Doc, such as ReceiptType, AdamID and AppItemID. Although they are appear in the response, using them can be a risk. Because they are not promised by Apple, things would be changed in the future.

So that I suggest that they should be removed to avoid misuse.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.