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

Dealing with an account using two-factor authentication (and other download errors) #280

Open
rmaddy opened this issue Nov 15, 2015 · 28 comments

Comments

@rmaddy
Copy link

rmaddy commented Nov 15, 2015

After installing the latest version of this app and deleting sales reports from October 26 and later I tried to redownload those reports. The app appeared like it was downloading and processing the reports but in the end, there were no bars for those days.

Then I noticed a bunch of errors in the console about the fact that my account uses two-factor authentication and I should create an app-specific app id.

So I guess this is an enhancement request that could help anyone complaining that this app isn't downloading any new reports. The app didn't indicate there was any error during the download. It would be nice if this app could present any download errors instead of silently ignoring them. Such an error message would have saved me some head scratching trying to figure out why I wasn't getting any new reports.

BTW - in my case I created app-specific app id and updated the password in this app with the new password and it started working again.

@nicolasgomollon
Copy link

Thanks for this! I ran into the same exact issue, and couldn’t figure out what was going on!

I just incorporated your idea into my copy of this project so I can be alerted about these kinds of things in the future:

In ReportDownloadOperation.m line 60:

NSMutableDictionary *errors = [[NSMutableDictionary alloc] init];

…and replaced line 177 in ReportDownloadOperation.m with:

// The message "Daily Reports are only available for past 365 days. Please enter a new date."
// just means that the report in question has not yet been released.
// We can safely ignore this error and move on.
if ([errorMessage rangeOfString:@"past 365 days"].location == NSNotFound) {
    NSLog(@"%@ -> %@", reportDateString, errorMessage);

    NSInteger year = [[reportDateString substringWithRange:NSMakeRange(0, 4)] intValue];
    NSInteger month = [[reportDateString substringWithRange:NSMakeRange(4, 2)] intValue];
    NSInteger day = [[reportDateString substringWithRange:NSMakeRange(6, 2)] intValue];

    NSDateComponents *components = [[NSDateComponents alloc] init];
    [components setYear:year];
    [components setMonth:month];
    [components setDay:day];

    NSDate *reportDate = [[NSCalendar currentCalendar] dateFromComponents:components];

    NSMutableDictionary *reportTypes = [[NSMutableDictionary alloc] initWithDictionary:errors[errorMessage]];

    NSMutableArray *reports = [[NSMutableArray alloc] initWithArray:reportTypes[dateType]];
    [reports addObject:reportDate];
    reportTypes[dateType] = reports;

    errors[errorMessage] = reportTypes;
}

…and right before line 225 in ReportDownloadOperation.m:

dispatch_async(dispatch_get_main_queue(), ^{
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    dateFormatter.timeStyle = NSDateFormatterNoStyle;
    dateFormatter.dateStyle = NSDateFormatterShortStyle;
    for (NSString *error in errors.allKeys) {
        NSString *message = error;

        NSDictionary *reportTypes = errors[error];
        for (NSString *reportType in reportTypes.allKeys) {
            message = [message stringByAppendingFormat:@"\n\n%@ Reports:", reportType];
            for (NSDate *reportDate in reportTypes[reportType]) {
                message = [message stringByAppendingFormat:@"\n%@", [dateFormatter stringFromDate:reportDate]];
            }
        }

        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Error", nil)
                                                            message:message
                                                           delegate:nil
                                                  cancelButtonTitle:NSLocalizedString(@"OK", nil)
                                                  otherButtonTitles:nil];
        [alertView show];
    }
});

This code generates a summarized error alert for each distinct error message encountered:
img_2703

@ddaddy
Copy link

ddaddy commented Nov 16, 2015

I've been seeing the error The report could not be downloaded, please try again later. but I don't think it's related to 2-factor auth.
Refreshing again seems to pull the report down.

@statcoder
Copy link

Thanks for posting your solution to the problem. For those who might not be aware of the method of creating an app-specific password: https://support.apple.com/en-us/HT204397

@Morpheus2002
Copy link

I'm getting an error after daily report is downloaded. Maybe it's payment download issue?

img_0253

@ddaddy
Copy link

ddaddy commented Nov 20, 2015

Yes it's payments. I haven't had the time to look into it myself yet.
iTunesConnect login page changed.

@nicolasgomollon
Copy link

I’ve just added UI to handle two-step verification and proper app-specific password support to my fork of AppSales, and submitted a pull request to @ddaddy's fork (https://github.com/ddaddy/AppSales-Mobile/pull/1).
Go check it out if you’re interested.

@Morpheus2002
Copy link

@nicolasgomollon does it fix payments download error?

BTW, is there any option in ITC to download payments manually to import them to App Sales?

@ddaddy
Copy link

ddaddy commented Dec 15, 2015

@nicolasgomollon Thanks for your additions. I do apologise, I haven't had the time to take a look yet, but it is on my todo list.

@Morpheus2002 No it won't fix the payments, however that is also on my todo list to take a look at. There's no way to export/import payments as they are literally scraped from the web page.

@Morpheus2002
Copy link

@ddaddy thanks for your answer! I took a look at ITC, but couldn't find any fix for this issue.

@ddaddy
Copy link

ddaddy commented Dec 15, 2015

The payment issue, will be down to the new login view for iTC.

@nicolasgomollon
Copy link

@Morpheus2002 @ddaddy My fork of AppSales does indeed fix the Payments download issue (among other minor issues). I also added in some UI to handle Two-Step Verification code input, since developer accounts with this enabled are now required to verify their account on untrusted devices, so my fork supports these accounts as well.

The problem was initially due to the changed iTunes Connect login page.

The way I accomplished this was by performing the login via the Member Center (which has a much more simplified page structure, and is much less hacky), and then visiting the Payments and Financial Reports page in iTunes Connect. This works because both the Member Center and iTunes Connect use the same cookies to recognize a logged in user.

I’ve made so many other changes to my fork since fixing this, so you might have to dig in to my commit history to find the right commits, or you can download a copy of my fork and give it a try for yourself.


EDIT:
Here are the highlight commits that address this issue:

@ddaddy
Copy link

ddaddy commented Dec 15, 2015

@nicolasgomollon that's awesome, thanks. It just moved higher up my todo list.

@pupasani
Copy link

@nicolasgomollon still getting same payments error (indicated parsing error of login page) on your latest commit

@nicolasgomollon
Copy link

@pupasani Do you mind providing additional details about the error?

The page structure might be a bit different for accounts that only have one vendor ID (and mine happens to have two), which may be the cause of your issue. Could you provide a snippet of the source code of your Payments and Financial Reports page, specifically the part where the vendor ID is shown? (See example snippet below.)

    <form name="mainForm" enctype="multipart/form-data" method="post" action="/WebObjects/iTunesConnect.woa/wo/25.0.0.11.5.0.9.3.1">
        <table width="980" border="0" cellpadding="0" cellspacing="0">
            <tr>
                <td width="8"><img src="https://itc.mzstatic.com/itc/images/wrapper_topl.png" width="8" height="51" alt=""></td>
                <td width="*" background="https://itc.mzstatic.com/itc/images/wrapper_top.png" height="51" align="center" class="header_text">

                    <div class="vendor-id-container">
                        <select onMouseDown="toggleVendorIdWidth()" style='top: 10px' onBlur="this.style.width = '250px'" onChange="this.form.submit();" class="vendor-id-select" id="vendor-id" name="0.0.11.5.0.9.3.1.5.1">
                            <option value="0">Vendor Name One - 8XXXXXXX</option>
                            <option selected="selected" value="1">Vendor Name Two - 8XXXXXXX</option>
                        </select>
                    </div>

                    <p id="header-txt">Payments and Financial Reports</p>
                </td>

@ddaddy
Copy link

ddaddy commented Dec 15, 2015

@nicolasgomollon I have cherry picked some of your changes for my branch thanks.
I noticed on a couple of occasions during testing, if I deleted the payments from my 2 accounts, it would download the same batch of payments for both.

@pupasani
Copy link

@nicolasgomollon my page does not have the vendor-id-container div at all. Here's the snippet:

                <p id="header-txt">Payments and Financial Reports</p>
            </td>
            <td width="8"><img src="https://itc.mzstatic.com/itc/images/wrapper_topr.png" width="8" height="51" alt=""></td>
        </tr>
        <tr>
            <td background="https://itc.mzstatic.com/itc/images/wrapper_10.png" width="8"></td>
            <td bgcolor="#C9C9C9">

@pupasani
Copy link

@Daddy, been using your fork for a long time, just switch to @nicolasgomollon fork to try it out. That fixed a long-term issue I have been having with not being able to download reviews. Also love the Touch ID integration! Hope you incorporated those changes as well :-)

@nicolasgomollon
Copy link

@pupasani That’s strange. Does your vendor ID show up anywhere on that page?

@pupasani
Copy link

No it doesn't - my guess is its not used when there is a single vendor id (like in my case).

@nicolasgomollon
Copy link

@pupasani I think I just nailed this bug and fixed Auto-Fill Vendor ID in my latest commit (nicolasgomollon@8523402) by using a different method. Try it out and let me know how it goes!

@pupasani
Copy link

@nicolasgomollon looks like its working now thanks! One minor issue, it downloaded the last 23 payments and added them to the existing payments instead of replacing them. I deleted all the payments and then re-downloaded, so now the numbers look fine (even with repeated downloads). Unfortunately in this process I lost my payment history from before 23 months ago :-) Do you know any way to manually input those numbers?

@nicolasgomollon
Copy link

@pupasani Sorry about that! That’s actually because I fixed a bug that’s been in the code for quite a long time (nicolasgomollon@2d393d1), where the vendor ID was never saved with each payment, so those payments are now duplicated because they’re technically not the same as the payments saved without it.

Nevertheless, I ran into the same issue, and ended up manually adding my missing payments using some SQLite editor app.

First you’ll need to download the AppSales app container:
0. Make sure that AppSales is closed on your device!

  1. Connect your device.
  2. Open Xcode.
  3. Go to Window → Devices.
  4. Select your device in the left pane.
  5. Click on AppSales in the right.
  6. Click on the little gear below the Installed Apps section, and “Download Container…”

Once you download the container, I would make and keep a copy of it (just in case), and then:

  1. Right-click the container and “Show Package Contents”.
  2. Navigate to AppData → Library → Application Support.
  3. The AppSales.sqlite file is the database that stores all of your AppSales data.

For this next step, you’ll need to use some SQLite editor app (I used MesaSQLite, but any app will get the job done):

  1. In the ZPAYMENT table, insert a new row.
  2. Ensure the Z_PK field is the next consecutive integer.
  3. Set Z_ENT and Z_OPT with the same values as the other rows.
  4. ZMONTH and ZYEAR are the payment month and year, respectively.
  5. The ZACCOUNT field is equal to the Z_PK field for your account in the ZACCOUNT table.
  6. ZAMOUNT is a float of the payment amount.
  7. ZCURRENCY is your three-character currency code (e.g. USD).
  8. ZVENDORID is the vendor ID for your account.
  9. Repeat steps 1-8 until you’ve added all missing payments.
  10. In the Z_PRIMARYKEY table, edit the Z_MAX field for “Payment” to equal the Z_PK field for your last inserted payment.
  11. Save and close the database.

Now we need to replace the app container with our edited one:
0. Make sure that AppSales is closed on your device!

  1. Connect your device.
  2. Open Xcode.
  3. Go to Window → Devices.
  4. Select your device in the left pane.
  5. Click on AppSales in the right.
  6. Click on the little gear below the Installed Apps section, and “Replace Container…”
  7. Select your edited container, and once it’s copied over to your device, boom, you’re done.

Open the AppSales app on your device once you’re done, and make sure that everything works as expected. Let me know if you run into any trouble along the way!

@nicolasgomollon
Copy link

@pupasani Since you mentioned that you use the reviews feature, I would suggest that you try out my latest commit, as I’ve greatly improved the reliability of the feature and grouped reviews by app version.

@pupasani
Copy link

Thanks @nicolasgomollon, reviews feature indeed looks good. But two minor issues there: firstly I miss the ability to download reviews for all my products at once, have to download each product's reviews separately. Secondly, for some reason I have a bunch of reviews without a version set (think these were downloaded previously) and the app crashes anytime I try to open one of those.

@nicolasgomollon
Copy link

@pupasani That feature’s not too difficult to add back in, so I’ll look into doing that next. As for the other issue, I recommend deleting all previous reviews from the database and then downloading them again within the app (they should all be redownloaded again—they were for me). If not, I’ll try adding in the ability to delete reviews individually within the app.

@ddaddy
Copy link

ddaddy commented Dec 22, 2015

@nicolasgomollon I'm thinking it might be worth using your fork now instead of mine as you have done a lot of tremendous work in it. I started cherry picking some of your updates, but it's seems pointless.
Can you enable issues in the settings of your fork please?
Thanks

@nicolasgomollon
Copy link

@ddaddy I hadn’t realized that feature was disabled! It should be on now. Thanks!

@ddaddy
Copy link

ddaddy commented Dec 22, 2015

Yeh me neither. It must be a new thing.
Thanks

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

6 participants