Use python to export report

Hi,
I am using the following curl command with success:
curl -v POST 'https://integrations.expensify.com/Integration-Server/ExpensifyIntegrations' -d 'requestJobDescription={ "type":"file", "credentials":{ "partnerUserID":"userid", "partnerUserSecret":"secret" }, "onReceive":{ "immediateResponse":["returnRandomFileName"] }, "inputSettings":{ "type":"combinedReportData", "filters":{ "startDate":"2019-11-01", "endDate":"2020-03-22" } }, "outputSettings":{ "fileExtension":"json", "fileBasename":"myExport" } }' --data-urlencode "[email protected]"
This command is sending the following POST data:
0000: requestJobDescription={. "type":"file",. "credenti
0040: als":{. "partnerUserID":"userid
0080: seil_com",. "partnerUserSecret":"secret
00c0: ". },. "onReceive":{.
0100: "immediateResponse":["returnRandomFileName"]. },.
0140: "inputSettings":{. "type":"combinedReportData",.
0180: "filters":{. "startDate":"2019-11-01",.
01c0: "endDate":"2020-03-22". }. },.
0200: "outputSettings":{. "fileExtension":"json",.
0240: "fileBasename":"myExport". }. }&template=%3C%23if%20
0280: addHeader%20%3D%3D%20true%3E%0A%20%20%20%20Merchant%2COriginal%2
02c0: 0Amount%2CCategory%2CReport%20number%2CExpense%20number%3C%23lt%
0300: 3E%0A%3C%2F%23if%3E%0A%3C%23assign%20reportNumber%20%3D%201%3E%0
0340: A%3C%23assign%20expenseNumber%20%3D%201%3E%0A%3C%23list%20report
0380: s%20as%20report%3E%0A%20%20%20%20%3C%23list%20report.transaction
03c0: List%20as%20expense%3E%0A%20%20%20%20%20%20%20%20%24%7Bexpense.m
0400: erchant%7D%2C%3C%23t%3E%0A%20%20%20%20%20%20%20%20%3C%23--%20not
0440: e%3A%20expense.amount%20prints%20the%20original%20amount%20only%
0480: 20--%3E%0A%20%20%20%20%20%20%20%20%24%7Bexpense.amount%7D%2C%3C%
04c0: 23t%3E%0A%20%20%20%20%20%20%20%20%24%7Bexpense.category%7D%2C%3C
0500: %23t%3E%0A%20%20%20%20%20%20%20%20%24%7BreportNumber%7D%2C%3C%23
0540: t%3E%0A%20%20%20%20%20%20%20%20%24%7BexpenseNumber%7D%3C%23lt%3E
0580: %0A%20%20%20%20%20%20%20%20%3C%23assign%20expenseNumber%20%3D%20
05c0: expenseNumber%20%2B%201%3E%0A%20%20%20%20%3C%2F%23list%3E%0A%20%
0600: 20%20%20%3C%23assign%20reportNumber%20%3D%20reportNumber%20%2B%2
0640: 01%3E%0A%3C%2F%23list%3E%0A
I am not able to reproduce the same thing with Python.
The nearest I am able to get is:
equestJobDescription=%7B%22type%22%3A+%22file%22%2C+%22credentials%22%3A+%7B%22partnerUserID%22%3A+%22userid%22%2C+%22partnerUserSecret%22%3A+%secret%22%7D%2C+%22onReceive%22%3A+%7B%22immediateResponse%22%3A+%5B%22returnRandomFileName%22%5D%7D%2C+%22inputSettings%22%3A+%7B%22type%22%3A+%22combinedReportData%22%2C+%22filter%22%3A+%7B%22startDate%22%3A+%222019-11-01%22%2C+%22endDate%22%3A+%222020-03-22%22%7D%7D%2C+%22outputSettings%22%3A+%7B%22fileExtension%22%3A+%22json%22%7D%7D&template=%3C%23if+addHeader+%3D%3D+true%3EMerchant%2COriginal+Amount%2CCategory%2CReport+number%2CExpense+number%3C%23lt%3E%3C%2F%23if%3E%3C%23assign+reportNumber+%3D+1%3E%3C%23assign+expenseNumber+%3D+1%3E%3C%23list+reports+as+report%3E%3C%23list+report.transactionList+as+expense%3E%24%7Bexpense.merchant%7D%2C%3C%23t%3E%3C%23--+note%3A+expense.amount+prints+the+original+amount+only+--%3E%24%7Bexpense.amount%7D%2C%3C%23t%3E%24%7Bexpense.category%7D%2C%3C%23t%3E%24%7BreportNumber%7D%2C%3C%23t%3E%24%7BexpenseNumber%7D%3C%23lt%3E%3C%23assign+expenseNumber+%3D+expenseNumber+%2B+1%3E%3C%2F%23list%3E%3C%23assign+reportNumber+%3D+reportNumber+%2B+1%3E%3C%2F%23list%3E
I have the following error:
{'responseMessage': 'Error while parsing job description', 'responseCode': 500}
The only difference is that the first part is URL encoded.
Here is my Python code:
_export_template2 = "<#if addHeader == true>Merchant,Original Amount,Category,Report number,Expense number<#lt></#if><#assign reportNumber = 1><#assign expenseNumber = 1><#list reports as report><#list report.transactionList as expense>${expense.merchant},<#t><#-- note: expense.amount prints the original amount only -->${expense.amount},<#t>${expense.category},<#t>${reportNumber},<#t>${expenseNumber}<#lt><#assign expenseNumber = expenseNumber + 1></#list><#assign reportNumber = reportNumber + 1></#list>" JobDescription_exporter = {"requestJobDescription": json.dumps({ "type": "file", "credentials": { "partnerUserID": _partnerUserID, "partnerUserSecret": _partnerUserSecret }, "onReceive":{ "immediateResponse":["returnRandomFileName"] }, "inputSettings": { "type": "combinedReportData", "filter": { "startDate": "2019-11-01", "endDate": "2020-03-22" } }, "outputSettings": { "fileExtension": "json" } }) } # This is to combine the job description and template in one dict. post_data = {**JobDescription_exporter,**{"template":_export_template3}} headers = {'content-type': 'application/x-www-form-urlencoded'} result = requests.post(self._base_url, data=post_data, headers=headers) print("header: ",result.request.headers) print("data: ",post_data) print("body: ",result.request.body) print("status_code: ",result.status_code) print("result: ",result.json())
It seems the first JSON part (requestJobDescription) must be sent without encoding, but the second part (template), must be sent with encoding.
Answers
-
Hi @Vin100,
If you see the outgoing request as
requestJobDescription=%7B%22type%22%3A+%22file%22%2C....
, it means that therequestJobDescription
parameter itself is being URL-encoded, which shouldn't be the case (you should seerequestJobDescription={"type":+"file"...
)We have a few existing posts in the community about using Python, maybe one of them will contain a useful code snippet you can reuse?
-
I already read them all. I thought it was that (because of my curl dump)
But with Python, I didn't find the way to not encode this part but encode the template. Everybody (when doing the export) use the code above.
-
Just found the difference.
Curl use post (in your examples)
I was trying with python post requests, but it work only with get.
Python get and post is not handing the encoding the same way.