{{article.name}}
字数 {{article.content.length}}
阅读 {{article.read_count}}
8人点赞
"小礼物走一走,来简书关注我"
已经有{{article.reward_count}}人赞赏,支持一下
还没有人赞赏,支持一下
書酱
你读书的样子真好看。
总资产0
共写了78.7W字
获得6,072个赞
共1,308个粉丝
给作者送糖
{{num}}
选择支付方式
{{type}}
支付接口,可以实现网络转账。
很多的第三方支付接口:
国外:万事达,applePay,PayPAl,Visa,八达通,西联[邮政汇款]
国内:支付宝,微信,京东钱包,百度钱包,贝宝[PayPal中国版]
https://open.alipay.com/platform/home.htm
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sFS71XCH-1595162910475)(E:/python八期/北京python27期荏苒项目/day125/assets/1584442807263.png)]
支付宝的申请需要企业资质,但是我们作为开发者可以使用支付宝提供的测试账号先开发功能,将来调整账号即可用于公司项目的正式运营。
地址:https://openhome.alipay.com/platform/developerIndex.htm
是支付宝提供给开发者的模拟支付的环境
沙箱环境跟真实环境是分开的,项目上线时必须切换对应的配置服务器地址和开发者ID和密钥。
沙箱应用开发文档:https://docs.open.alipay.com/200/105311
沙箱账号:https://openhome.alipay.com/platform/appDaily.htm?tab=account
真实的支付宝网关: https://openapi.alipay.com/gateway.do
沙箱的支付宝网关: https://openapi.alipaydev.com/gateway.do
【前后端不分离】时序图[ 时间顺序流程图 ]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6Ik5a4IA-1595162910477)(E:/python八期/北京python27期荏苒项目/day125/assets/电脑网站支付流程图.png)]
【前后端分离】
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Y20fly7P-1595162910480)(E:/python八期/北京python27期荏苒项目/day125/assets/1584445167899.png)]
RSA算法,属于非堆成加密,一旦加密以后不能解密的。
可以通过密钥来进行验证。
密钥成对生成的。分公钥和私钥。
公钥用于验证数据[ 解签 ]
私钥用于加密数据[ 签名 ]
cd renranapi/apps
python ../../manage.py startapp payments
注册子应用
INSTALLED_APPS = [
。。。。
'payments',
]
下载对应系统的秘钥生成工具: https://doc.open.alipay.com/docs/doc.htm?treeId=291&articleId=105971&docType=1
生成如下,安装软件时需要管理员身份来安装.
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nOToDfqU-1595162910483)(E:/python八期/北京python27期荏苒项目/day125/assets/1566548916758.png)]
生成如下:
openssl
OpenSSL> genrsa -out app_private_key.pem 2048 # 生成私钥到指定文件中
OpenSSL> rsa -in app_private_key.pem -pubout -out app_public_key.pem # 导出公钥
OpenSSL> exit
应用公钥复制粘贴到支付宝网站页面中.
点击修改以后,粘贴进去
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MMPbznY6-1595162910486)(E:/python八期/北京python27期荏苒项目/day125/assets/1554192143494.png)]
在payments应用中新建keys目录,用来保存秘钥文件。
将应用私钥文件app_private_key.pem复制到payment/keys目录下。
windows系统生成的私钥必须在上下两行加上以下标识:
-----BEGIN RSA PRIVATE KEY-----
私钥
-----END RSA PRIVATE KEY-----
在payments/key目录下新建alipay_public_key.pem文件,用于保存支付宝的公钥文件。
将支付宝的公钥内容复制到alipay_public_key.pem文件中
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Bec2pVcG-1595162910487)(E:/python八期/北京python27期荏苒项目/day125/assets/支付宝公钥.png)]
-----BEGIN PUBLIC KEY-----
公钥
-----END PUBLIC KEY-----
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A5dcptc7-1595162910489)(E:/python八期/北京python27期荏苒项目/day125/assets/1554200221417.png)]
SDK:https://docs.open.alipay.com/270/106291/
python版本的支付宝SDK文档:https://github.com/fzlee/alipay/blob/master/README.zh-hans.md
安装命令:
pip install python-alipay-sdk --upgrade
创建模型,保存打赏记录
from django.db import models
from renranapi.utils.models import BaseModel
from users.models import User
from article.models import Article
class Reward(BaseModel):
REWARD_TYPE = (
(1, "支付宝"),
(2, "余额"),
)
user = models.ForeignKey(User, on_delete=models.DO_NOTHING, verbose_name="用户")
money = models.DecimalField(decimal_places=2, max_digits=6, verbose_name="打赏金额")
article = models.ForeignKey(Article, on_delete=models.DO_NOTHING, verbose_name="文章")
status = models.BooleanField(default=False, verbose_name="打赏状态")
trade_no = models.CharField(max_length=255, null=True, blank=True, verbose_name="流水号")
out_trade_no = models.CharField(max_length=255, null=True, blank=True, verbose_name="支付平台返回的流水号")
reward_type = models.IntegerField(default=1, verbose_name="打赏类型")
message = models.TextField(null=True,blank=True, verbose_name="打赏留言")
class Meta:
db_table = "rr_user_reward"
verbose_name = "打赏记录"
verbose_name_plural = verbose_name
def __str__(self):
return self.user.nickname+"打赏了"+self.article.user.nickname+"的文章《" +self.article.title+"》"+self.money+"元"
注册子应用
INSTALLED_APPS = [
# ....
'payments',
]
迁移迁移
python manage.py makemigrations
python manage.py migrate
编写视图提供支付的url地址
from django.shortcuts import render
# Create your views here.
from rest_framework.views import APIView
from .models import Reward
from rest_framework.permissions import IsAuthenticated
import random
from datetime import datetime
from alipay import AliPay
from django.conf import settings
from rest_framework.response import Response
class AliPayAPIView(APIView):
permission_classes = [IsAuthenticated]
def post(self,request):
"""生成支付的链接地址"""
# 创建打赏记录
user = request.user
# 验证用户打赏的文章是否存在
trade_no = datetime.now().strftime("%Y%m%d%H%M%S") + ("%06d" % user.id) + ("%06d"% random.randint(1,999999))
reward = Reward.objects.create(
user=user,
money=request.data.get("money"),
article_id=request.data.get("article_id"),
status=False,
trade_no=trade_no,
out_trade_no=None,
reward_type=request.data.get("type"),
message = request.data.get("message"),
)
if reward.reward_type == 1:
# 生成支付链接
# 初始化支付对象
app_private_key_string = open(settings.ALIAPY_CONFIG["app_private_key_path"]).read()
alipay_public_key_string = open(settings.ALIAPY_CONFIG["alipay_public_key_path"]).read()
alipay = AliPay(
appid=settings.ALIAPY_CONFIG["appid"],
app_notify_url=settings.ALIAPY_CONFIG["app_notify_url"], # 默认回调url
app_private_key_string=app_private_key_string,
# 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥,
alipay_public_key_string=alipay_public_key_string,
sign_type=settings.ALIAPY_CONFIG["sign_type"],
debug = settings.ALIAPY_CONFIG["debug"] # 默认False
)
# 调用接口
order_string = alipay.api_alipay_trade_page_pay(
out_trade_no=reward.trade_no,
total_amount=float(reward.money),
subject="打赏文章",
return_url=settings.ALIAPY_CONFIG["return_url"],
notify_url=settings.ALIAPY_CONFIG["notify_url"] # 可选, 不填则使用默认notify url
)
url = settings.ALIAPY_CONFIG["gateway_url"] + order_string
else:
# 进行其他类型的支付方式
url = ""
return Response(url)
setttins/dev.py,代码:
ALIAPY_CONFIG = {
# "gateway_url": "https://openapi.alipay.com/gateway.do?", # 真实支付宝网关地址
"gateway_url": "https://openapi.alipaydev.com/gateway.do?", # 沙箱支付宝网关地址
"appid": "2016091600523592",
"app_notify_url": None,
"app_private_key_path": os.path.join(BASE_DIR, "apps/payments/keys/app_private_key.pem"),
"alipay_public_key_path": os.path.join(BASE_DIR, "apps/payments/keys/alipay_public_key.pem"),
"sign_type": "RSA2",
"debug": False,
"return_url": "http://www.moluo.net:8080/", # 同步回调地址
"notify_url": "http://api.renran.cn:8000/payments/result", # 异步结果通知
}
注册url地址:payments/urls.py,代码:
from django.urls import path,re_path
from . import views
urlpatterns = [
path(r"alipay/",views.AlipayAPIView.as_view()),
]
总路由,代码:
path('payments/', include('payments.urls')),
{{article.title}}
文/小鸟飞过
罗曼·罗兰说:“生活中最沉重的负担不是工作,而是无聊。”
废掉一个人最快的方法
就是让他闲着
这段时间,综艺节目《妻子的浪漫旅行第三季3》正在热播,四对明星夫妻的相处模式曝光,也让观众更了解了曾经饱受争议的女人唐一菲。
有人很喜欢她大大咧咧的女侠性格,有人为她叫屈,当然还是有人骂她,说她旧事重提。
而我,则是觉得非常惋惜。
唐一菲是中央戏剧学院表演系毕业,真正的科班出身。
从2003年到2011年,基本保证每年都有作品,要么拍电视剧、要么拍电影,2008年出演新版《红楼梦》的秦可卿也是颇为动人。
可是自2012年结婚后,8年时间里,只拍了一部电视剧,就再也没了一点儿消息,仿佛整个人生都停滞了。
她在《妻子3》中展现出的婚姻状态是非常可悲的。
一喝酒,就是吐槽自己的人生被毁了。
要么直接形容老公凌潇肃是缩头乌龟。
作者简介:小鸟飞过,富小书的人,富书专栏作者,写温暖的文字,传递美好的情感;本文首发富小书(ID:fxsfrc),你身边最好的闺蜜,富书2018重磅推出新书《好好生活》。
注:本文章图片来源网络,如有侵权,请联系删除。
8人点赞
"小礼物走一走,来简书关注我"
还没有人赞赏,支持一下
書酱
你读书的样子真好看。
总资产0
共写了78.7W字
获得6,072个赞
共1,308个粉丝
给作者送糖
{{item}}
选择支付方式
支付宝
简书余额
客户端接收支付宝跳转发送回来的同步结果参数,并发起请求服务端的同步处理结果API接口
路由,代码:
import Wallet from "@/components/Wallet"
{
name:"Wallet",
path:"/usr/wallet",
component: Wallet,
},
视图代码:
# Create your views here.
from .models import Reward
from rest_framework.viewsets import ViewSet
from alipay import AliPay
from rest_framework.permissions import IsAuthenticated
from datetime import datetime
import random
from rest_framework import status
from rest_framework.response import Response
from django.conf import settings
from django.db import transaction
from article.models import Article
class AliPayAPIViewSet(ViewSet):
permission_classes = [IsAuthenticated]
def get_alipay(self):
# 初始化支付对象
app_private_key_string = open(settings.ALIAPY_CONFIG["app_private_key_path"]).read()
alipay_public_key_string = open(settings.ALIAPY_CONFIG["alipay_public_key_path"]).read()
alipay = AliPay(
appid=settings.ALIAPY_CONFIG["appid"],
app_notify_url=settings.ALIAPY_CONFIG["app_notify_url"], # 默认回调url
app_private_key_string=app_private_key_string,
# 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥,
alipay_public_key_string=alipay_public_key_string,
sign_type=settings.ALIAPY_CONFIG["sign_type"],
debug=settings.ALIAPY_CONFIG["debug"] # 默认False
)
return alipay
def post(self,request):
"""生成支付的链接地址"""
# 创建打赏记录
user = request.user
# 随机流水号
trade_no = datetime.now().strftime("%Y%m%d%H%M%S") + ("%06d" % user.id) + ("%06d" % random.randint(1, 999999))
money = request.data.get("money")
if money < 0:
return Response("对不起,支付金额不能小于0元", status=status.HTTP_400_BAD_REQUEST)
reward = Reward.objects.create(
user=user,
money=money,
article_id=request.data.get("article_id"),
status=0,
trade_no=trade_no,
out_trade_no=None,
reward_type=request.data.get("pay_type"),
message=request.data.get("content"),
orders=0,
)
if reward.reward_type == 0:
# 生成支付链接
alipay = self.get_alipay()
# 调用接口
order_string = alipay.api_alipay_trade_page_pay(
out_trade_no=reward.trade_no,
total_amount=float(reward.money), # 打赏金额
subject="打赏文章",
return_url=settings.ALIAPY_CONFIG["return_url"],
notify_url=settings.ALIAPY_CONFIG["notify_url"] # 可选, 不填则使用默认notify url
)
url = settings.ALIAPY_CONFIG["gateway_url"] + order_string
else:
# 进行其他类型的支付方式
url = ""
return Response(url)
def return_result(self,request):
"""支付宝同步结果处理"""
data = request.query_params.dict()
signature = data.pop("sign")
alipay = self.get_alipay()
success = alipay.verify(data, signature)
if success:
"""支付结果处理"""
# 开启ORM的mysql事务的自动提交,在with语句范围内,所有的SQL会全部被事务控制,要么一起提交,要么一起不提交
with transaction.atomic():
# 设置事务的回滚点,用于指定在事务失败时,在哪一部分的SQL语句无效
save_id = transaction.savepoint()
try:
# 修改打赏记录的状态为已付款
reward = Reward.objects.get(
trade_no=data.get("out_trade_no"),
status=0,
)
reward.status = 1
reward.save()
# 增加文章的打赏人数
article = Article.objects.get(pk=reward.article.id)
article.reward_count += 1
article.save()
print(article.user.money)
print(reward.money)
# 给用户资产增加打赏的资金
article.user.money= int((article.user.money + reward.money) * 100) / 100
article.user.save()
# 参考打赏,实现一个资金流水记录[专门显示在钱包位置]
except Reward.DoesNotExist:
transaction.savepoint_rollback(save_id)
return Response("当前打赏已经处理完成!请不要重复提交!")
except:
transaction.savepoint_rollback(save_id)
return Response({"message": "支付结果处理有误!"})
return Response({"message":"支付处理成功!"})
else:
return Response({"message": "支付失败!"}, status=status.HTTP_400_BAD_REQUEST)
路由:
from django.urls import path,re_path
from . import views
urlpatterns = [
path("alipay/", views.AliPayAPIViewSet.as_view({"post":"post"})),
path("alipay/result/", views.AliPayAPIViewSet.as_view({"get":"return_result"})),
]
from django.shortcuts import render
# Create your views here.
from .models import Reward
from rest_framework.viewsets import ViewSet
from alipay import AliPay
from rest_framework.permissions import IsAuthenticated
from datetime import datetime
import random
from rest_framework import status
from rest_framework.response import Response
from django.conf import settings
from django.db import transaction
from article.models import Article
class AliPayAPIViewSet(ViewSet):
permission_classes = [IsAuthenticated]
def get_alipay(self):
# 初始化支付对象
app_private_key_string = open(settings.ALIAPY_CONFIG["app_private_key_path"]).read()
alipay_public_key_string = open(settings.ALIAPY_CONFIG["alipay_public_key_path"]).read()
alipay = AliPay(
appid=settings.ALIAPY_CONFIG["appid"],
app_notify_url=settings.ALIAPY_CONFIG["app_notify_url"], # 默认回调url
app_private_key_string=app_private_key_string,
# 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥,
alipay_public_key_string=alipay_public_key_string,
sign_type=settings.ALIAPY_CONFIG["sign_type"],
debug=settings.ALIAPY_CONFIG["debug"] # 默认False
)
return alipay
def post(self,request):
"""生成支付的链接地址"""
# 创建打赏记录
user = request.user
# 随机流水号
trade_no = datetime.now().strftime("%Y%m%d%H%M%S") + ("%06d" % user.id) + ("%06d" % random.randint(1, 999999))
money = request.data.get("money")
if money < 0:
return Response("对不起,支付金额不能小于0元", status=status.HTTP_400_BAD_REQUEST)
reward = Reward.objects.create(
user=user,
money=money,
article_id=request.data.get("article_id"),
status=0,
trade_no=trade_no,
out_trade_no=None,
reward_type=request.data.get("pay_type"),
message=request.data.get("content"),
orders=0,
)
if reward.reward_type == 0:
# 生成支付链接
alipay = self.get_alipay()
# 调用接口
order_string = alipay.api_alipay_trade_page_pay(
out_trade_no=reward.trade_no,
total_amount=float(reward.money), # 打赏金额
subject="打赏文章",
return_url=settings.ALIAPY_CONFIG["return_url"],
notify_url=settings.ALIAPY_CONFIG["notify_url"] # 可选, 不填则使用默认notify url
)
url = settings.ALIAPY_CONFIG["gateway_url"] + order_string
else:
# 进行其他类型的支付方式
url = ""
return Response(url)
def return_result(self,request):
"""支付宝同步结果处理"""
data = request.query_params.dict()
signature = data.pop("sign")
alipay = self.get_alipay()
success = alipay.verify(data, signature)
if success:
"""支付结果处理"""
# 开启ORM的mysql事务的自动提交,在with语句范围内,所有的SQL会全部被事务控制,要么一起提交,要么一起不提交
with transaction.atomic():
# 设置事务的回滚点,用于指定在事务失败时,在哪一部分的SQL语句无效
save_id = transaction.savepoint()
try:
# 修改打赏记录的状态为已付款
reward = Reward.objects.get(
trade_no=data.get("out_trade_no"),
status=0,
)
reward.status = 1
reward.save()
# 增加文章的打赏人数
article = Article.objects.get(pk=reward.article.id)
article.reward_count += 1
article.save()
print(article.user.money)
print(reward.money)
# 给用户资产增加打赏的资金
article.user.money= int((article.user.money + reward.money) * 100) / 100
article.user.save()
# 参考打赏,实现一个资金流水记录[专门显示在钱包位置]
except Reward.DoesNotExist:
transaction.savepoint_rollback(save_id)
return Response("当前打赏已经处理完成!请不要重复提交!")
except:
transaction.savepoint_rollback(save_id)
return Response({"message": "支付结果处理有误!"})
return Response({"message":"支付处理成功!"})
else:
return Response({"message": "支付失败!"}, status=status.HTTP_400_BAD_REQUEST)
def notify_result(self,request):
"""支付宝异步结果处理"""
data = request.data.dict()
signature = data.pop("sign")
alipay = self.get_alipay()
success = alipay.verify(data, signature)
if success:
"""支付结果处理"""
# 开启ORM的mysql事务的自动提交,在with语句范围内,所有的SQL会全部被事务控制,要么一起提交,要么一起不提交
with transaction.atomic():
# 设置事务的回滚点,用于指定在事务失败时,在哪一部分的SQL语句无效
save_id = transaction.savepoint()
try:
# 修改打赏记录的状态为已付款
reward = Reward.objects.get(
trade_no=data.get("out_trade_no"),
status=0,
)
reward.status = 1
reward.save()
# 增加文章的打赏人数
article = Article.objects.get(pk=reward.article.id)
article.reward_count += 1
article.save()
print(article.user.money)
print(reward.money)
# 给用户资产增加打赏的资金
article.user.money= int((article.user.money + reward.money) * 100) / 100
article.user.save()
# 参考打赏,实现一个资金流水记录[专门显示在钱包位置]
except Reward.DoesNotExist:
transaction.savepoint_rollback(save_id)
return Response("当前打赏已经处理完成!请不要重复提交!")
except:
transaction.savepoint_rollback(save_id)
return Response({"message": "支付结果处理有误!"})
return Response({"message":"支付处理成功!"})
else:
return Response({"message": "支付失败!"}, status=status.HTTP_400_BAD_REQUEST)
路由代码:
from django.urls import path,re_path
from . import views
urlpatterns = [
path("alipay/", views.AliPayAPIViewSet.as_view({"post":"post"})),
path("alipay/result/", views.AliPayAPIViewSet.as_view({"get":"return_result","post":"notify_result"})),
]
d.save()
# 增加文章的打赏人数
article = Article.objects.get(pk=reward.article.id)
article.reward_count += 1
article.save()
print(article.user.money)
print(reward.money)
# 给用户资产增加打赏的资金
article.user.money= int((article.user.money + reward.money) * 100) / 100
article.user.save()
# 参考打赏,实现一个资金流水记录[专门显示在钱包位置]
except Reward.DoesNotExist:
transaction.savepoint_rollback(save_id)
return Response("当前打赏已经处理完成!请不要重复提交!")
except:
transaction.savepoint_rollback(save_id)
return Response({"message": "支付结果处理有误!"})
return Response({"message":"支付处理成功!"})
else:
return Response({"message": "支付失败!"}, status=status.HTTP_400_BAD_REQUEST)
路由代码:
```python
from django.urls import path,re_path
from . import views
urlpatterns = [
path("alipay/", views.AliPayAPIViewSet.as_view({"post":"post"})),
path("alipay/result/", views.AliPayAPIViewSet.as_view({"get":"return_result","post":"notify_result"})),
]