I have been fighting with Paypals API, and more specifically I've been trying to implement IPN (instant payment notifications) into my flask app. I have gotten it to the point where it works as long as I don't include any special characters. Unfortunately my last name is Engström...
The way it works is that paypal sends a bunch of parameters to you, which you are then supposed to send back exactly the way they came to you, with the addition of a parameter specifying cmd=_notify-validate
My current code is essentially:
@app.route("/paypal_ipn", methods=['POST', 'GET'])
def paypal_ipn_listener():
# Returning message as-is with the notify-validate request
raw_data = "cmd=_notify-validate&" + request.get_data()
response = requests.post(VERIFY_URL, params=raw_data, verify=True)
response.raise_for_status()
# See if PayPal confirms the validity of the IPN received
if response.text == 'VERIFIED':
print(OKGREEN + "Verified IPN response received." + ENDC)
elif response.text == 'INVALID':
# Don't trust
print(FAIL + "Invalid IPN response." + ENDC)
else:
print("Some other response.")
print(response.text)
return ""
And this code in fact works fine so long as my last name is Engstrom rather than Engström when paying for something.
My troubleshooting so far:
Apparently Paypal uses the windows-1252 encoding per default. I however changed for it to use the utf-8 encoding using this SO answer: https://stackoverflow.com/a/46303635/5331467, however that didn't do anything when I made a payment, and I'm sticking with the IPN simulator tool for now, which is stuck with windows-1252
If I print request.form
I get among other things ImmutableMultiDict([('last_name', u'Engstr\ufffdm'')
which notably looks the same for ä and ö, which at least tells me it sees no distinction between them
The stuff that's in request.get_data() is
payment_type=instant&payment_date=15%3A08%3A30%20Jan%2028%2C%202022%20PST&payment_status=Completed&address_status=confirmed&payer_status=verified&first_name=John&last_name=Engstr%F6m&payer_email=buyer@paypalsandbox.com&payer_id=TESTBUYERID01&address_name=John%20Smith&address_country=United%20States&address_country_code=US&address_zip=95131&address_state=CA&address_city=San%20Jose&address_street=123%20any%20street&business=seller@paypalsandbox.com&receiver_email=seller@paypalsandbox.com&receiver_id=seller@paypalsandbox.com&residence_country=US&item_name1=something&item_number1=AK-1234&tax=2.02&mc_currency=USD&mc_fee=0.44&mc_gross=12.34&mc_gross_1=12.34&mc_handling=2.06&mc_handling1=1.67&mc_shipping=3.02&mc_shipping1=1.02&txn_type=cart&txn_id=474083376¬ify_version=2.1&custom=xyz123&invoice=abc1234&test_ipn=1&verify_sign=A8Vpc0Ws5acpR3s0gcM6u4Qtk1utA8eY7wJKy6n.AkPJ6RHIQeSSmBzL
where it says &last_name=Engstr%F6m
Now I don't know if what I want is for it to actually have the right encoding when being sent, or if theres some way for me to ensure it never touches the encoding anyways.
**TL;DR
Taking an incoming POST message and sending it straight back in Flask still screws up the formatting somehow.**