支付宝接口集成

1.登陆蚂蚁金服开发者平台,创建沙箱应用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2.生成应用的公钥与私钥

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

3.下载RSA密钥软件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

4.生成密钥

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

注意:python开发者要选择PKCS1(非JAVA适用),然后点击生成应用私钥与公钥

5.设置应用公钥生成支付宝公钥

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

填写完应用公钥后点击查看支付宝公钥,把支付宝公钥记录下来,并用.txt文件保存下来(注意:如果用的是windows中的文本打开要关闭自动换行后再保存,避免添加看不见的回车,导致验证失败)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

6.正式版的应用网关和授权回调地址设置

支付宝app支付应用网关和授权回调地址为非必填

创建应用以后在应用的概览中看到应用网关和授权回调地址

名词解释

**应用网关:**用于接收由支付宝服务器通知。使用接口:生活号接口和口碑门店被动通知

注意:如果您现在开发的接口不是生活号,口碑开店,请勿配置应用网关,如果已经配置可以删除或者不管也不会对您开发的接口有任何影响

**授权回调地址:**顾名思义仅用于授权接口。使用接口第三方应用授权和用户信息授权

注意:如果您现在开发的接口不是第三方应用授权,用户信息授权,请勿配置第三方应用授权链接,如果已经配置放在那里不会对您开发的接口有任何影响

注:不管是授权回调地址还是应用网关都是需要传入http或是https开头的网页地址。

电脑网站,手机网站。app支付,当面付,这些接口都不需要填写应用授权回调地址和应用网关,直接提交应用审核上线即可

特别提醒!!!:只有口碑开店,生活号用到应用网关。只有第三方应用授权和用户信息授权用到授权回调地址

创建Django项目

1.安装需要的库

  • django (本人用的是2.1.1)
  • python-alipay-sdk (本人用的是1.9.1)
  • python版本是 3.7.1
pip install django==2.1.1
pip install python-alipay-sdk==1.9.1

2.文件结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

3.设置settings

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

把创建的app加入到INSTALLED_APPS中,并且允许所有IP访问

设置静态文件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

设置静态文件的路径与允许所有机器进行访问是因为要放到服务器上进行测试

支付宝相关配置

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

支付宝公钥放与应用私钥设置

把保存下来的支付宝公钥与应用私钥放到对应的路径下,并把中文名改成英文的,不要有中文字

并在支付宝公钥与私钥中加入下面的代码

-----BEGIN PRIVATE KEY-----
.....公钥或私钥.....
-----END PRIVATE KEY-----

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

公钥与私钥都要加上

pay/views的配置

from django.shortcuts import render,redirect,HttpResponse
from django.views.decorators.csrf import csrf_exempt
from alipay import AliPay
from django.conf import settings#支付宝支付设置参数的函数
from utils.pay import order_numdef aliPay():#支付宝支付接口obj = AliPay(appid = settings.APPID, # 支付宝申请下来的APPIDapp_notify_url = settings.NOTIFY_URL,   # 如果支付成功过,支付宝会向这个地址发送POST请求(校验是否支付已经成功) 异步支付通知urlalipay_public_key_path = settings.PUB_KEY_PATH, #支付宝公钥app_private_key_path = settings.PRI_KEY_PATH,   # 应用私钥debug = True,   # 默认False,)return objdef index(request):# 如果是地址次进入那么就给index.html的支付页面if request.method == "GET":return render(request,'index.html')# 支付后返回来的是POST方法alipay = aliPay()   #设置支付宝支付的参数# 对购买的数据进行加密money = float(request.POST.get('price'))#这个order_num函数是自定义的生成随机订单号的函数(这里的订单号是非支付宝的订单号,是开发者自己定义的)out_trade_no = order_num(6001)# 创建一条移动端商品订单query_params = alipay.api_alipay_trade_wap_pay(subject="【Python Cookbook】",    # 商品简单描述out_trade_no = out_trade_no,    # 商户订单号total_amount = money,   # 交易金额(单位:元 保留俩位小数))# 创建一条app端商品订单#query_params = alipay.api_alipay_trade_app_pay(#    subject="【Python Cookbook】",    # 商品简单描述#    out_trade_no = out_trade_no,    # 商户订单号#    total_amount = money,   # 交易金额(单位:元 保留俩位小数)#)# 创建一条PC端商品订单#query_params = alipay.api_alipay_trade_page_pay(#    subject="【Python Cookbook】",    # 商品简单描述#    out_trade_no = out_trade_no,    # 商户订单号#    total_amount = money,   # 交易金额(单位:元 保留俩位小数)#)# 电脑网站支付,需要跳转到https://openapi.alipay.com/gateway.do? + order_string# 手机网站支付,需要跳转到https://openapi.alipay.com/gateway.do? + order_string# App支付,将order_string返回给app即可# 这一条是沙箱的重定向urlpay_url = "https://openapi.alipaydev.com/gateway.do?{}".format(query_params)# 重定向到的urlreturn redirect(pay_url)def pay_result(request):"""支付完成后,跳转回的地址   同步支付通知url:param request::return:"""params = request.GET.dict()     #获取传回来的参数sign = params.pop('sign',None)alipay = aliPay()   # 设置支付宝支付参数status = alipay.verify(params,sign)     #支付宝验证 返回来的是False或Trueif status:return HttpResponse('支付成功')return HttpResponse('支付失败')@csrf_exempt
def update_order(request):"""支付成功后,支付宝向该地址发送的POST请求(用于修改订单状态)   异步支付通知url:param request::return:"""if request.method == 'POST':from urllib.parse import parse_qsbody_str = request.body.decode('utf-8')post_data = parse_qs(body_str)  #反序列化将请求参数转回字典参数 --> 返回的是一个字典格式的数据#重构一个新的方便操作的字典post_dict = {}for k,v in post_data.items():post_dict[k] = v[0]alipay = aliPay()sign = post_dict.pop('sign',None)   #验证status = alipay.verify(post_dict,sign)  #返回的是True还是Falseif status:out_trade_no = post_dict.get('out_trade_no')    #获取自定义的订单号return HttpResponse('支付成功')else:return HttpResponse('支付失败')return HttpResponse('')

支付宝会有两个回调通知:同步通知和异步通知。

不同的是:

  • 同步通知会在支付完成后,跳转到回调通知地址页面,并以GET方式传递参数。
  • 异步通知会在支付完成后,向回调通知地址发出POST请求,同时传递参数字典。

不管是同步通知还是异步通知,我们都需要对通知中的签名(sign)进行校验,以确认该通知来自支付宝,保障信息安全。

在支付宝SDK中,为我们提供了验签的函数,我们只需要组织参数进行验签。

因为,两种回调通知的验签参数处理过程都是一样的,只是参数分别来自于GET和POST,所以我们可以只定义1个检查支付结果的函数。

参考官方的验签过程,取出的回调参数后,必须经过以下处理。

  • 参数字典去除签名(sign)和签名类型(sign_type);
  • 剩余参数的字典进行按字母升序排序,形成列表;
  • 将排序后的列表转换为二进制参数字符串。
  • 将支付宝公钥、参数字符串和签名传入验签函数进行验签,验签通过返回值为True,否则会引发异常。
# 上面body_str 的数据分析
{
'buyer_logon_id': ['xxxxxxxx'],     #购买人的支付宝账号
'buyer_id': ['xxxxxxxx'],   #买家的ID
'gmt_payment': ['2019-02-19 13:38:51'],     #付款的时间
'seller_email': ['xxxxxxx'],    #商家的支付宝账号
'notify_id': ['xxxxxx'], #通知id
'invoice_amount': ['10.00'],    #支付的金额
'subject': ['【Python Cookbook】'],   #商品描述
'gmt_create': ['2019-02-19 13:38:50'],  #创建该订单的时间
'version': ['1.0'],     #版本号
'out_trade_no': ['xxxxxxxx'],   #非支付宝生成的订单号,即开发者自定义的订单号
'trade_no': ['2019021922001492560500721286'],   #支付宝的订单号
'app_id': ['xxxxxxxx'],     #APPID
'auth_app_id': ['xxxxxxxx'],    #验证的APPID
'receipt_amount': ['10.00'],    #收到的总额
'total_amount': ['10.00'],      #全部的总额
'point_amount': ['0.00'],       #积分支付的金额,就是减少多少金额
'notify_type': ['trade_status_sync'],   #通知类型
'trade_status': ['TRADE_SUCCESS'],  #交易状态
'buyer_pay_amount': ['10.00'],  #买家支付的总额
'fund_bill_list': ['[{"amount":"10.00","fundChannel":"ALIPAYACCOUNT"}]'],# 资金账单列表 第一个是金额  第二个是资金给的通道 支付宝
'seller_id': ['2088102176750416'],  #商家的ID
'sign_type': ['RSA2'],  #加密类型
'notify_time': ['2019-02-19 13:38:51'], #通知的时间
'charset': ['utf-8'],   #编码类型
'sign': ['xxxxxxxxxxxxxxxxxxxxx']   #验证
}trade_status的含义
WAIT_BUYER_PAY 交易创建,等待买家付款
TRADE_CLOSED    未付款交易超时关闭,或支付完成后全额退款
TRADE_SUCCESS   交易支付成功
TRADE_FINISHED  交易结束,不可退款

pay/urls的配置

from django.contrib import admin
from django.urls import path
from pay import viewsurlpatterns = [path('admin/', admin.site.urls),path('index/',views.index), #第一次进入的网页path('pay_result/',views.pay_result),   #支付完成后,跳转回的地址   异步支付的地址path('update_order/',views.update_order),   #支付成功后,支付宝向该地址发送的POST请求(用于修改订单状态)  同步支付
]

alipay_django中的urls的配置

from django.contrib import admin
from django.urls import path, includeurlpatterns = [path('admin/', admin.site.urls),path('pay/',include('pay.urls'))
]

templates/index的配置

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><title>Title</title><meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body><form method="post">{% csrf_token %}<input type="text" name="price" placeholder="请输入要支付的金额"><input type="submit" value="支付"></form>
</body>
</html>

utils/pay的配置

import time
from random import Random# 生成随机字符串
def random_str(randomlength=8):"""生成随机字符串:param randomlength: 字符串长度:return:"""str = ''chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789'length = len(chars) - 1random = Random()for i in range(randomlength):str += chars[random.randint(0, length)]return strdef order_num(code):"""生成付款订单,60位:param machine_code: 商品编码:return:"""local_time = time.strftime('%Y%m%d%H%M%S', time.localtime(time.time()))result = str(machine_code) + 'T' + local_time + random_str(5)return result

电脑版的对接进行测试

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

注意:要用沙箱的app进行支付,沙箱的支付宝中的账号到蚂蚁金服里查看

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
支付完成,因为没有设置跳转页面,所以没有进行跳转

官方支付宝支付接口

1.安装官方支付宝的库

pip install alipay-sdk-python

如果是windows系统的安装会报下面的错误

  • error: command ‘cl.exe’ failed: No such file or directory
  • error: command ‘C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\BIN\x86_amd64\cl.exe’ failed with exit status 2
  • error: Microsoft Visual C++ 14.0 is required. Get it with “Microsoft Visual C++ Build Tools”: http://landinghub.visualstudio.com/visual-cpp-build-tools

解决办法,安装Visual Studio,安装时把VC++的给装上就可以了,例如我按的是VS2015

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

因为,我们只是下载了安装器,勾选组件之后,安装器会下载相应的组件进行安装,不过即便这样安装过程也非常漫长。

完成安装之后,我们进行环境变量中**用户变量(不是系统变量)**的设置。

变量名称:VCINSTALLDIR

变量值:C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC

如果安装的是其它版本的VS那么找到对应版本VS中的VC文件就可以了

例如我自己电脑的是C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\VC,那么上面的变量值就写C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\VC

接下来,打开cmd,执行如下命令:

set CL=/FI"%VCINSTALLDIR%\\INCLUDE\\stdint.h" %CL%

注意:如果是虚拟环境,请在虚拟环境的命令行中输入此命令

如果还报错误**“src/winrand.c: fatal error C1083: Cannot open include file: ‘%VCINSTALLDIR%\INCLUDE\stdint.h’: No such file or directory”**,可以尝试把命令改为绝对路径。

set CL=/FI"C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\\INCLUDE\\stdint.h" %CL%
#注:FI""里面写的是VC中stdint.h文件的路径

完成上述步骤之后,重新执行安装Pycrypto的命令,就应该不出什么问题了。

注意:建议每次执行上述命令时,先通过“set CL=”命令,将已有设置清空。

继续安装alipay-sdk-python。

pip install alipay-sdk-python

安装过程中会自动安装一些依赖项,如果上面没有安装Pycrypto,此时也会自动进行安装。

如果在项目运行的时候报pycrypto的库错误,可以把库给卸载了

pip uninstall pycrypto

然后再安装一次

pip install pycrypto

再把alipay-sdk-python给卸载了,再安装运行程序就没什么问题了

pip uninstall alipay-sdk-python
pip install alipay-sdk-python

2.设置settings

#支付相关配置
AL_APPID = 'xxxxxxx' #appid# ALIPAY_URL = "https://openapi.alipaydev.com/gateway.do" # 沙箱网关,生产环境须更改为正式网关。
ALIPAY_URL = "https://openapi.alipay.com/gateway.do" # 正式网关,开发环境勿使用。# 如果支付成功,支付宝会向这个地址发送POST请求(校验是否支付已经完成)  异步支付的地址
NOTIFY_URL = "http://xxxxxxxxx/pay/update_order/"
# 如果支付成功,重定向回到的网站的地址。   同步支付的地址
RETURN_URL = "http://xxxxxx/pay/pay_result/"
APP_PRIVATE_KEY = 'xxxxxxx' # 应用私钥
ALIPAY_PUBLIC_KEY = 'xxxxxx' # 支付宝公钥

3.构建支付宝支付的参数类

在pay中新建一个alipay_utils.py

from alipay.aop.api.AlipayClientConfig import AlipayClientConfig  # 客户端配置类
from alipay.aop.api.DefaultAlipayClient import DefaultAlipayClient  # 默认客户端类
from alipay.aop.api.domain.AlipayTradeAppPayModel import AlipayTradeAppPayModel  # app支付模型类
from alipay.aop.api.domain.AlipayTradePagePayModel import AlipayTradePagePayModel  # 网站支付数据模型类
from alipay.aop.api.domain.AlipayTradeWapPayModel import AlipayTradeWapPayModel  # 手机网页支付模型
from alipay.aop.api.util.SignatureUtils import verify_with_rsafrom alipay_django import settings# 设置支付宝支付的参数
class AlPayConfig():def __init__(self):self.alipay_client_config = AlipayClientConfig()  # 创建配置对象self.alipay_client_config.server_url = settings.ALIPAY_URL  # 支付的网关self.alipay_client_config.app_id = settings.AL_APPID  # APPIDself.alipay_client_config.app_private_key = settings.APP_PRIVATE_KEY  # 应用私钥self.alipay_client_config.alipay_public_key = settings.ALIPAY_PUBLIC_KEY  # 支付宝公钥self.client = DefaultAlipayClient(alipay_client_config=self.alipay_client_config)  # 使用配置创建客户端# 创建手机支付model
class AlWapPayModel():def __init__(self, out_trade_no,product_code,quit_url,subject,total_amount,auth_token=None, body=None, business_params=None,disable_pay_channels=None, enable_pay_channels=None,ext_user_info=None, extend_params=None, goods_type=None,invoice_info=None,  passback_params=None,promo_params=None,royalty_info=None, seller_id=None, settle_info=None,specified_channel=None, store_id=None,time_expire=None, timeout_express=None,sub_merchant=None):self.model = AlipayTradeWapPayModel()  # 创建手机网页支付模型self.model.auth_token = auth_token  # 可选参数,string,针对用户授权接口,获取用户相关数据时,用于标识用户授权关系self.model.body = body  # 可选参数,string,对一笔交易的具体描述信息self.model.business_params = business_params  # 可选参数,string,商户传入业务信息,具体值要和支付宝约定,应用于安全,营销等参数直传场景,格式为json格式self.model.disable_pay_channels = disable_pay_channels  # 可选参数,string,禁用渠道,用户不可用指定渠道支付 当有多个渠道时用“,”分隔 注,与enable_pay_channels互斥self.model.enable_pay_channels = enable_pay_channels  # 可选参数,string,可用渠道,用户只能在指定渠道范围内支付 当有多个渠道时用“,”分隔  注,与disable_pay_channels互斥self.model.ext_user_info = ext_user_info  # 可选参数,扩展参数,外部指定买家self.model.extend_params = extend_params  # 可选参数,业务扩展参数self.model.goods_type = goods_type  # 可选参数,string,商品主类型 :0-虚拟类商品,1-实物类商品self.model.invoice_info = invoice_infoself.model.out_trade_no = out_trade_no  # 必选参数,string,商户网站唯一订单,即我们自定义的订单self.model.passback_params = passback_params  # 可选参数,string,公用回传参数,如果请求时传递了该参数,则返回给商户时会回传该参数。支付宝只会在同步返回(包括跳转回商户网站)和异步通知时将该参数原样返回。本参数必须进行UrlEncode之后才可以发送给支付宝。self.model.product_code = product_code  # 必选参数,string,销售产品码,商家和支付宝签约的产品码     QUICK_WAP_WAYself.model.promo_params = promo_params  # 可选参数,string,优惠参数 注:仅与支付宝协商后可用self.model.quit_url = quit_url  # 必选参数,string,用户付款中途退出返回商户网站的地址self.model.royalty_info = royalty_infoself.model.seller_id = seller_idself.model.settle_info = settle_infoself.model.specified_channel = specified_channel  # 可选参数,指定渠道,目前仅支持传入pcredit 若由于用户原因渠道不可用,用户可选择是否用其他渠道支付。 注:该参数不可与花呗分期参数同时传入self.model.store_id = store_id  # 可选参数,string,商户门店编号self.model.sub_merchant = sub_merchantself.model.subject = subject  # 必选参数,string,商品的标题/交易标题/订单标题/订单关键字等self.model.time_expire = time_expire  # 可选参数,string,绝对超时时间,格式为yyyy-MM-dd HH:mm。self.model.timeout_express = timeout_express  # 可选参数,string,该笔订单允许的最晚付款事件,逾期将关闭交易。取值范围:1m-15d。m-分钟,h-小时,d-天,1c-当天(1c-当天的情况下,无论交易何时创建,都在0点关闭)。 该参数数值不接受小数点, 如 1.5h,可转换为 90m。self.model.total_amount = total_amount  # 必选参数,float,订单总金额,单位为元,精确到小数点后两位,取值范围[0.01,100000000]# 创建App支付的model
class AlAppPayModel():def __init__(self,out_trade_no,subject,total_amount, body=None, business_params=None, disable_pay_channels=None, enable_pay_channels=None,ext_user_info=None, extend_params=None, goods_type=None, invoice_info=None,passback_params=None, product_code=None, promo_params=None, royalty_info=None, seller_id=None,settle_info=None, specified_channel=None, store_id=None, sub_merchant=None,time_expire=None, timeout_express=None,  ):self.model = AlipayTradeAppPayModel()  # 创建APP支付模型self.model.body = body  # 可选参数,string,对一笔交易的具体描述信息self.model.business_params = business_params  # 可选参数,string,商户传入业务信息,具体值要和支付宝约定,应用于安全,营销等参数直传场景,格式为json格式self.model.disable_pay_channels = disable_pay_channels  # 可选参数,string,禁用渠道,用户不可用指定渠道支付 当有多个渠道时用“,”分隔 注,与enable_pay_channels互斥self.model.enable_pay_channels = enable_pay_channels  # 可选参数,string,可用渠道,用户只能在指定渠道范围内支付 当有多个渠道时用“,”分隔  注,与disable_pay_channels互斥self.model.ext_user_info = ext_user_info  # 可选参数,扩展参数,外部指定买家self.model.extend_params = extend_params  # 可选参数,业务扩展参数self.model.goods_type = goods_type  # 可选参数,string,商品主类型 :0-虚拟类商品,1-实物类商品self.model.invoice_info = invoice_infoself.model.out_trade_no = out_trade_no  # 必选参数,string,商户网站唯一订单,即我们自定义的订单self.model.passback_params = passback_params  # 可选参数,string,公用回传参数,如果请求时传递了该参数,则返回给商户时会回传该参数。支付宝只会在同步返回(包括跳转回商户网站)和异步通知时将该参数原样返回。本参数必须进行UrlEncode之后才可以发送给支付宝。self.model.product_code = product_code  # 可选参数,string,销售产品码,商家和支付宝签约的产品码  QUICK_MSECURITY_PAYself.model.promo_params = promo_params  # 可选参数,string,优惠参数 注:仅与支付宝协商后可用self.model.royalty_info = royalty_infoself.model.seller_id = seller_idself.model.settle_info = settle_infoself.model.specified_channel = specified_channel  # 可选参数,指定渠道,目前仅支持传入pcredit 若由于用户原因渠道不可用,用户可选择是否用其他渠道支付。 注:该参数不可与花呗分期参数同时传入self.model.store_id = store_id  # 可选参数,string,商户门店编号self.model.sub_merchant = sub_merchantself.model.subject = subject  # 必选参数,string,商品的标题/交易标题/订单标题/订单关键字等self.model.time_expire = time_expire  # 可选参数,string,绝对超时时间,格式为yyyy-MM-dd HH:mm。self.model.timeout_express = timeout_express  # 可选参数,string,该笔订单允许的最晚付款事件,逾期将关闭交易。取值范围:1m-15d。m-分钟,h-小时,d-天,1c-当天(1c-当天的情况下,无论交易何时创建,都在0点关闭)。 该参数数值不接受小数点, 如 1.5h,可转换为 90m。self.model.total_amount = total_amount  # 必选参数,float,订单总金额,单位为元,精确到小数点后两位,取值范围[0.01,100000000]# 创建PC支付宝支付的models
class AlPcPayModel():def __init__(self, out_trade_no,product_code,subject,total_amount,agreement_sign_params=None, body=None, business_params=None, disable_pay_channels=None,enable_pay_channels=None, ext_user_info=None, extend_params=None, goods_detail=None,goods_type=None, integration_type=None, invoice_info=None,passback_params=None,  promo_params=None, qr_pay_mode=None,qrcode_width=None, request_from_url=None, royalty_info=None, settle_info=None,store_id=None, sub_merchant=None,  time_expire=None, timeout_express=None,):self.model = AlipayTradePagePayModel()  # 创建PC网站支付模型self.model.agreement_sign_params = agreement_sign_params  # 可选参数,签约参数,支付后签约场景使用self.model.body = body  # 可选参数,string,对一笔交易的具体描述信息self.model.business_params = business_params  # 可选参数,string,商户传入业务信息,具体值要和支付宝约定,应用于安全,营销等参数直传场景,格式为json格式self.model.disable_pay_channels = disable_pay_channels  # 可选参数,禁用渠道,用户不可用指定渠道支付,多个渠道以逗号分割 注,与enable_pay_channels互斥 渠道列表:https://docs.open.alipay.com/common/wifww7self.model.enable_pay_channels = enable_pay_channels  # 可选参数,可用渠道,用户只能在指定渠道范围内支付,多个渠道以逗号分割 注,与disable_pay_channels互斥 渠道列表:https://docs.open.alipay.com/common/wifww7self.model.ext_user_info = ext_user_info  # 可选参数,外部指定买家self.model.extend_params = extend_params  # 可选参数,业务扩展参数self.model.goods_detail = goods_detail  # 可选参数,拓展参数,订单包含的商品列表信息,json格式,其它说明详见商品明细说明self.model.goods_type = goods_type  # 可选参数,string,商品主类型 :0-虚拟类商品,1-实物类商品self.model.integration_type = integration_type"""可选参数,string,请求后页面的集成方式。 取值范围: 1. ALIAPP:支付宝钱包内 2. PCWEB:PC端访问 默认值为PCWEB。"""self.model.invoice_info = invoice_info  # 可选参数,开票信息self.model.out_trade_no = out_trade_no  # 必选参数,string,商户网站唯一订单,即我们自定义的订单self.model.passback_params = passback_params  # 可选参数,string,公用回传参数,如果请求时传递了该参数,则返回给商户时会回传该参数。支付宝只会在同步返回(包括跳转回商户网站)和异步通知时将该参数原样返回。本参数必须进行UrlEncode之后才可以发送给支付宝。self.model.product_code = product_code  # 必选参数,string,销售产品码,与支付宝签约的产品码名称。 注:目前仅支持FAST_INSTANT_TRADE_PAYself.model.promo_params = promo_params  # 可选参数,string,优惠参数 注:仅与支付宝协商后可用self.model.qr_pay_mode = qr_pay_mode"""可选参数,string,PC扫码支付的方式,支持前置模式和 跳转模式。 前置模式是将二维码前置到商户 的订单确认页的模式。需要商户在 自己的页面中以 iframe 方式请求 支付宝页面。具体分为以下几种: 0:订单码-简约前置模式,对应 iframe 宽度不能小于600px,高度不能小于300px;1:订单码-前置模式,对应iframe 宽度不能小于 300px,高度不能小于600px; 3:订单码-迷你前置模式,对应 iframe 宽度不能小于 75px,高度不能小于75px; 4:订单码-可定义宽度的嵌入式二维码,商户可根据需要设定二维码的大小。 跳转模式下,用户的扫码界面是由支付宝生成的,不在商户的域名下。 2:订单码-跳转模式"""self.model.qrcode_width = qrcode_width  # 可选参数,int,商户自定义二维码宽度 注:qr_pay_mode=4时该参数生效self.model.request_from_url = request_from_url  # 可选参数,string,请求来源地址。如果使用ALIAPP的集成方式,用户中途取消支付会返回该地址。self.model.royalty_info = royalty_info  # 可选参数,描述分账信息,json格式,详见分账参数说明self.model.settle_info = settle_info  # 可选参数,描述结算信息,json格式,详见结算参数说明self.model.store_id = store_id  # 可选参数,string,商户门店编号self.model.sub_merchant = sub_merchant  # 可选参数,间连受理商户信息体,当前只对特殊银行机构特定场景下使用此字段self.model.subject = subject  # 必选参数,string,商品的标题/交易标题/订单标题/订单关键字等self.model.time_expire = time_expire  # 可选参数,string,绝对超时时间,格式为yyyy-MM-dd HH:mm。self.model.timeout_express = timeout_express  # 可选参数,string,该笔订单允许的最晚付款事件,逾期将关闭交易。取值范围:1m-15d。m-分钟,h-小时,d-天,1c-当天(1c-当天的情况下,无论交易何时创建,都在0点关闭)。 该参数数值不接受小数点, 如 1.5h,可转换为 90m。self.model.total_amount = total_amount  # 必选参数,float,订单总金额,单位为元,精确到小数点后两位,取值范围[0.01,100000000]```pythondef check_pay(params):  # 定义检查支付结果的函数sign = params.pop('sign', None)  # 取出签名params.pop('sign_type')  # 取出签名类型params = sorted(params.items(), key=lambda e: e[0], reverse=False)  # 取出字典元素按key的字母升序排序形成列表message = "&".join("{}={}".format(k, v) for k, v in params).encode()  # 将列表转为二进制参数字符串# with open(settings.ALIPAY_PUBLIC_KEY_PATH, 'rb') as public_key: # 打开公钥文件try:#     status =verify_with_rsa(public_key.read().decode(),message,sign) # 验证签名并获取结果status = verify_with_rsa(settings.ALIPAY_PUBLIC_KEY.encode('utf-8').decode('utf-8'), message,sign)  # 验证签名并获取结果return status  # 返回验证结果except:  # 如果验证失败,返回假值。return False

urls的配置与上面的那个方式一样的配置

check_pay函数解释

在支付宝SDK中,为我们提供了验签的函数,我们只需要组织参数进行验签。

因为,两种回调通知的验签参数处理过程都是一样的,只是参数分别来自于GET和POST,所以我们可以只定义1个检查支付结果的函数。

参考官方的验签过程,取出的回调参数后,必须经过以下处理。

  • 参数字典去除签名(sign)和签名类型(sign_type);
  • 剩余参数的字典进行按字母升序排序,形成列表;
  • 将排序后的列表转换为二进制参数字符串。
  • 将支付宝公钥、参数字符串和签名传入验签函数进行验签,验签通过返回值为True,否则会引发异常。

4.pay/views的配置

from django.shortcuts import render, HttpResponse, redirect
from django.views.decorators.csrf import csrf_exempt
from alipay.aop.api.request.AlipayTradePagePayRequest import AlipayTradePagePayRequest  # 网站支付请求类
from alipay.aop.api.request.AlipayTradeWapPayRequest import AlipayTradeWapPayRequest    #手机网页支付请求类
from alipay.aop.api.request.AlipayTradeAppPayRequest import AlipayTradeAppPayRequest    #app支付请求类from alipay_django import settings
from pay.alipay_utils import AlPayConfig, AlWapPayModel, check_pay
from utils.pay import order_numdef index(request):# 如果是地址次进入那么就给index.html的支付页面if request.method == "GET":return render(request,'index.html')if request.method == "POST":# 支付后返回来的是POST方法total_amount = request.POST['price']alipay = AlPayConfig()   #设置支付宝支付的参数out_trade_no = order_num(6001)alwapmodel = AlWapPayModel(out_trade_no,'QUICK_WAP_WAY',"http://xxx/pay/index/",'pythonbook',total_amount) #设置H5支付模型,必填参数   out_trade_no,product_code,quit_url,subject,total_amountwap_pay_request = AlipayTradeWapPayRequest(biz_model=alwapmodel.model)wap_pay_request.notify_url = settings.NOTIFY_URL   #设置异步回调通知方式response = alipay.client.page_execute(wap_pay_request,http_method="GET")return redirect(response)@csrf_exempt
def update_order(request):"""支付成功后,支付宝向该地址发送的POST请求(用于修改订单状态):param request::return:"""if request.method == "GET":params = request.GET.dict() #获取参数字典if check_pay(params):   #调用检查支付结果的函数#业务逻辑在这里编写print("支付成功get")return HttpResponse('支付成功get')else:#业务逻辑在这里编写print('支付失败get')return HttpResponse('支付失败get')if request.method == 'POST':params = request.POST.dict()    #获取参数字典if check_pay(params):#业务逻辑在这里编写print("支付成功post")return HttpResponse('支付成功post')else:#业务逻辑在这里编写print("支付失败post")return HttpResponse("支付失败post")

当我们使用沙箱钱包扫码完成支付,如果设置了回调通知地址,此时支付宝会有两个回调通知:同步通知和异步通知。

不同的是:

  • 同步通知会在支付完成后,跳转到回调通知地址页面,并以GET方式传递参数。
  • 异步通知会在支付完成后,向回调通知地址发出POST请求,同时传递参数字典。

不管是同步通知还是异步通知,我们都需要对通知中的签名(sign)进行校验,以确认该通知来自支付宝,保障信息安全。

同步通知的响应结果,我们需要返回内容到页面。

异步通知的响应结果,我们需要返回内容到支付宝服务器。

这里特别注意,异步通知如果没有向支付宝返回字符串“success”的话,会在一定时间内不停的发起回调请求,直到超出时限或者接收到字符串“success”为止。

支付宝接口使用文档说明 支付宝异步通知(notify_url)与return_url.

现支付宝的通知有两类。
A服务器通知,对应的参数为notify_url,支付宝通知使用POST方式
B页面跳转通知,对应的参数为return_url,支付宝通知使用GET方式 (通知地址不需要像以前一样去账户内设置,而是由客户在支付的时候通过参数传递给我地址。

例如 notify_url=http://www.xxx.com/notify_alipay.asp 注意:www.XXX.com是您网站的域名,也可以用ip地址代替。对于服务器通知,ip地址一定是公网的,私有地址(例如10.2.1.1或者 192.168.1.1)支付宝无法通知到客户端)

以下内容来自支付宝官方网站,不过由于地址改变了,导致原帖无法访问,通过快照查找到其内容,特分享一下.

  1. 确认您使用的接口是用notify_url还是return_url。
  2. notify_url为服务器通知,支付宝可以保证99.9999%的通知到达率,前提是您的网络通畅。
  3. return_url为网页重定向通知,是由客户的浏览器触发的一个通知,若客户去网银支付,也会受银行接口影响,由于各种影响因素特别多,所以该种类型的通知支付宝不保证其到达率。
    买家付款成功后,会跳到 return_url所在的页面,这个页面可以展示给客户看,这个页面只有付款成功才会跳转,并且只跳转一次…
    notify_url: 服务器后台通知,这个页面是支付宝服务器端自动调用这个页面的链接地址,这个页面根据支付宝反馈过来的信息修改网站的定单状态,更新完成后需要返回一个success给支付宝.,不能含有任何其它的字符包括html语言.
    流程:买家付完款(trade_status=WAIT_SELLER_SEND_GOODS)—>支付宝通知 notify_url—>如果反馈给支付宝的是success(表示成功,这个状态下不再反馈,如果不是继续通知,一般第一次发送和第二次发送的时间间隔是3分钟)
    剩下的过程,卖家发货,买家确认收货,交易成功都是这个流程

服务器异步通知页面特性

  • 必须保证服务器异步通知页面(notify_url)上无任何字符,如空格、HTML 标签、开发系统自带抛出的异常提示信息等;
  • 支付宝是用 POST 方式发送通知信息,因此该页面中获取参数的方式,如:request.Form(“out_trade_no”)$_POST[‘out_trade_no’]
  • 支付宝主动发起通知,该方式才会被启用;
  • 只有在支付宝的交易管理中存在该笔交易,且发生了交易状态的改变,支付宝才会通过该方式发起服务器通知(即时到账交易状态为“等待买家付款”的状态默认是不会发送通知的);
  • 服务器间的交互,不像页面跳转同步通知可以在页面上显示出来,这种交互方式是不可见的;
  • 第一次交易状态改变(即时到账中此时交易状态是交易完成)时,不仅会返回同步处理结果,而且服务器异步通知页面也会收到支付宝发来的处理结果通知;
  • 程序执行完后必须打印输出“success”(不包含引号)。如果商户反馈给支付宝的字符不是 success 这7个字符,支付宝服务器会不断重发通知,直到超过24小时22分钟。一般情况下,25小时以内完成8次通知(通知的间隔频率一般是:4m,10m,10m,1h,2h,6h,15h);
  • 程序执行完成后,该页面不能执行页面跳转。如果执行页面跳转,支付宝会收不到 success 字符,会被支付宝服务器判定为该页面程序运行出现异常,而重发处理结果通知;
  • cookies、session 等在此页面会失效,即无法获取这些数据;
  • 该方式的调试与运行必须在服务器上,即互联网上能访问;
  • 该方式的作用主要防止订单丢失,即页面跳转同步通知没有处理订单更新,它则去处理;
  • 当商户收到服务器异步通知并打印出 success 时,服务器异步通知参数 notify_id 才会失效。也就是说在支付宝发送同一条异步通知时(包含商户并未成功打印出 success 导致支付宝重发数次通知),服务器异步通知参数 notify_id 是不变的。

python接入支付宝相关推荐

  1. python接入支付宝接口

    安装包 # 安装python-alipay-sdk# --upgrade 是你之前安装了pycrypto, 加它是升级, 一次都没安装的用户, 直接pip install python-alipay- ...

  2. 个人如何用python支付宝收款_python怎么接入支付宝

    Python接入支付宝流程: 第一步: 首先要下载一个python的sdk,这个sdk在支付宝的开发者文档中是没有的,但是强大的python程序员自己开发了一套属于python的支付宝支付sdk. 下 ...

  3. python接入微信支付_特斯拉中国官网首次接入支付宝 暂未开通微信支付

    前不久,特斯拉CEO埃隆·马斯克(Elon Musk)宣布,未来将关闭世界各地的零售店,所有的特斯拉汽车都将转向线上渠道独家销售,大幅降低销售和营销开支,以保证3.5万美元Model 3的顺利量产. ...

  4. 「轻松支付,只需几步」使用 LeanCloud 云代码接入支付宝示例

    如果你的应用想接入支付宝,让用户可以在应用内部直接支付,你可以看下这篇文档和开源项目,也许会给你带来一些帮助. 项目:https://github.com/leancloud/cloud-code-a ...

  5. H5网站接入支付宝的支付接口

    写本文章的目的是为了记录工作中遇到的问题,方便以后遇到可以迅速解决问题 H5手机网站接入支付宝的支付接口,推荐使用支付宝提供的SDK来快速开发 我使用的是SDK开发 引用命名空间 using Aop. ...

  6. 网站如何接入支付宝(转)

    本文介绍了网站如何接入支付宝. 1 注册企业支付宝帐号 https://enterpriseportal.alipay.com/login.htm 2 实名认证 提供公司相关证件进行实名认证,提交后, ...

  7. Android 接入支付宝支付实现

    接上篇android接入微信支付文章,这篇我们带你来接入支付宝支付服务 简介 首先要说明的是个人感觉接入支付宝比微信简单多了,很轻松的,所以同学们不要紧张~ 当然还是老规矩啦,上来肯定的贴上官网地址, ...

  8. php 支付宝订单查询_5. PHP接入支付宝单笔订单查询接口

    巴西奥运会来了,刚好我又是做体育行业的互联网.哎!这个月又要加班成狗了.最近遇到好多莫名其妙的问题,待我忙完这段,再跟大家分享下.今天还是继续说说 Payment项目 今天主要说说支付宝订单查询接口. ...

  9. Android接入支付宝支付实现

    接上篇android接入微信支付文章,这篇我们带你来接入支付宝支付服务 简介 首先要说明的是个人感觉接入支付宝比微信简单多了,很轻松的,所以同学们不要紧张~ 当然还是老规矩啦,上来肯定的贴上官网地址, ...

最新文章

  1. PHP上传文件函数move_upload,如何使用php中move_uploaded_file函数
  2. 如何通过BIPlatform完成多维报表以及图形配置
  3. LeakCanary上传 leak trace 到服务器
  4. python调用arcpy函数_python笔记之ArcPy函数列表
  5. 计算机应用基础是文管二级吗,计算机应用基础(文管二级)习题册.doc
  6. python正则表达式操作指南_比较详细Python正则表达式操作指南(re使用)
  7. Java基础学习总结(136)——有关流资源关闭(try-with-resources与AutoCloseable)的使用总结
  8. Oracle 常用符号CHR
  9. 【图神经网络】向往的GAT(图注意力模型)
  10. 程序猿 C语言入门 颈椎,【计时器小工具】70行代码让你远离颈椎病,致所有的程序猿们...
  11. python三角函数公式计算_使用Python三角函数公式计算三角形的夹角案例
  12. 面试被问“红黑树”,我一脸懵逼......
  13. php多合一安装包,DOXCX多合一小程序系统Sass平台源码分享
  14. 大数据概论、大数据概念、大数据特点(4V)、Volume(大量)、Velocity(高速)、Variety(多样)、Value(低价值密度)、大数据应用场景、大数据发展前景、大数据部门间业务流程分析
  15. 魔力 java下载安装,UBNT EdgeMAX EdgeRouter ERPoE-5 POE+ UAP-AC-PRO开箱及安装调试
  16. 微信小程序如何解析标签?
  17. 海关外贸企业大数据风控平台产品应用
  18. 【光线追踪系列九】物体动态模糊
  19. 关于耳机的IEC711是什么(频响)
  20. 神策杯 2018高校算法大师赛(个人、top2、top6)方案总结

热门文章

  1. Centos7 编译 php5.6出错
  2. CentOS 7下的软件安装方法及策略
  3. IEEE754浮点数
  4. Facebook中国程序员之死:年仅38岁跳楼轻生,浙大EE毕业生,去年刚入职
  5. 视频聊天开发包的介绍
  6. Excel中如何让第一行、第二行一直显示出来 excel冻结窗格与拆分窗格
  7. MIS和MES的区别
  8. 【java算法】排序算法大合集
  9. 【网络】Padavan固件获取运营商ipv6设置
  10. 2D-X光图像重建3D-CT图像项目总结—后续补充