Reputation: 8821
I refered google play android api to check the purchase and consumption status of an in-app item. For some orders, I can get right result,but some return the error as below:
error: {
errors: [
{
domain: "global",
reason: "purchaseTokenNotFound",
message: "The purchase token was not found.",
locationType: "parameter",
location: "token"
}
],
code: 404,
message: "The purchase token was not found."
}
Purchase token is provided by google, does it can be faked?
I found if I cancel the google order, then check the purchase status,it will return the purchase token was not found. if not, i will get the right purchase status.
Hope somebody can help.
Upvotes: 5
Views: 4967
Reputation: 55
The documents are misleading. You don't need to use this API to verify purchases.
Mobile app have INAPP_PURCHASE_DATA and INAPP_DATA_SIGNATURE from getBuyIntent method.
You can verify the purchase with the signature and your public key.
https://developer.android.com/google/play/billing/billing_reference.html#getBuyIntent
You can find the public key on Google Play Developer Console
-> YOUR_APP
-> service and API
package main
import (
"crypto"
"crypto/rsa"
"crypto/sha1"
"crypto/x509"
"encoding/base64"
"encoding/pem"
"fmt"
)
//replace const below with your own.
const (
pubKeyPEM=`-----BEGIN PUBLIC KEY-----
Some thing like this
-----END PUBLIC KEY-----`
data = `purchase data from getBuyIntent API`
sign = `purchase data signature from getBuyIntent API`
)
func Panic(err error) {
if err != nil {
panic(err)
}
}
func main() {
PEMBlock, _ := pem.Decode([]byte(pubKeyPEM))
if PEMBlock == nil {
Panic(fmt.Errorf("Could not parse Public Key PEM"))
}
if PEMBlock.Type != "PUBLIC KEY" {
Panic(fmt.Errorf("Found wrong key type"))
}
pubkey, err := x509.ParsePKIXPublicKey(PEMBlock.Bytes)
if err != nil {
Panic(err)
}
// compute the sha1
h := sha1.New()
h.Write([]byte(data))
// decode b64 signature
signature, err := base64.StdEncoding.DecodeString(sign)
Panic(err)
// Verify
err = rsa.VerifyPKCS1v15(pubkey.(*rsa.PublicKey), crypto.SHA1, h.Sum(nil), signature)
Panic(err)
// It verified!
fmt.Println("OK")
}
Upvotes: 1
Reputation: 1303
If you are selling the same INAPP product to the same user muliple times within a short period, then it's very likely that all access tokens except the last purchase will return a 404 code.
For example:
[email protected] went to your app and purchased com.example.test.product a few times, you will probaly notice within your records (or Google Wallet Merchant account) that it's the same user buying the product.
When you go to check the last purchase from this user, then the following is likely to appear
{
kind: "androidpublisher#inappPurchase",
purchaseTime: "1409823171827",
purchaseState: "0",
consumptionState: "1",
developerPayload: "My Product | Ref | 1409823162466"
}
and yet if you were to check his previous tokens, then it's very likely that his purchases will return 404!
I had read somewhere (can't remember where) that the purchase token created for each purchase is basically based on the inapp product and google user. Therefore, it's very likely that each purchase will "destroy" any previous purchase token created for the same user.
Hope this explanation helps. I am constantly having this problem everyday when my server is attempting to connect to the Google API and check the transactions. Perhaps one day somebody will read this and provide a solution :)
Upvotes: 5