iap-receipt-validator icon indicating copy to clipboard operation
iap-receipt-validator copied to clipboard

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

Open mcmatan opened this issue 7 years ago • 10 comments

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'.

mcmatan avatar Apr 11 '17 18:04 mcmatan

Any solution to this?

chatras avatar Apr 16 '17 18:04 chatras

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

sibelius avatar Apr 16 '17 22:04 sibelius

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

chatras avatar Apr 16 '17 23:04 chatras

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.

mcmatan avatar Apr 17 '17 12:04 mcmatan

@mcmatan do you mind sending a PR fixing this?

sibelius avatar Apr 17 '17 12:04 sibelius

@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?

mcmatan avatar Apr 17 '17 20:04 mcmatan

I'm ok with it

sibelius avatar Apr 17 '17 20:04 sibelius

K I'll try to do it soon

mcmatan avatar Apr 18 '17 12:04 mcmatan

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())
      })

ajonno avatar Oct 14 '17 04:10 ajonno

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 :)

JazLow avatar Nov 13 '18 09:11 JazLow