Using Batch Token in ListPayment Python SDK

I keep getting an error when using the Python List Payment method for the V1 Transaction API. I get invalid batch token - bad request. How do I need to format the batch token in order to get the next set of data? Does anyone have a sample of the batch token being used succesfully?

Initial request:
v1_transactions_lstpay = v1_transactions_api.list_payments(location_id = value, begin_time = beginTime, end_time = endTime, limit = 200)

Second call using Batch Token received:
v1_transactions_lstpay2 = v1_transactions_api.list_payments(location_id = value, batch_token = v1_transactions_lstpay.headers['Link'])

Error message: {‘message’: ‘Invalid batch token’, ‘type’: ‘bad_request’}

Hey @armlopez I believe this is due to the Link header containing extra information besides just the batch token, In the old SDK we had a built-in function that did this:

        link_header = self.getheader('Link')
        if link_header != None:
            match = re.match("^<([^>]+)>;rel='next'$", link_header)
            if match != None:
                next_url = match.group(1)
                parsed_url = urlparse(next_url)
                parameters = parse_qs(parsed_url.query)
                if 'batch_token' in parameters:
                    return parameters['batch_token'][0]
        return None

Could you see if this works for you on at least retrieving the batch token from the Link header?

Hi @sjosey, there is a lot of dependencies missing here and thus I cannot get the code to work.

Here is my header that I get from the API:
{'Content-Encoding': 'gzip', 'Content-Type': 'application/json', 'Link': "<https://connect.squareup.com/v1/DEPW2ZMK96YZS/payments?batch_token=Zo6WqHjvqWyp0NjChnT2nfsWpcCcsNxRG1EdvRDo3YGBJnyydOegDvDTi3y5bPpIFrPBOui9sYsj74EXMqqKKuddeKEcABwSLxLSwtxP6GfBZWVogeRcW3GLpqLXzNp373HVzTAyS8O01N&begin_time=2020-03-02T06%3A00%3A00Z&end_time=2020-03-31T17%3A59%3A59Z&limit=200>;rel='next'", 'Vary': 'Origin, Accept-Encoding', 'X-Content-Type-Options': 'nosniff', 'X-Download-Options': 'noopen', 'X-Frame-Options': 'SAMEORIGIN', 'X-Permitted-Cross-Domain-Policies': 'none', 'X-Xss-Protection': '1; mode=block', 'Date': 'Wed, 29 Apr 2020 02:16:05 GMT', 'Strict-Transport-Security': 'max-age=631152000; includeSubDomains; preload', 'Transfer-Encoding': 'chunked'}

I’ve tried manually extracting the batch token which in this case is:
Zo6WqHjvqWyp0NjChnT2nfsWpcCcsNxRG1EdvRDo3YGBJnyydOegDvDTi3y5bPpIFrPBOui9sYsj74EXMqqKKuddeKEcABwSLxLSwtxP6GfBZWVogeRcW3GLpqLXzNp373HVzTAyS8O01N&begin_time=2020-03-02T06%3A00%3A00Z&end_time=2020-03-31T17%3A59%3A59Z&limit=200

However this still generated an error. Would you be able to guide me what the batch token is suppose to look like? Also how it should be formatted?

It looks like the batch_token is including several fields that are not part of the actual token. As can be seen in your example, it includes begin_time, end_time, and limit which is not part of the batch token. In your example, the token is only Zo6WqHjvqWyp0NjChnT2nfsWpcCcsNxRG1EdvRDo3YGBJnyydOegDvDTi3y5bPpIFrPBOui9sYsj74EXMqqKKuddeKEcABwSLxLSwtxP6GfBZWVogeRcW3GLpqLXzNp373HVzTAyS8O01N

Also, just to be clear, I tested with the above example, and was able to extract the batch token with the entire Link header.

import re
from urlparse import urlparse
from urlparse import parse_qs

link_header ="<https://connect.squareup.com/v1/DEPW2ZMK96YZS/payments?batch_token=Zo6WqHjvqWyp0NjChnT2nfsWpcCcsNxRG1EdvRDo3YGBJnyydOegDvDTi3y5bPpIFrPBOui9sYsj74EXMqqKKuddeKEcABwSLxLSwtxP6GfBZWVogeRcW3GLpqLXzNp373HVzTAyS8O01N&begin_time=2020-03-02T06%3A00%3A00Z&end_time=2020-03-31T17%3A59%3A59Z&limit=200>;rel='next'"

def get_batch_token(link_header):
  if link_header != None:
    match = re.match("^<([^>]+)>;rel='next'$", link_header)
    if match != None:
        next_url = match.group(1)
        parsed_url = urlparse(next_url)
        parameters = parse_qs(parsed_url.query)
        if 'batch_token' in parameters:
            return parameters['batch_token'][0]
    return None

print(get_batch_token(link_header))

this printed Zo6WqHjvqWyp0NjChnT2nfsWpcCcsNxRG1EdvRDo3YGBJnyydOegDvDTi3y5bPpIFrPBOui9sYsj74EXMqqKKuddeKEcABwSLxLSwtxP6GfBZWVogeRcW3GLpqLXzNp373HVzTAyS8O01N.

1 Like

Hi @sjosey, this was nearly perfect haha! This should work on Python 2, I am using Python 3 so the urlparse library was renamed haha. Thank you so much for that help! I was bagging my head on this one until you solved the problem :smiley:

Here is the updated code for Python 3:

import re
from urllib.parse import urlparse
from urllib.parse import parse_qs

def get_batch_token(link_header):
  if link_header != None:
    match = re.match("^<([^>]+)>;rel='next'$", link_header)
    if match != None:
        next_url = match.group(1)
        parsed_url = urlparse(next_url)
        parameters = parse_qs(parsed_url.query)
        if 'batch_token' in parameters:
            return parameters['batch_token'][0]
    return None
1 Like

Thanks for sharing that :slight_smile: I forgot to mention that! I’m definitely not a Python dev, and pulled this from our old SDK lol. Glad it worked, though!