最新版支付宝算法的改变就是RSA升级了RSA2,长度推荐2048,其他的逻辑变化不大,关于秘钥的生成在之前的一篇文章已经有所介绍

  在Mac的系统下生成新版支付宝(2019年4月)支付接口私钥和公钥

  在Django的中集成支付接口的前置操作就是需要安装pycryptodome

  pip3 install -i https://pypi.douban.com/simple pycryptodome

  然后将之前生成好的私钥和公钥(注意这里的公钥是指支付宝公钥),放入到项目目录中去

文档地址:https//docs.open.alipay.com/api

  然后根据支付宝官网文档写一个支付基类pay.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
109
110
111
112
从日期时间进口日期时间
从加密。PublicKey 从Crypto 导入RSA
。签名从Crypto 导入PKCS1_v1_5
。哈希从urllib 导入SHA256
。从urllib 解析import quote_plus
。解析import urlparse ,parse_qs
来自base64 import decodebytes ,encodebytes
import json

类AliPay (对象):“”“

支付宝支付接口(PC端支付接口)
“””

def __init__selfappidapp_notify_urlapp_private_key_path
alipay_public_key_path ,return_url ,debug = False ):
self 。appid = appid
自我。app_notify_url = app_notify_url
自我。app_private_key_path = app_private_key_path
自我。app_private_key = 无
自我。return_url = return_url
与打开(自我。app_private_key_path )作为FP :
自我。app_private_key = RSA 。importKey (fp 。读())
自我。alipay_public_key_path = alipay_public_key_path
与开放(自我。alipay_public_key_path )作为fp :
self 。alipay_public_key = RSA 。importKey (fp 。读())

如果debug 为True
self 。__gateway = “https://openapi.alipaydev.com/gateway.do” 否则:
自我。__gateway = “https://openapi.alipay.com/gateway.do”


def direct_pay (self ,subject ,out_trade_no ,total_amount ,return_url = None ,** kwargs ):
biz_content = { “subject” :subject ,“out_trade_no” :out_trade_no ,“total_amount” :total_amount ,“product_code” :“FAST_INSTANT_TRADE_PAY” ,# “qr_pay_mode”:4 }







biz_content 。更新(kwargs )
data = self 。build_body (“alipay.trade.page.pay” ,biz_content ,自我。return_url )回归自我。sign_data (数据)


def build_body (self ,method ,biz_content ,return_url = None ):
data = { “app_id” :self 。appid ,“method” :方法,“charset” :“utf-8” ,“sign_type” :“RSA2” ,“timestamp” :datetime 。现在()。strftime (“%Y-%m-%d%H:%M:%S” ),“版本” :






“biz_content” :biz_content
}

如果return_url 是不无:
数据[ “notify_url” ] = 自我。app_notify_url
data [ “return_url” ] = self 。return_url

返回数据

def sign_dataselfdata ):
datapop (“sign” ,None )#排序后的字符串
unsigned_items = self 。ordered_data (data )
unsigned_string = “&” 。加入(“{0} = {1}” 。格式(ķ ,v )为ķ ,v 在unsigned_items )
标志= 自我。
符号(unsigned_string 。编码(“UTF-8” ))#ordered_items = self.ordered_data(数据)
quoted_string = “&” 。加入(“{0} = {1}” 。格式(ķ ,quote_plus (v ))为ķ ,v 在unsigned_items )


#获得最终的订单信息字符串
signed_string = quoted_string + “&sign =” + quote_plus (sign )return signed_string


DEF ordered_data (自,数据):
complex_keys = [] 为键,值在数据。items ():if isinstance (value ,dict ):
complex_keys 。追加(关键)



#将字典类型的数据转储出来用于键在complex_keys :
数据[ 键] = JSON 。转储(data [ key ],separators =(','':' ))


返回排序([(ķ ,v )为ķ ,v 在数据。项()])

def signselfunsigned_string ):#开始计算签名
key = self 。app_private_key

签名者= PKCS1_v1_5 。新(关键)
签名= 签名者。符号(SHA256 。新(unsigned_string ))#BASE64编码,转换为Unicode的表示并移除回车
登录= encodebytes (签名)。解码(“utf8” )。替换(“n” ,“” )返回标志



def _verifyselfraw_contentsignature ):#开始计算签名
key = self 。alipay_public_key

签名者= PKCS1_v1_5 。新(关键)
摘要= SHA256 。new ()
摘要。更新(raw_content 。编码(“UTF-8” ))如果签名者。验证(消化,decodebytes (签名。编码(“UTF-8” ))):返回真正的回报假




DEF 验证(自,数据,签名:)如果“sign_type” 在数据:
sign_type = 数据。pop (“sign_type” )#排序后的字符串
unsigned_items = self 。ordered_data (data )
message = “&” 。加入(u “{} = {}” 。格式(k ,v )为k ,

v in unsigned_items )返回self 。_verify (消息,签名)

​ 最后在视图文件中定义方法就可以了

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
#导入支付基类来自。支付宝进口支付宝


#initialgeneration化阿里支付对象def get_ali_object ():#沙箱环境地址:https://openhome.alipay.com/platform/appDaily.htm?tab = info
app_id = “2016092600603658”#APPID (沙箱应用)



#支付完成后,支付偷偷向这里地址发送一个帖子请求,识别公网IP,如果是192.168.20.13局域网IP,支付宝找不到,def page2()接收不到这个请求
notify_url = “http:// localhost :8000 / md_admin / alipayreturn”

#支付完成后,跳转的地址
return_url = “HTTP://本地主机:8000 / md_admin / alipayreturn”

merchant_private_key_path = “c:/Users/liuyue/www/md/keys/app_private_2048.txt” #应用私是
号码alipay_public_key_path = “c:/Users/liuyue/www/md/keys/alipay_public_2048.txt” #support宝公司

支付宝= 支付宝(
appid = app_id ,
app_notify_url = notify_url ,
return_url = return_url ,
app_private_key_path = merchant_private_key_path ,
alipay_public_key_path = alipay_public_key_path ,#支付宝的公司,验证支付宝回传消息使用,不是你自己的公子
调试= True ,#默认虚假,)返回支付宝





def page1 (请求):

如果要求。method == “POST” :

#根据当前用户的配置,生成URL,并跳转。
钱= 浮动(请求。POST ,得到('钱' ))

支付宝= get_ali_object ()

#生成支付的url
query_params = 支付宝。direct_pay (
主题= “测试” ,#商品简单描述
out_trade_no = “myorder” + STR (时间。时间()), #用户购买的商品订单号(每次不一样)20180301073422891
TOTAL_AMOUNT = 钱,#交易金额(单位:元保留俩位小数))


pay_url = “https://openapi.alipaydev.com/gateway.do?{0}” 。格式(query_params )#支付宝网关地址(沙箱应用)

return redirect (pay_url )elsereturn render (request ,'md_admin / page1.html'




DEF alipay_return (请求):
宝= get_ali_object ()
PARAMS = 请求。GET 。dict ()
sign = params 。pop ('sign'None
status = 支付宝。验证(params ,sign )print'==================开始=================='print'GET验证' ,状态)


print'==================结束==================' )返回HttpResponse ('支付成功'