Python實(shí)現(xiàn)支付寶支付功能

網(wǎng)上搜【Python支付寶】始腾,搜到的結(jié)果州刽,除了發(fā)布的人不一樣之外,內(nèi)容一模一樣浪箭。拿過(guò)來(lái)用的時(shí)候老是失敗穗椅,要么合作身份者ID不正確,要么簽名驗(yàn)證出錯(cuò)奶栖,修改了幾次ID匹表,加密也沒(méi)有問(wèn)題门坷。

不知道是我復(fù)制的有問(wèn)題,還是這demo本身就有問(wèn)題桑孩。反正我就是調(diào)不出支付頁(yè)面拜鹤。后來(lái)發(fā)現(xiàn)要加密的數(shù)據(jù)在處理上出現(xiàn)了問(wèn)題框冀。真是醉了啊蓬抄,所有人都復(fù)制的好起勁傲挂小??声畏?

當(dāng)我看著搜到的結(jié)果中有這幾行的時(shí)候。序愚。(-"-怒)(-"-怒)(-"-怒)

最后復(fù)制粘貼率碾,修修改改。撑刺。

代碼:實(shí)現(xiàn)的是即時(shí)到賬接口

1鹉胖、調(diào)起支付頁(yè)面方法

def smart_str(s, encoding='utf-8', strings_only=False, errors='strict'):
    """
    Returns a bytestring version of 's', encoded as specified in 'encoding'.

    If strings_only is True, don't convert (some) non-string-like objects.
    """
    if strings_only and isinstance(s, (types.NoneType, int)):
        return s
    if not isinstance(s, basestring):
        try:
            return str(s)
        except UnicodeEncodeError:
            if isinstance(s, Exception):
                # An Exception subclass containing non-ASCII data that doesn't
                # know how to print itself properly. We shouldn't raise a
                # further exception.
                return ' '.join([smart_str(arg, encoding, strings_only,
                                           errors) for arg in s])
            return str(s).encode(encoding, errors)
    elif isinstance(s, str):
        return s.encode(encoding, errors)
    elif s and encoding != 'utf-8':
        return s.decode('utf-8', errors).encode(encoding, errors)
    else:
        return s


# 對(duì)數(shù)組排序并除去數(shù)組中的空值和簽名參數(shù)
# 返回?cái)?shù)組和鏈接串
def params_filter(params):
    prestr = ''
    params = OrderedDict({k: v for k, v in params.items() if v != ''})
    params = OrderedDict(sorted(params.items(), key=lambda t: t[0]))
    print(params)
    for k in params:
        prestr += k + '=' + params[k] + '&'
    prestr = prestr[:-1]
    return params, prestr


# 生成簽名結(jié)果
def build_mysign(prestr, key, sign_type='MD5'):
    if sign_type == 'MD5':
        m = hashlib.md5()
        m.update((prestr + key).encode("utf-8"))
        encodeStr = m.hexdigest()
        return encodeStr
    return ''

# 網(wǎng)關(guān)地址
_GATEWAY = 'https://mapi.alipay.com/gateway.do?'

def create_direct_pay_by_user(tn, subject, body, total_fee):
    params = OrderedDict()
    params['service'] = 'create_direct_pay_by_user'
    params['payment_type'] = '1'

    # 獲取配置文件
    params['partner'] = Settings.ALIPAY_PARTNER
    params['seller_email'] = Settings.ALIPAY_SELLER_EMAIL
    params['return_url'] = Settings.ALIPAY_RETURN_URL
    params['notify_url'] = Settings.ALIPAY_NOTIFY_URL
    params['_input_charset'] = Settings.ALIPAY_INPUT_CHARSET
    params['show_url'] = Settings.ALIPAY_SHOW_URL

    # 從訂單數(shù)據(jù)中動(dòng)態(tài)獲取到的必填參數(shù)
    params['out_trade_no'] = tn  # 請(qǐng)與貴網(wǎng)站訂單系統(tǒng)中的唯一訂單號(hào)匹配
    params['subject'] = subject  # 訂單名稱(chēng),顯示在支付寶收銀臺(tái)里的“商品名稱(chēng)”里够傍,顯示在支付寶的交易管理的“商品名稱(chēng)”的列表里甫菠。
    params['body'] = body  # 訂單描述、訂單詳細(xì)冕屯、訂單備注寂诱,顯示在支付寶收銀臺(tái)里的“商品描述”里
    params['total_fee'] = total_fee  # 訂單總金額,顯示在支付寶收銀臺(tái)里的“應(yīng)付總額”里

     # 擴(kuò)展功能參數(shù)——網(wǎng)銀提前
    if bank=='alipay' or bank=='':
        params['paymethod'] = 'directPay'   # 支付方式安聘,四個(gè)值可選:bankPay(網(wǎng)銀); cartoon(卡通); directPay(余額); CASH(網(wǎng)點(diǎn)支付)
        params['defaultbank'] = ''          # 支付寶支付痰洒,這個(gè)為空
    else:
        params['paymethod'] = 'bankPay'     # 默認(rèn)支付方式,四個(gè)值可選:bankPay(網(wǎng)銀); cartoon(卡通); directPay(余額); CASH(網(wǎng)點(diǎn)支付)
        params['defaultbank'] = bank        # 默認(rèn)網(wǎng)銀代號(hào)浴韭,代號(hào)列表見(jiàn)http://club.alipay.com/read.php?tid=8681379   

    params, prestr = params_filter(params)
    params['sign'] = build_mysign(prestr, Settings.ALIPAY_KEY, Settings.ALIPAY_SIGN_TYPE)
    params['sign_type'] = Settings.ALIPAY_SIGN_TYPE

    return _GATEWAY + urlencode(params)


def notify_verify(post):
    # 初級(jí)驗(yàn)證--簽名
    _,prestr = params_filter(post)
    mysign = build_mysign(prestr, settings.ALIPAY_KEY, settings.ALIPAY_SIGN_TYPE)

    if mysign != post.get('sign'):
        return False
    
    # 二級(jí)驗(yàn)證--查詢(xún)支付寶服務(wù)器此條信息是否有效
    params = {}
    params['partner'] = settings.ALIPAY_PARTNER
    params['notify_id'] = post.get('notify_id')

    gateway = 'https://mapi.alipay.com/gateway.do?service=notify_verify&'
    verify_result = urlopen(gateway, urlencode(params)).read()
    if verify_result.lower().strip() == 'true':
        return True
    return False

2丘喻、config.py

class Settings:
  # 安全檢驗(yàn)碼,以數(shù)字和字母組成的32位字符
  ALIPAY_KEY = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'

  ALIPAY_INPUT_CHARSET = 'utf-8'

  # 合作身份者ID念颈,以2088開(kāi)頭的16位純數(shù)字
  ALIPAY_PARTNER = 'xxxxxxxxxxxxxxxx'

  # 簽約支付寶賬號(hào)或賣(mài)家支付寶帳戶(hù)
  ALIPAY_SELLER_EMAIL = 'ls@abc.com'

  ALIPAY_SIGN_TYPE = 'MD5'

  # 付完款后跳轉(zhuǎn)的頁(yè)面(同步通知) 要用 http://格式的完整路徑泉粉,不允許加?id=123這類(lèi)自定義參數(shù)
  ALIPAY_RETURN_URL='http://www.xxx.com/alipay/return/'

  # 交易過(guò)程中服務(wù)器異步通知的頁(yè)面 要用 http://格式的完整路徑,不允許加?id=123這類(lèi)自定義參數(shù)
  ALIPAY_NOTIFY_URL='http://www.xxx.com/alipay/notify/'

3舍肠、view.py

url = create_direct_pay_by_user(order_no, "名稱(chēng)", "描述", total_cost)
        # 去支付頁(yè)面
    return HttpResponseRedirect(url)


#alipay異步通知

@csrf_exempt
def alipay_notify_url (request):
    if request.method == 'POST':
        if notify_verify (request.POST):
            #商戶(hù)網(wǎng)站訂單號(hào)
            tn = request.POST.get('out_trade_no')
            #支付寶單號(hào)
            trade_no=request.POST.get('trade_no')
            #返回支付狀態(tài)
            trade_status = request.POST.get('trade_status')
            cb = cBill.objects.get(pk=tn)
            
            if trade_status == 'TRADE_SUCCESS':
                cb.exe()
                log=Log(operation='notify1_'+trade_status+'_'+trade_no)
                log.save()
                return HttpResponse("success")
            else:
                #寫(xiě)入日志
                log=Log(operation='notify2_'+trade_status+'_'+trade_no)
                log.save()
                return HttpResponse ("success")
        else:
            #黑客攻擊
            log=Log(operation='hack_notify_'+trade_status+'_'+trade_no+'_'+'out_trade_no')
            log.save()
    return HttpResponse ("fail")

#同步通知

def alipay_return_url (request):
    if notify_verify (request.GET):
        tn = request.GET.get('out_trade_no')
        trade_no = request.GET.get('trade_no')
        trade_status = request.GET.get('trade_status')
          
        cb = cBill.objects.get(pk=tn)
        log=Log(operation='return_'+trade_status+'_'+trade_no)
        log.save()
        return HttpResponseRedirect ("/public/verify/"+tn)
    else:
        #錯(cuò)誤或者黑客攻擊
        log=Log(operation='err_return_'+trade_status+'_'+trade_no)
        log.save()
        return HttpResponseRedirect ("/")


#外部跳轉(zhuǎn)回來(lái)的鏈接session可能丟失搀继,無(wú)法再進(jìn)入系統(tǒng)。
#客戶(hù)可能通過(guò)xxx.com操作翠语,但是支付寶只能返回www.xxx.com叽躯,域名不同,session丟失肌括。
def verify(request,cbid):
    try:
        cb=cBill.objects.get(id=cbid)
        #如果訂單時(shí)間距現(xiàn)在超過(guò)1天点骑,跳轉(zhuǎn)到錯(cuò)誤頁(yè)面酣难!
        #避免網(wǎng)站信息流失
        
        return render_to_response('public_verify.html',{'cb':cb},RequestContext(request))
    except ObjectDoesNotExist:
        return HttpResponseRedirect("/err/no_object")

PS:跟在網(wǎng)上搜到的,主要就是修改了【對(duì)數(shù)組排序并除去數(shù)組中的空值和簽名參數(shù)和返回?cái)?shù)組和鏈接串】方法

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末黑滴,一起剝皮案震驚了整個(gè)濱河市憨募,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌袁辈,老刑警劉巖菜谣,帶你破解...
    沈念sama閱讀 221,635評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異晚缩,居然都是意外死亡尾膊,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)荞彼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)冈敛,“玉大人,你說(shuō)我怎么就攤上這事鸣皂∽デ矗” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,083評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵寞缝,是天一觀(guān)的道長(zhǎng)癌压。 經(jīng)常有香客問(wèn)我,道長(zhǎng)第租,這世上最難降的妖魔是什么措拇? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,640評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮慎宾,結(jié)果婚禮上丐吓,老公的妹妹穿的比我還像新娘。我一直安慰自己趟据,他們只是感情好券犁,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著汹碱,像睡著了一般粘衬。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上咳促,一...
    開(kāi)封第一講書(shū)人閱讀 52,262評(píng)論 1 308
  • 那天稚新,我揣著相機(jī)與錄音,去河邊找鬼跪腹。 笑死褂删,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的冲茸。 我是一名探鬼主播屯阀,決...
    沈念sama閱讀 40,833評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼缅帘,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了难衰?” 一聲冷哼從身側(cè)響起钦无,我...
    開(kāi)封第一講書(shū)人閱讀 39,736評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎盖袭,沒(méi)想到半個(gè)月后失暂,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,280評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡苍凛,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評(píng)論 3 340
  • 正文 我和宋清朗相戀三年趣席,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片醇蝴。...
    茶點(diǎn)故事閱讀 40,503評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖想罕,靈堂內(nèi)的尸體忽然破棺而出悠栓,到底是詐尸還是另有隱情,我是刑警寧澤按价,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布惭适,位于F島的核電站,受9級(jí)特大地震影響楼镐,放射性物質(zhì)發(fā)生泄漏癞志。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評(píng)論 3 333
  • 文/蒙蒙 一框产、第九天 我趴在偏房一處隱蔽的房頂上張望凄杯。 院中可真熱鬧,春花似錦秉宿、人聲如沸戒突。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,340評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)膊存。三九已至,卻和暖如春忱叭,著一層夾襖步出監(jiān)牢的瞬間隔崎,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,460評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工韵丑, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留爵卒,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,909評(píng)論 3 376
  • 正文 我出身青樓埂息,卻偏偏與公主長(zhǎng)得像技潘,于是被迫代替她去往敵國(guó)和親遥巴。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,283評(píng)論 25 707
  • 22年12月更新:個(gè)人網(wǎng)站關(guān)停享幽,如果仍舊對(duì)舊教程有興趣參考 Github 的markdown內(nèi)容[https://...
    tangyefei閱讀 35,188評(píng)論 22 257
  • 支付寶簡(jiǎn)介文檔 (適用于ydm-java接口與后臺(tái)值桩,如有誤入摆霉,但愿也能給您帶來(lái)幫助) 此文檔寫(xiě)于2017年3月,只...
    隔壁付叔叔閱讀 17,082評(píng)論 3 19
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理奔坟,服務(wù)發(fā)現(xiàn)携栋,斷路器,智...
    卡卡羅2017閱讀 134,699評(píng)論 18 139
  • 最近比較懶咳秉,都沒(méi)有在學(xué)30天學(xué)會(huì)繪畫(huà)婉支,不過(guò)每天還是在堅(jiān)持繪畫(huà),每天畫(huà)一點(diǎn)澜建,想來(lái)也是會(huì)進(jìn)步的向挖。 還是納豆老師的簡(jiǎn)筆畫(huà)...
    滴水沁心閱讀 377評(píng)論 2 4