2009-04-25 9 views
20

Estoy tratando de implementar la funcionalidad de PayPal IPN. El protocolo básico es el siguiente:Interfaz de Python con PayPal - urllib.urlencode caracteres no ASCII que fallan

  1. El cliente se redirige de mi sitio al sitio de PayPal para completar el pago. Se registra en su cuenta, autoriza el pago.
  2. PayPal llama a una página de mi servidor que transmite los detalles como POST. Los detalles incluyen el nombre de una persona, dirección e información de pago, etc.
  3. Necesito llamar internamente una URL en el sitio de PayPal desde mi página de procesamiento, devolviendo todos los parámetros que se pasaron en abovem y uno adicional llamado 'cmd' con un valor de '_notify-validate'.

Cuando intento urllib.urlencode los parametros que utiliza PayPal ha enviado a mí, me sale un:

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) 

entiendo que urlencode hace la codificación ASCII, y en ciertos casos, la información de contacto de un usuario

puede contener caracteres que no sean ASCII. Esto es comprensible Mi pregunta es, ¿cómo codificar los caracteres no ASCII para su publicación en una dirección URL utilizando urllib2.urlopen (req) (u otro método)

Detalles:

leí los parametros en la solicitud inicial de PayPal como de la siguiente manera (el GET es para la prueba):

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() 

el código que utilizo para enviar de regreso a la solicitud de PayPal desde la página de procesamiento es:

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 

Obviamente, el problema solo surge si el nombre o la dirección de una persona u otro campo utilizado para el pago de PayPal no entran en el rango ASCII.

Respuesta

41

pruebas a convertir el diccionario params a UTF-8 primero ... urlencode parece que le gusta que mejor que Unicode:

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

Por supuesto, esto supone que su entrada es Unicode. Si la entrada es algo que no sea Unicode, usted querrá decodificarlo a Unicode primero, y luego codificarlo:

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

Tiene razón; esto eliminó la Excepción de URLEncode. Sin embargo, ahora PayPal me está dando una respuesta inválida. Son tan dolorosos ... –

+1

así que, krys, ¿documentan ellos (paypal) qué codificación desean, si no es utf-8? –

+0

¡Gracias! Error menor: hay mucho más al final del primer examen que das. –

6

En lugar de codificación de utf-8, se debe codificar a lo que cada vez el paypal está utilizando para el puesto . Está disponible bajo la clave 'charset' en la forma que envía PayPal.

Así que el siguiente código trabajó para mí:

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

3

Sé que es un poco tarde para meter su cuchara aquí, pero la mejor solución que encontré fue que ni siquiera analizar lo que eran devolviendo. En django (no sé lo que estás usando) pude obtener la solicitud sin procesar que enviaron, la cual transmití al pie de la letra. Entonces solo era cuestión de poner la clave cmd en eso.

De esta manera, nunca importa la codificación que le envíen, simplemente la está enviando de regreso.

+0

¿Has probado esto con una respuesta de IPN que incluye caracteres unicode como ñ, á, é, etc.? El problema solo ocurre con estos tipos de personajes. –

Cuestiones relacionadas