سؤال

أحاول تنفيذ وظائف PayPal IPN. البروتوكول الأساسي على هذا النحو:

  1. يتم إعادة توجيه العميل من موقعي إلى موقع PayPal لإكمال الدفع. انه يسجل إلى حسابه، ويأذن الدفع.
  2. يستدعي PayPal صفحة على الخادم الخاص بي يمر في التفاصيل كما نشر. تشمل التفاصيل اسم الشخص وعنوانها ومعلومات الدفع وما إلى ذلك
  3. أحتاج إلى استدعاء عنوان URL على موقع PayPal داخليا من صفحة المعالجة الخاصة بي يمر بجميع المعالم التي تم تمريرها في Abovem وواحدة إضافية تسمى "CMD" بقيمة "_Notify-التحقق من صحة".

عندما أحاول urllib.urlencode، أرسلت المعالم التي أرسلتها باي بال لي، أحصل على:

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)

أفهم أن URLEncode يقوم بترميز ASCII، وفي بعض الحالات، يمكن أن تحتوي معلومات جهات الاتصال الخاصة بالمستخدم على أحرف غير ASCII. هذا مفهوم. سؤالي هو، كيف يمكنني تشفير أحرف غير ASCII للنشر إلى عنوان URL باستخدام URLLIB2.URLOPEN (REQ) (أو طريقة أخرى)

تفاصيل:

قرأت المعالم في طلب PayPal الأصلي على النحو التالي (GET IS لاختبار):

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

الرمز الذي أستخدمه لإرسال طلب مرة أخرى إلى PayPal من صفحة المعالجة هو:

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

من الواضح أن المشكلة تنشأ فقط إذا كان اسم شخص أو عنوان شخص ما أو حقل آخر يستخدم لدفع PayPal لا يقع في نطاق ASCII.

هل كانت مفيدة؟

المحلول

حاول تحويل قاموس الإطفاء إلى UTF-8 أولا ... يبدو أن Urlencode ترغب في ذلك أفضل من Unicode:

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

بالطبع، هذا يفترض إدخالك هو Unicode. إذا كان الإدخال الخاص بك شيء آخر غير Unicode، فستحتاج إلى فك تشفيره إلى Unicode أولا، ثم ترميزه:

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

نصائح أخرى

بدلا من الترميز ل utf-8, ، يجب على المرء أن يرمز إلى ما يستخدمه PayPal من أي وقت مضى لهذا المنصب. إنه متاح تحت مفتاح "Charset" في نموذج يرسل PayPal.

لذلك عملت الكود التالي بالنسبة لي:

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

أعلم أنه متأخرا بعض الشيء للتناغم هنا، لكن أفضل حل وجدت أنه لم يكن حتى تحليل ما كانوا يعيدون فيه. في Django (لا تعرف ما الذي تستخدمه) كنت قادرا على الحصول على طلب RAW أرسلوا، والذي مررته باستخدام حرفي. ثم كانت مجرد مسألة وضع مفتاح CMD على ذلك.

بهذه الطريقة لا يهم أبدا ما يرمزك، فأنت فقط ترسله مرة أخرى.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top