DRF实操——支付宝的介绍与对接支付宝
- 1. 支付宝的介绍
- 实际上线环境:
- 开发环境:
- 2. DRF对接支付宝
- 1. 创建配置文件
- 2. 在setting文件中,做支付宝配置
- 3. 安装支付宝第三方库
- 4. 在setting文件中实例化支付宝对象
- 5.创建模型,保存订单的支付交易号
1. 支付宝的介绍
实际上线环境:
- 在浏览器搜索“支付宝开放平台”,扫码登录。
2. 进入控制台
3. 网页移动应用——创建网页移动应用
4. 填写信息,会生成这个应用的appid,会绑定真实的账户,进行对接。
开发环境:
我们在开发过程中使用的是沙箱环境,进行调试和开发。
应用appid,商家信息,用户信息,都是模拟的
-
在控制台中找到“沙箱”
-
沙箱中有一个appid,上线之后,直接改成在实际生成的ID即可
-
沙箱应用——开发信息——接口加签方式——自定义秘钥——公钥模式,点击启用——支付宝秘钥生成器——秘钥工具下载
-
打开下载的秘钥工具,点击生成秘钥
5. 新建两个记事本txt文件,分别保存生成的应用公钥和应用私钥
- 将应用公钥填写到加签管理这个页面(即第3步的页面),点击保存显示加签完成,这时候会生成一个支付宝公钥。
2. DRF对接支付宝
1. 创建配置文件
这里要用公钥进行加密,用私钥进行解密。配置错误会导致无法核销。
- 在config文件夹下创建一个名为alipay_key的文件夹
- 在该文件夹下创建一个alipay_public的文件用来存放支付宝公钥。开头要加上
-----BEGIN PUBLKIKC KEY-----
,结尾要加上-----END PUBLKIKC KEY-----
- 再创建一个app_private_key的文件用来存放应用私钥。开头要加上
-----BEGIN RSA PRIVATE KEY-----
,结尾要加上-----END RSA PRIVATE KEY-----
- 创建一个appid的文件,将沙箱环境中的appid复制过来
2. 在setting文件中,做支付宝配置
#支付宝配置
APPID = open(f'{BASE_DIR}/config/alipay_key/appid').read()
APP_PRIVATE_KEY_STRING = open(f'{BASE_DIR}/config/alipay_key/app_private_key').read()
ALIPAY_PUBLIC_KEY_STRING = open(f'{BASE_DIR}/config/alipay_key/alipay_public').read()
3. 安装支付宝第三方库
pip install python-alipay-sdk -i https://pypi.douban.com/simple
4. 在setting文件中实例化支付宝对象
# 实例化支付宝对象
alipay = AliPay(appid=APPID,app_notify_url =None,app_private_key_string=APP_PRIVATE_KEY_STRING,alipay_public_key_string=ALIPAY_PUBLIC_KEY_STRING,sign_type='RSA2',# 如果是沙箱环境,要将debug设置为Truedebug=True
)
5.创建模型,保存订单的支付交易号
- 创建一个支付信息模型
class Payment(DateTimeModelMixin):trade_id = models.CharField(max_length=100,unique=True,verbose_name='支付宝交易号')order = models.ForeignKey(Order,on_delete=models.CASCADE,verbose_name='订单')class Meta:ordering=['-create_time']db_table = 'payment'verbose_name = '支付信息'verbose_name_plural = verbose_name
- 创建序列化器
class PaymentSerializer(ModelSerializer):class Meta:model = Paymentfields = '__all__'
- 创建视图,并实现支付接口。
路由记得自己配置。
class OrderCartViewSet(ReadOnlyModelViewSet,CreateModelMixin):serializer_class = OrderCartSerializerpermission_classes = [IsAuthenticated]# 返回当前登录用户的数据def get_queryset(self):# 使用管理器:源模型类小写_setreturn self.request.user.order_set.all()@action(methods=['put'],detail=False)def status(self,request):"""支付成功后将订单状态从待支付改为待发货"""# 得到支付宝回调过来的数据,在请求地址里卖弄query_dict = request.query_params #得到地址栏的参数 比如:https://www.baidu.com?sign=xxxdata = query_dict.dict()# 不能无脑直接修改订单状态,核实身份try:#类似于token# pop 方法会从字典中删除指定的键(在这里是 'sign')# 如果键存在,它会返回该键的值;如果键不存在,则会引发 KeyErrorsign = data.pop('sign') #删除data里面的signexcept KeyError:return Response(status=HTTP_400_BAD_REQUEST)# 验证sign。data的其他数据加密后会得到sign,这里把data传入alipay进行加密在跟sign进行比对校验res = alipay.verify(data,sign)if not res:return Response(status=HTTP_403_FORBIDDEN)#得到订单编号,支付宝交易号order_id = data.get('out_trade_no') #订单编号 out_trade_no固定参数trade_no = data.get('trade_no' ) #支付宝交易号 trade_no固定参数# 保存支付信息,修改订单状态# 这两个动作要一起完成,所以加入事务with transaction.atomic():save_point = transaction.savepoint()try:Payment.objects.create(order_id=order_id,trade_id=trade_no)Order.objects.filter(order_id=order_id,status=1).update(status=2)except Exception as e:transaction.savepoint_rollback(save_point)raise serializers.ValidationError(e)else:transaction.savepoint_commit(save_point)return Response({'order_id':order_id,'trade_id':trade_no})class PaymentViewSet(ReadOnlyModelViewSet):queryset = Payment.objects.all()serializer_class = PaymentSerializerpermission_classes = [IsAuthenticated]@action(methods=['get'],detail=True)def pay(self,request,pk):"""返回支付页面"""#获取订单信息,必须是当前登录的用户的订单,并且是没有支付的try:order = Order.objects.get(order_id=pk,user=request.user,status=1)except Order.DoesNotExist:return Response(status=HTTP_404_NOT_FOUND)# 对接支付宝,返回支付页面# 通过支付宝对象处理订单信息order_string = alipay.api_alipay_trade_page_pay(out_trade_no=order.order_id, #订单号传过去total_amount = str(order.total_amount), #要支付的金额subject=f'PROMOTE系统{order.order_id}',#标题# 这里可以配置到配置文件中去,前端更新,方便我们同步更新return_url='http://localhost:8080/home/order/success', #回调地址,成功后就跳转到前端的支付成功的页面)# 将订单信息发送给支付宝#即沙箱环境中的支付宝网关地址pay_url = 'https://openapi-sandbox.dl.alipaydev.com/gateway.do?' + order_string# 返回支付页面,前端拿到这个地址后发起请求,就会跳转到支付宝的支付页面return Response({'pay_url':pay_url})
- 点击支付后,页面会跳转到支付宝的支付页面
- 在支付宝开放平台找到买家账号密码进行登录
- 支付成功后会根据回调地址跳转到我们前端的支付成功页面
- 在加载这个页面时,前端就会拿到这个页面中的订单参数,去访问OrderCartViewSet中的status接口,修改订单状态为待发货。