Frage

Ich versuche, PayPal -IPN -Funktionalität zu implementieren. Das Grundprotokoll ist als solches:

  1. Der Kunde wird von meiner Website auf die PayPal -Website umgeleitet, um die Zahlung abzuschließen. Er meldet sich in sein Konto an und autorisiert die Zahlung.
  2. PayPal ruft eine Seite auf meinem Server in Details als Beitrag auf. Details enthalten den Namen, die Adresse und die Zahlungsinformationen einer Person usw.
  3. Ich muss eine URL auf der PayPal-Site intern auf meiner Verarbeitungsseite anrufen, die alle Parameter zurückgibt, die in Abovem übergeben wurden, und eine zusätzliche als "CMD" mit einem Wert von "_notify-Validat".

Wenn ich versuche, die Parameter zu urllib.urlencode, die PayPal an mich gesendet hat, bekomme ich eine:

While calling send_response_to_paypal. Traceback (most recent call last):
  File "<snip>/account/paypal/views.py", line 108, in process_paypal_ipn
    verify_result = send_response_to_paypal(params)
  File "<snip>/account/paypal/views.py", line 41, in send_response_to_paypal
    params = urllib.urlencode(params)
  File "/usr/local/lib/python2.6/urllib.py", line 1261, in urlencode
    v = quote_plus(str(v))
UnicodeEncodeError: 'ascii' codec can't encode character u'\ufffd' in position 9: ordinal not in range(128)

Ich verstehe, dass Urlencode ASCII-Codierung durchführt, und in bestimmten Fällen kann die Kontaktinformationen eines Benutzers Nicht-ASCII-Zeichen enthalten. Das ist verständlich. Meine Frage ist, wie codiere ich Nicht-ASCII-Zeichen für das Posten in einer URL unter Verwendung von Urllib2.urlopen (REQ) (oder einer anderen Methode)

Einzelheiten:

Ich habe die Parameter in der ursprünglichen Anfrage von PayPal wie folgt gelesen (das Get ist zum Testen):

def read_ipn_params(request):
    if request.POST:  
        params= request.POST.copy()  
        if "ipn_auth" in request.GET:
            params["ipn_auth"]=request.GET["ipn_auth"]
        return params
    else:  
        return request.GET.copy()  

Der Code, den ich verwendet, um die Anfrage an PayPal von der Verarbeitungsseite zurückzuschicken, lautet:

def send_response_to_paypal(params):
    params['cmd']='_notify-validate'  
    params = urllib.urlencode(params)  
    req = urllib2.Request(PAYPAL_API_WEBSITE, params)  
    req.add_header("Content-type", "application/x-www-form-urlencoded") 
    response = urllib2.urlopen(req)  
    status = response.read()  
    if not status == "VERIFIED":  
        logging.warn("PayPal cannot verify IPN responses: " + status)
        return False

    return True

Offensichtlich tritt das Problem nur auf, wenn der Name oder die Adresse eines Menschen oder ein anderes Feld, das für die PayPal -Zahlung verwendet wird, nicht in den ASCII -Bereich fällt.

War es hilfreich?

Lösung

Versuchen Sie, das Params-Wörterbuch zuerst in UTF-8 zu konvertieren ... Urlencode scheint das besser zu mögen als Unicode:

params = urllib.urlencode(dict([k, v.encode('utf-8')] for k, v in params.items()))

Dies setzt natürlich voraus, dass Ihre Eingabe Unicode ist. Wenn Ihre Eingabe etwas anderes als Unicode ist, möchten Sie sie zuerst zu Unicode dekodieren, dann codieren Sie sie:

params['foo'] = my_raw_input.decode('iso-8859-1')
params = urllib.urlencode(dict([k, v.encode('utf-8')] for k, v in params.items()))

Andere Tipps

Anstatt zu codieren zu utf-8, man sollte für das PayPal für den Beitrag kodieren. Es ist unter dem Key 'Charset' im Formular PayPal Sends erhältlich.

Der folgende Code funktionierte also für mich:

data = dict([(k, v.encode(data['charset'])) for k, v in data.items()])

Ich weiß, dass es ein bisschen spät ist, hier einzuhacken, aber die beste Lösung, die ich gefunden habe, war nicht einmal, was sie zurückzugeben. In Django (weiß nicht, was Sie verwenden) konnte ich die von ihnen gesendete rohe Anfrage erhalten, die ich wörtlich zurückgegeben habe. Dann ging es nur darum, den CMD -Schlüssel darauf zu setzen.

Auf diese Weise spielt es nie eine Rolle, welche Codierung sie Ihnen senden. Sie senden es einfach sofort zurück.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top