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

Malformed receipt #126

Closed nscherer closed 7 years ago

nscherer commented 7 years ago

I'm getting this error trying to validate an Android purchase:

Error: malformed receipt: {"data":{"orderId":"GPA.3354-6621-7173-31262","packageName":"com.my.package","productId":"report.credit.1","purchaseTime":1503794900119,"purchaseState":0,"purchaseToken":"dkbcooidfbbddfnhnclhbnic.AO-J1OxojPM6MOqVIYbb8TiFQccbPgj1aj4DM5nDvlcgXr8YITs2Rb60clH0lZwOh1ZiyuKXT4uXAW7axtK_L59aONGNlieQ_BFoKpI0Qz_0m3wLQXHLqVkTRdyszbYvXm3jHEXPM_A98NC0_A1jZVk6eHjT0E7Hsg"},"signature":"PgvYnIO4ptwL3QU+wDxpWFz3tDq8UjtRnxDygOYenLSdLJc4GHc1yrskFp9YOBv3NpipHhnd1Wfu7daY0MrSsFQCQR8rGVH8SUriFhHsQdt0hwGQEswy4TlMsh1bzKtdRtbZVvRq59ZyNL0mPrtyO3WxKcynae1oC2+3sXOKVGyez0sl8IpIRcjtqUTKQv+JOGb0EmMLrjtIWA1HykYKjRV2cYmOEwbuv3GpWnuIfXjsbvt+9MixvnBziL0qJeei4kkSk4f26GlOzSktGW/vNw1DySXG3cudFVvPD0Y+NFz/ydXvDyE3q6eOzi8K8MyuEYIWnI+X90EVtyviBiivTw=="}

I anonymized the package, otherwise it's copied and pasted. I pasted the JSON into jsonlint.com and it validated fine. I've copied these values from an actual Android purchase and I'm hitting my web service using Postman; I assume that should work and wouldn't cause this problem. What is happening here?

Here's some relevant code:

const params = {
    clientId: 'ID-GOES-HERE,
    clientSecret: 'SECRET-HERE',
    refreshToken: 'REFRESH-TOKEN'
};

iap.config({
    googlePublicKeyPath: "./" // Files are in project root
});

iap.setup(function (error) {
    if (error) {
        return console.error('something went wrong...');
    }
    console.log("IAP ready"); // This is logged to console
});

app.get('/verifyAndroid', function (req, res) {

    var receipt = req.query.receipt;
    var email = req.query.email;
    var productId = req.query.productId;
    if(!receipt){
        respond(res,"ERROR","Required 'receipt' parameter missing: { 'data':[stringified data object], 'signature':'signature from Google' }");
        return;
    }
    if(!email){
        respond(res,"ERROR","Required parameter \"email\" missing");
        return;
    }
    if(!productId){
        respond(res,"ERROR","Required parameter \"productId\" missing");
        return;
    }

    console.log("Validating purchase.  Receipt = " + receipt);
    iap.validateOnce(receipt, params, function(err, resp){
        if(err){
            // This block is executed
            console.error(err);
            respond(res,"ERROR",err.toString());
            return;
        }
        // etc...
voltrue2 commented 7 years ago

Hello

It seems you are missing signature in your receipt.

Cheers

On Sep 19, 2017, at 09:22, nscherer notifications@github.com wrote:

I'm getting this error trying to validate an Android purchase:

Error: malformed receipt: {"data":{"orderId":"GPA.3354-6621-7173-31262","packageName":"com.my.package","productId":"report.credit.1","purchaseTime":1503794900119,"purchaseState":0,"purchaseToken":"dkbcooidfbbddfnhnclhbnic.AO-J1OxojPM6MOqVIYbb8TiFQccbPgj1aj4DM5nDvlcgXr8YITs2Rb60clH0lZwOh1ZiyuKXT4uXAW7axtK_L59aONGNlieQ_BFoKpI0Qz_0m3wLQXHLqVkTRdyszbYvXm3jHEXPM_A98NC0_A1jZVk6eHjT0E7Hsg"},"signature":"PgvYnIO4ptwL3QU+wDxpWFz3tDq8UjtRnxDygOYenLSdLJc4GHc1yrskFp9YOBv3NpipHhnd1Wfu7daY0MrSsFQCQR8rGVH8SUriFhHsQdt0hwGQEswy4TlMsh1bzKtdRtbZVvRq59ZyNL0mPrtyO3WxKcynae1oC2+3sXOKVGyez0sl8IpIRcjtqUTKQv+JOGb0EmMLrjtIWA1HykYKjRV2cYmOEwbuv3GpWnuIfXjsbvt+9MixvnBziL0qJeei4kkSk4f26GlOzSktGW/vNw1DySXG3cudFVvPD0Y+NFz/ydXvDyE3q6eOzi8K8MyuEYIWnI+X90EVtyviBiivTw=="} I anonymized the package, otherwise it's copied and pasted. I pasted the JSON into jsonlint.com and it validated fine. I've copied these values from an actual Android purchase and I'm hitting my web service using Postman; I assume that should work and wouldn't cause this problem. What is happening here?

Here's some relevant code:

const params = { clientId: 'ID-GOES-HERE, clientSecret: 'SECRET-HERE', refreshToken: 'REFRESH-TOKEN' };

iap.config({ googlePublicKeyPath: "./" // Files are in project root });

iap.setup(function (error) { if (error) { return console.error('something went wrong...'); } console.log("IAP ready"); // This is logged to console });

app.get('/verifyAndroid', function (req, res) {

var receipt = req.query.receipt;
var email = req.query.email;
var productId = req.query.productId;
if(!receipt){
    respond(res,"ERROR","Required 'receipt' parameter missing: { 'data':[stringified data object], 'signature':'signature from Google' }");
    return;
}
if(!email){
    respond(res,"ERROR","Required parameter \"email\" missing");
    return;
}
if(!productId){
    respond(res,"ERROR","Required parameter \"productId\" missing");
    return;
}

console.log("Validating purchase.  Receipt = " + receipt);
iap.validateOnce(receipt, params, function(err, resp){
    if(err){
        // This block is executed
        console.error(err);
        respond(res,"ERROR",err.toString());
        return;
    }
    // etc...

― You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub, or mute the thread.

nscherer commented 7 years ago

No, the signature was there. I had a look in the source code, and it seems the receipt string needs to be turned into an object, which wasn't clear to me from the documentation.

voltrue2 commented 6 years ago

The receipt should look like this:

{
  "data": {"pakagename":"foo"...},
  "signature": "xxxxxxx"
}

You may pass this as an object or a string.

Cheers