voltrue2 / in-app-purchase

A Node.js module for in-App-Purchase for iOS, Android, Amazon and Windows.
http://iap.gracenode.org
Other
1.05k stars 289 forks source link

Google public key setup #129

Closed sekiwired closed 7 years ago

sekiwired commented 7 years ago

Hello, First of all, thank you for the amazing work. I have an issue with a Unity receipt for android. I made a test with an apple receipt, everything works fine. But with google I have an error which states : 'Missing receipt data' (but sadly it is not).

What puzzles me is that if I remove my google public key from the configuration (I hadn't called it correctly at first - by the way: it is weird to have to give a specific name for this file), your library gave me the exact same error message, so I assume setup is not working exactly as intended.

From this point on, I don't know what to look for to correct the mistake I could have made. My key is correct, my receipt is correct, I'm kinda lost.

so I named my key : iap-live and put it in config folder I have:

iap.config({
    googlePublicKeyPath: './config/'
});

and my receipt is:

{
    "Store": "GooglePlay",
    "TransactionID": "GPA.3342-6560-9712-xxx",
    "Payload": "{\"json\":\"{\\\"orderId\\\":\\\"GPA.3342-6560-9712-xxx\\\",\\\"packageName\\\":\\\"com.xxx.xxx\\\",\\\"productId\\\":\\\"product_namey\\\",\\\"purchaseTime\\\":1507187729072,\\\"purchaseState\\\":0,\\\"purchaseToken\\\":\\\"xxx\\\"}\",\"signature\":\"TYN...wMkVtgg==\"}"
}

Error message with badly setup key: "Error: missing receipt data" Error message with correctly setup key "Error: missing receipt data"

Can you help ? (also: Google gives me only one key, idk if it's the sandbox or live one) Thank you

voltrue2 commented 7 years ago

Hello,

What happens if you extract Payload: { "json": <extract here> } and use it as a regular Google receipt? I would like to determine where the problem is such as "Is it Unity receipt that has the issue?" or "There's something wrong with the receipt/key that we don't know about?" if extracting the google receipt makes the validation work, then we can conclude that there's something wrong with Unity receipt handling the library.

If possible, if you could give me the both receipt and the key, I would be more than happy to run some tests on my end also.

Cheers

sekiwired commented 7 years ago

Hello, I tried to extract the Payload, but I'am not sure to have done it correctly, here is what I did and got as result: After extracted the Payload I have something which is not valid json because it contains a signature:

{
    "orderId": "GPA.3342-6560-xxx-50544",
    "packageName": "com.xxx.xxx",
    "productId": "beta04_discovery",
    "purchaseTime": 1507187729072,
    "purchaseState": 0,
    "purchaseToken": "pcocjmflclgonmdfkjpccigc.AO-J1OwKDQD9oyYzkKqmduOHCjeQ4CeGmydrbkoYZztzc_xje1wv8gXrBYeCnv4YyOQHR3AucTf1qHsC0stuMtN5OWEB6e1lEFtWSZoRzzsQLD-XKO-J174MY-mZNzM2q9oHog-3MLhb"
}
","
signature ":"
TYNVhqnv20IWKPRSOzodllhIgnf2hka0HNiq1NhsD + aoDO40RlBplXol3i0MTFj\\ / 1 Mup3reB2M0sfZVBhk\\ / xJY9hLR\\ / zZmAo36b3pvutF\\ / gFVUykwBdKsWexfDtrIAoCoTRJeCRfsuw0UorQFn81k84wJ4R5oGmGoCeG13Gl1rwkfYqR5qfW4oLAwwy6WKCyJGMS6HkVtgg == "

So I tried to remove the last part (signature) and got as a result:

Error: Invalid Purchase Token: https://appstore-sdk.amazon.com/version/2.0/verify/developer/{developerSecret}/user/undefined/purchaseToken/undefined

I attached you a receipt and a key so you can see and test as you want.

Thanks !

F0RIS commented 7 years ago

@sekiwired u mast pass in iap.validate method object with next structure image

sekiwired commented 7 years ago

Hello, @F0RIS this is a Unity receipt so my receipt is not a Google one, and "as of version 1.6.0, the module now automatically detects subscription receipts and validates them accordingly". Do you suggest I should detect myself the type to pass 'iap.GOOGLE' ? I don't think your answers applies, but if I am wrong, I would be pleased to understand why.

Thanks for your help

F0RIS commented 7 years ago

@sekiwired I'm just suggesting u form ur receipt in different sturcture. I got "Error: missing receipt data" error when passed empty signature. I found this reason just from line by line debuggin inside library. You can try do same thing)

voltrue2 commented 7 years ago

@sekiwired Hello, my apologies that it took time for me to test it. The issue was that your Payload was a stringified JSON. That is the cause of you getting receipt is missing error. Here is the test I did to successfully validate your receipt:

var iap = require('./');
var receipt = {
    "Store": "GooglePlay",
    "TransactionID": "GPA.3342-6560-9712-50544",
    "Payload": "{\"json\":\"{\\\"orderId\\\":\\\"GPA.3342-6560-9712-50544\\\",\\\"packageName\\\":\\\"com.Meludia.MicroMelody\\\",\\\"productId\\\":\\\"beta04_discovery\\\",\\\"purchaseTime\\\":1507187729072,\\\"purchaseState\\\":0,\\\"purchaseToken\\\":\\\"pcocjmflclgonmdfkjpccigc.AO-J1OwKDQD9oyYzkKqmduOHCjeQ4CeGmydrbkoYZztzc_xje1wv8gXrBYeCnv4YyOQHR3AucTf1qHsC0stuMtN5OWEB6e1lEFtWSZoRzzsQLD-XKO-J174MY-mZNzM2q9oHog-3MLhb\\\"}\",\"signature\":\"TYNVhqnv20IWKPRSOzodllhIgnf2hka0HNiq1NhsD+aoDO40RlBplXol3i0MTFj\\/1Mup3reB2M0sfZVBhk\\/xJY9hLR\\/zZmAo36b3pvutF\\/gFVUykwBdKsWexfDtrIAoCoTRJeCRfsuw0UorQFn81k84wJ4R5oGmGoCeG13Gl1rwkfYqR5qfW4oLAwwy6WKCyJGMS6Hm88k4pqFaDXJDmEAthaV1+0sBdzDM9MKt\\/x50TdEC+nGpUoxS9QzwxoFUGOuVO1ZJrFk00JaeNICav1lJLeenBJB+i6UfCPuvG2o8PVrRpsjwYbLCzz1nZNiHze4+EWV28VEx4WlrwMkVtgg==\"}"
};
iap.config({
    verbose: true,
    googlePublicKeyStrLive: 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkCBCCBXREajZN2NSSXZjtIvg3oTvqPCb5l5rg98Yiaxi8+NO/vIKSG1wVAVyrRCK71I6jZTPLthn693BEMY2A2KjITtWpim7HsrsIsFlZw4v9XQfYeExlf10TvG+UzApVQclAZoMEpUzoL/toXsoFxwIE1iwpcqh3k9rU1qGaPr6dqxLB0QRwX/tYb11GSW0c+umaXXlDn7UbohTMlZPXGeaqflBQwv7t1rYjcCYP8AqOl3Lm3/7Sj+T4cxgEDLIDNR+2kJPudzfibR6lFRt5gqAhpIESeZQf06fmHi+J+0MPlimupAvCrdvrpu2XwAEkZ+wBRII4iigXAfklDEy4wIDAQAB' });

receipt.Payload = JSON.parse(receipt.Payload);

iap.setup(function (err) {
    if (err) {
        console.error(err);
    }
    iap.validate(receipt, function (err, windowsRes) {
        if (err) {
            console.error(err);
        }
        if (iap.isValidated(windowsRes)) {
            console.info("Ok");
        }
    });
});
receipt.Payload = JSON.parse(receipt.Payload);

This is the key. I will update the module in the near future to automatically handle this part.

Cheers!

sekiwired commented 7 years ago

@voltrue2 Thank you !! @FORIS thank you too

voltrue2 commented 7 years ago

Awesome!

sekiwired commented 7 years ago

To deal with both stores I just added:

if (unityReceipt.Store.includes('Google')){
      unityReceipt.Payload = JSON.parse(unityReceipt.Payload);
  }

And it works. Thanks for your help