目錄
零之前言
網上雖然有很多的Django接入支付寶付款,但是很少看到有面對面掃碼的支付寶教程,所以整合了一下。
主要使用到的模塊Python-Alipay-SDK的樣例等信息:https://github.com/fzlee/alipay/blob/master/README.zh-hans.md
注意此SDK非官方SDK
一.註冊支付寶開放平臺賬號
因爲這一步我已經註冊過了,所以過程可能不會非常詳細。
1.註冊
這過程可能不會太詳細,如果看我的不明白,還是找一找其他大佬的文章吧QAQ
在支付寶開放平臺的開發者中心控制檯裏註冊“研發服務”(開通沙箱功能),你可以把沙箱理解成一個獨立的支付寶,使用獨立的網關、賬號。我們只需要在這上面調試通後,稍微改改配置,就可以上線了!
2.創建公私祕鑰
下載我們的 "支付寶開放平臺開發助手"https://opensupport.alipay.com/support/knowledge/20069/201602111105?ant_source=zsearch
創建我們的密鑰
然後我們把我們的公鑰複製到我們的沙箱應用裏:
創建好就是這個亞子:
2.項目中添加公私密鑰
我們在項目裏創建一個文件夾吧,且創兩個文本文件來存放我們的密鑰吧,當然它是有格式的
支付寶公鑰/私鑰格式:
-----BEGIN PUBLIC KEY-----
中間放公鑰(剛纔在網頁生成的下面的那個)
-----END PUBLIC KEY-----
-----BEGIN RSA2 PRIVATE KEY-----
這裏放私鑰(剛纔用軟件生成的那個)
-----END RSA2 PRIVATE KEY-----
然後在Django中寫代碼讀入我們的密鑰文件:我是寫在了Django中的settings裏:
APP_PRIVATE_KEY = open(os.path.join(BASE_DIR, 'Alipay/ali_private_key.pem'),'r').read()
APP_PUBLIC_KEY = open(os.path.join(BASE_DIR, 'Alipay/ali_public_key.pem'),'r').read()
然後我的結構就像這樣
當然,創建文件這一步你可以省略,直接讓這兩個值 = 我們的公私鑰文本。看個人習慣吧
二.生成二維碼
1.安裝模塊等
重申這是非官方SDK
安裝模塊:
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple python-alipay-sdk
項目地址:https://github.com/fzlee/alipay
2.模塊的結構
模塊的結構是:
創建一個阿里客戶端實例 -> 調用實例的函數(創建實例的時候基本上已經把我們要配置的東西配置好了)
我們先來看看創建實例的例子吧,作者文檔解釋:
alipay = AliPay(
appid="", #這個是剛纔你創建的時候保存的appid
app_notify_url=None, # 默認回調url
app_private_key_string=app_private_key_string,
# 支付寶的公鑰,驗證支付寶回傳消息使用,不是你自己的公鑰,
alipay_public_key_string=alipay_public_key_string,
sign_type="RSA2" # RSA 或者 RSA2
debug=True # 默認False
)
尤其要說一下我們的debug模式:在Pycharm中選中Alipay,ctrl+alt+b跳轉去看看他的代碼,網上找,找到和debug模式有關的:
if debug is True:
self._gateway = "https://openapi.alipaydev.com/gateway.do"
else:
self._gateway = "https://openapi.alipay.com/gateway.do"
這有兩個網關,這是什麼意思呢?仔細對比支付寶的文檔,我們就可以知道帶dev的是沙箱模式的網關。所以我們Debug==True的時候用的是沙箱模式,我們先調試,等要發佈的時候改成False就行了。注意此處設置錯誤,後面會出現奇怪的錯誤。
3.電腦支付
支付寶開發者文檔:https://docs.open.alipay.com/270/105898/
作者樣例:
# 如果你是Python 2用戶(考慮考慮升級到Python 3吧),請確保非ascii的字符串爲utf8編碼:
subject = u"測試訂單".encode("utf8")
# 如果你是 Python 3的用戶,使用默認的字符串即可
subject = "測試訂單"
# 電腦網站支付,需要跳轉到https://openapi.alipay.com/gateway.do? + order_string
order_string = alipay.api_alipay_trade_page_pay(
out_trade_no="20161112",
total_amount=0.01,
subject=subject,
return_url="https://example.com",
notify_url="https://example.com/notify" # 可選, 不填則使用默認notify url
)
我的代碼:
order_string = alipay.api_alipay_trade_page_pay(
out_trade_no=payid, #交易單號
total_amount=paysum, #共付金額
subject=payname, #項目名稱
return_url="https://baidu.com", #支付成功後默認跳轉的界面
notify_url="http://your_web/app/callback_post/" # 這個用於接收回調的POST信息,具體返回值可在官方API列表查詢
)
return redirect("https://openapi.alipaydev.com/gateway.do?" + order_string) #這是沙箱鏈接
訪問結果:
4.手機支付
手機支付就是彈出一個手機網頁,然後點擊它後自動拉取支付寶應用
支付寶開發者文檔:https://docs.open.alipay.com/60/104790
作者樣例:(參數基本上同電腦支付)
# 手機網站支付,需要跳轉到https://openapi.alipay.com/gateway.do? + order_string
order_string = alipay.api_alipay_trade_wap_pay(
out_trade_no="20161112",
total_amount=0.01,
subject=subject,
return_url="https://example.com",
notify_url="https://example.com/notify" # 可選, 不填則使用默認notify url
)
我的代碼:
order_string = alipay.api_alipay_trade_page_pay(
out_trade_no=payid,
total_amount=paysum,
subject=payname,
return_url="https://example.com",
notify_url="http://your_web/app/callback_post/"
)
return redirect("https://openapi.alipaydev.com/gateway.do?" + order_string)
訪問結果:
如此小節開篇所示。
5.面對面掃碼(真二維碼支付)
支付寶開發者文檔:https://docs.open.alipay.com/194/106078/
作者樣例:
alipay = AliPay(appid="", ...)
# create an order
alipay.api_alipay_trade_precreate (
subject="test subject",
out_trade_no="out_trade_no",
total_amount=100
)
# check order status
paid = False
for i in range(10):
# check every 3s, and 10 times in all
print("now sleep 3s")
time.sleep(3)
result = alipay.api_alipay_trade_query(out_trade_no="out_trade_no")
if result.get("trade_status", "") == "TRADE_SUCCESS":
paid = True
break
print("not paid...")
# order is not paid in 30s , cancel this order
if paid is False:
alipay.api_alipay_trade_cancel(out_trade_no=out_trade_no)
我的代碼:
由於這個模型和前兩個不一樣,它是創建一個請求,然後返回一堆參數,至於用戶是否真的支付了,我們需要再用循環然後使用一個API查詢是否交易成功,我只寫了生成二維碼的代碼:因爲使用了生成二維碼的部分代碼,所以要用到qrcode和image兩個包,而IO包python自帶
先下載包:
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple qrcode
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple image
#注意BytesIO()Pycharm是不能搜到的我們自己導入模塊
#from io import *
data = alipay.api_alipay_trade_precreate(
subject=payname,
# 這個必須確保不同,所以我們需要加一些前綴才行
out_trade_no="face" + payid,
total_amount= int(paysum)
)
if data["code"] == "10000": #這個是API調用成功
img = qrcode.make(data["qr_code"])
buf = BytesIO()
img.save(buf)
image_stream = buf.getvalue()
response = HttpResponse(image_stream, content_type="image/png")
return response
else:
return HttpResponse("<a href=""/app/alipay"">創建失敗,點此返回</a>")
對於代碼裏的data的返回值,我們可以參考官方的API參考文檔:https://docs.open.alipay.com/api_1/alipay.trade.create
對於生成二維碼的代碼,自己百度其意思。
訪問結果:
三.無情開源我的一個小項目代碼
真的很垃圾,別噴我,但是夠看了。
1.urls
說明:通過訪問/app/alipay來進行我們的支付選擇,然後通過/app/pay_post/返回顯示
re_path(r"alipay/", views.alipay, name='alipay'),
re_path(r"pay_post/", views.pay_post, name='pay_post'),
re_path(r"callback_post/", views.repay_post, name='callback_post'),
2.views
def alipay(request):
return render(request, 'creatalipay.html') #返回支付的界面
def pay_post(request):
payid = request.POST.get('payid')
paysum = request.POST.get('paysum')
payname = request.POST.get('payname')
payway = request.POST.get('payway')
alipay = AliPay(
appid="your appid",
app_notify_url=None,
app_private_key_string=APP_PRIVATE_KEY,
alipay_public_key_string=APP_PUBLIC_KEY,
sign_type="RSA2",
debug = True # True就是沙箱環境 False就是正式環境
)
if payway == "phone":
order_string = alipay.api_alipay_trade_wap_pay(
out_trade_no=payid,
total_amount=paysum,
subject=payname,
return_url="https://example.com",
notify_url="http://your web/app/callback_post/"
)
return redirect("https://openapi.alipaydev.com/gateway.do?" + order_string)
elif payway == "pc":
order_string = alipay.api_alipay_trade_page_pay(
out_trade_no=payid,
total_amount=paysum,
subject=payname,
return_url="https://example.com",
notify_url="http://your web/app/callback_post/"
)
return redirect("https://openapi.alipaydev.com/gateway.do?" + order_string)
elif payway == "face":
data = alipay.api_alipay_trade_precreate(
subject=payname,
out_trade_no="face" + payid,
total_amount= int(paysum)
)
if data["code"] == "10000":
img = qrcode.make(data["qr_code"])
buf = BytesIO()
img.save(buf)
image_stream = buf.getvalue()
response = HttpResponse(image_stream, content_type="image/png")
return response
else:
return HttpResponse("<a href=""/app/alipay"">創建失敗,點此返回</a>")
else:
return HttpResponse("<a href=""/app/alipay"">創建失敗,點此返回</a>")
def repay_post(request): #這只是一個簡單的驗證
data = request.POST.get('total_amount')
print("成功支付" + data)
return HttpResponse("1")
3.模板文件
creatalipay.html
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>創建訂單</title>
</head>
<body>
<div style ="text-align: center;">
<form action="{% url 'app:pay_post' %}" method ="post">
<span>訂單號:</span> <input type="text" name ="payid">
<br>
<span>金 額:</span> <input type = "text" name ="paysum">
<br>
<span>項目名:</span> <input type = "text" name ="payname">
<br>
<select name ="payway">
<option value="face">掃碼</option>
<option value="phone" >手機支付</option>
<option value="pc">電腦支付</option>
</select>
<br>
<button>提交</button>
</form>
</div>
</body>
</html>
4.訪問效果
剩下的就和剛纔演示的一模一樣。