激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

腳本之家,腳本語言編程技術及教程分享平臺!
分類導航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務器之家 - 腳本之家 - Python - python采用django框架實現支付寶即時到帳接口

python采用django框架實現支付寶即時到帳接口

2020-08-23 12:12hornbills Python

這篇文章主要介紹了python采用django框架實現支付寶即時到帳接口的相關資料,需要的朋友可以參考下

因工作需要研究了支付寶即時到帳接口,并成功應用到網站上,把過程拿出來分享。

即時到帳只是支付寶眾多商家服務中的一個,表示客戶付款,客戶用支付寶付款,支付寶收到款項后,馬上通知你,并且此筆款項與交易脫離關系,商家可以馬上使用。

即時到帳只對企業客戶服務,注冊成功企業賬號以后,申請簽約即時到帳產品,大約3-5個工作日后,簽約成功,可以馬上進入集成產品階段。

這個是支付寶提供的接口,有asp,c#,java,php四種語言的,每種語言提供GBK和UTF-8兩種方案。另帶一份支付寶的文檔,這份文檔我感覺本來簡單的事情越說越麻煩了。

網上搜了一下,發現Python接口有幾個現成的方案。
https://github.com/fengli/alipay_python

這兩個是一個,代碼我還沒看,寫文檔的時候發現的。
https://github.com/lxneng/alipay
https://pypi.python.org/pypi/alipay/0.2.2

支付寶即時到帳交易過程。

商家:是指支付寶的企業客戶。也就是你集成服務單位。
終端消費者:是指在網上購物的消費者,你集成服務單位的客戶。

1、終端消費者在商家網站選擇商品,下訂單。
2、商家把支付信息,get到支付寶指定的鏈接。
3、終端消費者在支付寶的網站上操作付款。
4、付款成功后,支付寶post付款成功的信息到商家預先提供的地址。
5、支付寶在終端消費者付款成功后三秒后,通過get跳回商家指定的鏈接。

第4步跟終端消費者操作付款的跳轉無關,所以被稱為異步通知。這一步,支付寶期待你返回'success',如果你不返回'success',支付寶會于4分鐘后再次post付款成功的信息,此后每10分鐘post一次,至少30分鐘內如此。如果終端消費者付款失敗,異步通知不會發生。

通過集成,我知道為什么終端消費者付款成功后要等3秒后跳轉回商家頁面了,因為它要等異步通知的信息先到達,先處理訂單,再帶終端消費者回到客戶的界面,這樣就可以看到支付成功的頁面了。當然付款失敗,異步通知不發生,訂單狀態沒有改變,終端消費者就只能看到付款失敗的信息。

了解了支付過程,開始設計程序。
1、生成商品訂單。終端消費者選擇商品生成商品訂單。ID號要唯一,這個唯一不是要你采用UUID,而是跟支付寶往來過程唯一即可,從1遞增也可以,只是終端消費者能看到這個id,所以最好采用固定長度的字符串,終端消費者如果知道自己是第一個客戶,會不會心里發怵?后面會談到,為了安全不僅不能用遞增,而且至少要6位隨機碼以上。
2、選擇支付方式。因為我們僅僅集成了即時到帳,所以只有支付寶付款一個選項。把支付方式加入訂單信息,同時把訂單id post到下一步地址,這一步post,最好采用新開頁面,本頁面彈出對話框,讓客戶自己選擇支付成功或者支付失敗。
3、發送支付信息。根據post過來的訂單號組合信息,get方式發送數據給支付寶,同時帶動終端消費者頁面跳轉到支付寶支付頁面。
4、接受異步通知。
5、支付成功后支付寶跳轉回來的程序。因為回來時get方式,為避免終端消費者看到更多敏感信息,這一步并沒有渲染頁面,而是處理信息,跳轉到另外一個頁面。
6、顯示支付結果。這個頁面和第2步讓客戶點擊支付成功跳轉的是同一個。支付失敗,就跳轉到一個說明吧。

alipay.py

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import types
from urllib import urlencode, urlopen
from hashcompat import md5_constructor as md5<span style="white-space:pre">  </span>#見hashcompact.py
from config import settings<span style="white-space:pre">     </span>#見config.py
 
#字符串編解碼處理
def smart_str(s, encoding='utf-8', strings_only=False, errors='strict'):
  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):
        return ' '.join([smart_str(arg, encoding, strings_only,
            errors) for arg in s])
      return unicode(s).encode(encoding, errors)
  elif isinstance(s, unicode):
    return s.encode(encoding, errors)
  elif s and encoding != 'utf-8':
    return s.decode('utf-8', errors).encode(encoding, errors)
  else:
    return s
 
# 網關地址
_GATEWAY = 'https://mapi.alipay.com/gateway.do?'
 
 
# 對數組排序并除去數組中的空值和簽名參數
# 返回數組和鏈接串
def params_filter(params):
  ks = params.keys()
  ks.sort()
  newparams = {}
  prestr = ''
  for k in ks:
    v = params[k]
    k = smart_str(k, settings.ALIPAY_INPUT_CHARSET)
    if k not in ('sign','sign_type') and v != '':
      newparams[k] = smart_str(v, settings.ALIPAY_INPUT_CHARSET)
      prestr += '%s=%s&' % (k, newparams[k])
  prestr = prestr[:-1]
  return newparams, prestr
 
 
# 生成簽名結果
def build_mysign(prestr, key, sign_type = 'MD5'):
  if sign_type == 'MD5':
    return md5(prestr + key).hexdigest()
  return ''
 
 
# 即時到賬交易接口
def create_direct_pay_by_user(tn, subject, body, bank, total_fee):
  params = {}
  params['service']    = 'create_direct_pay_by_user'
  params['payment_type'] = '1'    #商品購買,只能選這個
   
  # 獲取配置文件
  params['partner']      = settings.ALIPAY_PARTNER
  params['seller_id']     = 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
   
  # 從訂單數據中動態獲取到的必填參數
  params['out_trade_no'] = tn    # 請與貴網站訂單系統中的唯一訂單號匹配
  params['subject']    = subject  # 訂單名稱,顯示在支付寶收銀臺里的“商品名稱”里,顯示在支付寶的交易管理的“商品名稱”的列表里。
  params['body']     = body   # 訂單描述、訂單詳細、訂單備注,顯示在支付寶收銀臺里的“商品描述”里,可以為空
  params['total_fee']   = total_fee # 訂單總金額,顯示在支付寶收銀臺里的“應付總額”里,精確到小數點后兩位
   
  # 擴展功能參數——網銀提前
  if bank=='alipay' or bank=='':
    params['paymethod'] = 'directPay'  # 支付方式,四個值可選:bankPay(網銀); cartoon(卡通); directPay(余額); CASH(網點支付)
    params['defaultbank'] = ''     # 支付寶支付,這個為空
  else:
    params['paymethod'] = 'bankPay'   # 默認支付方式,四個值可選:bankPay(網銀); cartoon(卡通); directPay(余額); CASH(網點支付)
    params['defaultbank'] = bank    # 默認網銀代號,代號列表見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):
  # 初級驗證--簽名
  _,prestr = params_filter(post)
  mysign = build_mysign(prestr, settings.ALIPAY_KEY, settings.ALIPAY_SIGN_TYPE)
 
  if mysign != post.get('sign'):
    return False
   
  # 二級驗證--查詢支付寶服務器此條信息是否有效
  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

hashcompact.py

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
"""
The md5 and sha modules are deprecated since Python 2.5, replaced by the
hashlib module containing both hash algorithms. Here, we provide a common
interface to the md5 and sha constructors, preferring the hashlib module when
available.
"""
 
try:
  import hashlib
  md5_constructor = hashlib.md5
  md5_hmac = md5_constructor
  sha_constructor = hashlib.sha1
  sha_hmac = sha_constructor
except ImportError:
  import md5
  md5_constructor = md5.new
  md5_hmac = md5
  import sha
  sha_constructor = sha.new
  sha_hmac = sha

config.py

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#-*- coding:utf-8 -*-
 
class settings:
 # 安全檢驗碼,以數字和字母組成的32位字符
 ALIPAY_KEY = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
 
 ALIPAY_INPUT_CHARSET = 'utf-8'
 
 # 合作身份者ID,以2088開頭的16位純數字
 ALIPAY_PARTNER = 'xxxxxxxxxxxxxxxx'
 
 # 簽約支付寶賬號或賣家支付寶帳戶
 ALIPAY_SELLER_EMAIL = 'ls@abc.com'
 
 ALIPAY_SIGN_TYPE = 'MD5'
 
 # 付完款后跳轉的頁面(同步通知) 要用 http://格式的完整路徑,不允許加?id=123這類自定義參數
 ALIPAY_RETURN_URL='http://www.xxx.com/alipay/return/'
 
 # 交易過程中服務器異步通知的頁面 要用 http://格式的完整路徑,不允許加?id=123這類自定義參數
 ALIPAY_NOTIFY_URL='http://www.xxx.com/alipay/notify/'

view.py

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#確認支付
def pay(request):
  cbid=request.POST.get('id')
  try:
    cb=cBill.objects.get(id=cbid)
  except ObjectDoesNotExist:
    return HttpResponseRedirect("/err/no_object")
   
  #如果網關是支付寶
  if cb.cbank.gateway=='alipay':
      tn=cb.id
      subject=''
      body=''
      bank=cb.cbank.id
      tf='%.2f' % cb.amount
      url=create_direct_pay_by_user (tn,subject,body,bank,tf)
 
  #如果網關是財付通
  elif cb.cbank.gateway=='tenpay':
    pass
   
  #去支付頁面
  return HttpResponseRedirect (url)
 
#alipay異步通知
 
@csrf_exempt
def alipay_notify_url (request):
  if request.method == 'POST':
    if notify_verify (request.POST):
      #商戶網站訂單號
      tn = request.POST.get('out_trade_no')
      #支付寶單號
      trade_no=request.POST.get('trade_no')
      #返回支付狀態
      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:
        #寫入日志
        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:
    #錯誤或者黑客攻擊
    log=Log(operation='err_return_'+trade_status+'_'+trade_no)
    log.save()
    return HttpResponseRedirect ("/")
 
 
#外部跳轉回來的鏈接session可能丟失,無法再進入系統。
#客戶可能通過xxx.com操作,但是支付寶只能返回www.xxx.com,域名不同,session丟失。
def verify(request,cbid):
  try:
    cb=cBill.objects.get(id=cbid)
    #如果訂單時間距現在超過1天,跳轉到錯誤頁面!
    #避免網站信息流失
     
    return render_to_response('public_verify.html',{'cb':cb},RequestContext(request))
  except ObjectDoesNotExist:
    return HttpResponseRedirect("/err/no_object")

view.py中的代碼僅供參考!

以上就是本文的全部內容,希望對大家的學習有所幫助。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 在线播放免费av | 91丝袜| 国产91久久久久久 | 亚州综合一区 | 国产精品久久久久久婷婷天堂 | 亚洲影视在线观看 | hd日本xxxx| 一区二区三区精品国产 | 亚洲成人黄色片 | 久久精品一区二区三区不卡牛牛 | a免费毛片 | 国产青草视频在线观看视频 | 久久久三级免费电影 | 99seav| 亚洲精品欧美二区三区中文字幕 | 日韩精品久久久久久久九岛 | 成人在线视频精品 | 成人区一区二区三区 | 成人黄色免费视频 | 最新se94se在线欧美 | 成人午夜免费网站 | 久久草在线视频免费 | 国产羞羞网站 | 欧美一级黑人 | 九九热在线视频观看这里只有精品 | av手机免费在线观看 | 黄色免费网站在线观看 | 日产精品久久久久久久 | 国产精选电影免费在线观看 | 一级做a爱片久久毛片a高清 | 欧美视频在线观看一区 | 久久综合一区二区 | 久色成人网| 91在线色视频| 久久国产成人精品国产成人亚洲 | 国产一区二区三区四区五区精品 | 成人啪啪18免费网站 | 视频一区二区在线观看 | 国产精品午夜在线 | 羞羞的小视频 | 国产亚洲精久久久久久蜜臀 |