Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Failed to execute 'readAsText' on 'FileReader': parameter 1 is not of type 'Blob'. #11

Open
mcmatan opened this issue Apr 11, 2017 · 10 comments

Comments

@mcmatan
Copy link

mcmatan commented Apr 11, 2017

Using https://github.com/chirag04/react-native-in-app-utils for purchasing, and:

InAppUtils.receiptData((error, receiptData)=> {
if(error) {
} else {
IOSReceiptValidator.validate(receiptData).then(function (result) {
}).catch(function (error) {
});
}

For getting last receipt, when trying to validate, getting this error (While debugging on real device in Chrome)

Failed to execute 'readAsText' on 'FileReader': parameter 1 is not of type 'Blob'.

@chatras
Copy link

chatras commented Apr 16, 2017

Any solution to this?

@sibelius
Copy link
Owner

@mcmatan could you provide full stack trace? and also the receiptData ?

@chatras
Copy link

chatras commented Apr 16, 2017

Hi @sibelius Loving this library so far!

So this is what I am doing. After a purchase is successful, I am calling this function for validating the receipt

const validateRecipt = (response) => {
    InAppUtils.receiptData((error, receiptData) => {
        try {
            generalHelper.validate(receiptData);
        } catch (err) {
            console.log(err.valid, err.error, err.message);
        }
        if (error) {
            console.log(error);
            // AlertIOS.alert('itunes Error', 'Receipt not found.');
        } else {
            //send to validation server
        }
    });
const password = 'hidden'; // Shared Secret from iTunes connect
const production = false; // use sandbox or production url for validation

class GeneralHelper {

    async validate(receiptData) {
        const validateReceipt = iapReceiptValidator(password, production);
  
        try {
            const validationData = await validateReceipt(receiptData);
            console.log(validationData);
            // check if Auto-Renewable Subscription is still valid
            // validationData['latest_receipt_info'][0].expires_date > today
        } catch (err) {
            console.log(err.valid, err.error, err.message);
        }
    }
}
export default GeneralHelper;

Its throwing error on
const validateReceipt = iapReceiptValidator(password, production);
Here is the error

undefined undefined "Failed to execute 'readAsText' on 'FileReader': parameter 1 is not of type 'Blob'."

I get the following receiptData

@mcmatan
Copy link
Author

mcmatan commented Apr 17, 2017

Hi, yes I've solved this, the error seems to be because of the fetch req, not the URL this library is using.
I've fixed this by using 'fetchBlob' library for requesting, and used this url's:

const url = Env.isDebug() ? "https://sandbox.itunes.apple.com/verifyReceipt" : "https://buy.itunes.apple.com/verifyReceipt";

Body:

"receipt-data": receiptData,
password: password

And this are the responses you can get:

0 : Valid
21000 :The App Store could not read the JSON object you provided.
21002 : The data in the receipt-data property was malformed or missing.
21003 : The receipt could not be authenticated.
21004 : The shared secret you provided does not match the shared secret on file for your account.
Only returned for iOS 6 style transaction receipts for auto-renewable subscriptions.
21005: The receipt server is not currently available.
21006: This receipt is valid but the subscription has expired. When this status code is returned to your server, the receipt data is also decoded and returned as part of the response.
Only returned for iOS 6 style transaction receipts for auto-renewable subscriptions.
21007 : This receipt is from the test environment, but it was sent to the production environment for verification. Send it to the test environment instead.
21008 : This receipt is from the production environment, but it was sent to the test environment for verification. Send it to the production environment instead.

@sibelius
Copy link
Owner

@mcmatan do you mind sending a PR fixing this?

@mcmatan
Copy link
Author

mcmatan commented Apr 17, 2017

@sibelius I didn't use the library for it at all... I've just made a vanilla request with fetchBlob to the end point I've mentioned, I can if you want, but this means using the fetchBlob library, are you ok with it?

@sibelius
Copy link
Owner

I'm ok with it

@mcmatan
Copy link
Author

mcmatan commented Apr 18, 2017

K I'll try to do it soon

@ajonno
Copy link

ajonno commented Oct 14, 2017

here's example using RNFetchBlob:

   
   let receipts = <..go & get the receipt data...>

    const url = 'https://sandbox.itunes.apple.com/verifyReceipt'
    //for prod:- 'https://buy.itunes.apple.com/verifyReceipt'

    let body = {
      'receipt-data': receipts,
      password: '<your iTunes Connect shared secret here>'
    }

    RNFetchBlob.fetch(
      'POST',
      url,
      {
        'Content-Type': 'application/x-www-form-urlencoded'
      },
      JSON.stringify(body)
    )
      .then(res => {
        console.log('response', res.text())
      })
      .catch(err => {
        console.log(err.text())
      })

@JazLow
Copy link

JazLow commented Nov 13, 2018

I solved it by resetting the window.XMLHttpRequest to it's original state after finished using the fetch blob for uploading my image to cloud.

const Blob = FetchBlob.polyfill.Blob;
// Keep an original copy of window.XMLHttpRequest before set it to FetchBlob.polyfill.XMLHttpRequest
const oriWindowXMLHttpRequest = window.XMLHttpRequest;
window.XMLHttpRequest = FetchBlob.polyfill.XMLHttpRequest;
window.Blob = Blob;

return new Promise((resolve, reject) => {
Blob.build(imageFile, { type: mime })
.then(blob => {
uploadBlob = blob;
return imageRef.put(blob, { contentType: mime });
})
.then(() => {
uploadBlob.close();
return imageRef.getDownloadURL();
})
.then(url => {
// Reset it to the original WindowXMLHttpRequest after the task has been done completely
window.XMLHttpRequest = oriWindowXMLHttpRequest;
resolve(getSuccessResponse(url));
})
.catch(error => {
// Reset it to the original WindowXMLHttpRequest after the task has been done completely
window.XMLHttpRequest = oriWindowXMLHttpRequest;
showToast(getErrorMessage(error));
reject(getFailResponse(error));
});
});

Hope it helps :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants