最新版支付宝算法的改变就是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__ (self ,appid ,app_notify_url ,app_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_data (self ,data ): data 。pop (“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 sign (self ,unsigned_string ):#开始计算签名 key = self 。app_private_key 签名者= PKCS1_v1_5 。新(关键) 签名= 签名者。符号(SHA256 。新(unsigned_string ))#BASE64编码,转换为Unicode的表示并移除回车 登录= encodebytes (签名)。解码(“utf8” )。替换(“n” ,“” )返回标志
def _verify (self ,raw_content ,signature ):#开始计算签名 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”
支付宝= 支付宝( 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 )else :return 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 ('支付成功' )
|
Author:
Wenng
Slogan:
Do you believe in DESTINY?