Python interface de PayPal - urllib.urlencode des caractères non-ASCII défaut
Je suis en train de mettre en œuvre PayPal IPN fonctionnalité. Le protocole de base est en tant que tel:
- Le client est redirigé à partir de mon site vers le site de PayPal pour effectuer le paiement. Il se connecte à son compte, qui autorise le paiement.
- PayPal appelle une page sur mon serveur en passant dans les détails, comme la POSTE. Les détails incluent le nom d'une personne, l'adresse et les informations de paiement etc.
- J'ai besoin d'appeler une URL sur le site de PayPal en interne à partir de ma page de traitement de passer à l'arrière de tous les paramètres qui ont été passés en abovem et une autre appelée " cmd " avec une valeur de '_notify-validate".
Quand j'essaie de urllib.urlencode les paramètres qui PayPal m'a envoyé, je reçois 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)
Je comprends que urlencode ne le codage ASCII, et dans certains cas, un utilisateur informations de contact peut contenir des caractères non-ASCII. C'est compréhensible. Ma question est, comment puis-je encoder les caractères non-ASCII pour l'Affichage d'une URL à l'aide de urllib2.urlopen(req) (ou autre méthode)
Détails:
J'ai lu les params dans le compte PayPal de l'original de la demande comme suit (le GET est pour les tests):
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()
Le code que j'utilise pour l'envoi de la demande à PayPal à partir de la page de traitement est:
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
Évidemment, le problème se pose uniquement si le nom de quelqu'un, d'adresse ou d'autres champ utilisé pour le paiement PayPal ne relève pas de la plage ASCII.
Vous devez vous connecter pour publier un commentaire.
Essayer de convertir l'params dictionnaire de l'utf-8 en premier... urlencode semble que c'est mieux que unicode:
Bien sûr, cela suppose que votre entrée est au format unicode. Si votre entrée est autre chose que de l'unicode, vous aurez envie de le décoder en unicode d'abord, puis de l'encoder:
Au lieu d'un codage à
utf-8
, on doit coder pour ce que jamais l'paypal utilise pour le poste.Il est disponible sous la touche 'charset' dans le formulaire paypal envoie.
Donc le code suivant fonctionné pour moi:
Je sais que c'est un peu tard pour carillon ici, mais la meilleure solution que j'ai trouvé a été de même à ne pas analyser ce qu'ils ont à donner en retour. Dans django (vous ne savez pas ce que vous utilisez), j'ai été en mesure d'obtenir la demande brute, ils ont envoyé des, qui j'ai passé verbatim. Alors c'était juste une question de mettre la touche cmd sur que.
De cette façon, il n'a jamais questions de codage, ils vous envoyer, vous êtes juste de l'envoyer droit de retour.