支付宝流程
1.创建goods模型
1.1创建商品模型goods
python ../manage.py startapp goods # 创建goods模型
1.2在setting.py中注册goods模型(第一步)
INSTALLED_APPS = [ 'goods.apps.GoodsConfig', ] # 注:pycharm无法联想,需要把apps文件夹设置为源根
1.3 syl/urls.py添加路由(第二步)
urlpatterns = [ path('goods/', include('goods.urls')), ]
1.4 创建 goods/urls.py路由文件(第三步)
from django.urls import path, re_path from . import views urlpatterns = [ ]
2 表结构分析
2.1商品表与订单表
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
2.2用户表和vip表
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from django.db import models from django.contrib.auth.models import AbstractUser class Base(models.Model): create_time=models.DateTimeField('创建时间',auto_now_add=True,null=True) update_time=models.DateTimeField('更新时间',auto_now=True,null=True) class Meta: abstract=True # 创建Vip表,并和用户进行关联 class Vip(Base): vip_choise = ( ('0', '普通用户'), ('1', '普通会员'), ('2', '高级会员'), ) title = models.CharField('vip名称', max_length=16) vip_type = models.CharField('Vip种类',choices=vip_choise ,max_length=4) desc = models.CharField('vip描述',max_length=255) period = models.IntegerField('有效期', default=365) class Meta: db_table = 'tb_vip' def __str__(self): return self.title #用户表 class User(AbstractUser): phone = models.CharField('手机号',max_length=20) img = models.ImageField(upload_to='user',null=True) nick_name = models.CharField('昵称',max_length=20) address = models.CharField('地址',max_length=255) vip = models.ForeignKey(Vip, on_delete=models.SET_NULL, default=None, null=True) vip_expiration = models.DateField('vip到期时间', blank=True, default=None, null=True) class Meta: db_table = 'tb_user'
2.3添加购买课程表
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#用户购买的课程 class UserCourse(Base): user=models.ForeignKey('user.User',on_delete=models.CASCADE,related_name='paycourse') course = models.ForeignKey('course.Course', on_delete=models.CASCADE, related_name='payuser') class Meta: db_table = 'tb_usercourse' def __str__(self): return "用户:%s, 课程:%s" % (self.user.username, self.course.title)
2.4 admin中注册
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from django.contrib import admin # Register your models here. from . import models admin.site.register(models.UserCourse)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from django.contrib import admin # Register your models here. from .models import * admin.site.register(Goods) admin.site.register(Orders)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from django.contrib import admin # Register your models here. from .models import * admin.site.register(User) admin.site.register(Vip)
3测试沙箱支付宝链接
https://openhome.alipay.com/platform/appDaily.htm
3.1密钥
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
-----BEGIN RSA PRIVATE KEY-----
MIICXwIBAAKBgQCq0LFBc9yy8exEepMAXF4BoeaKaa/GJ8AZYh2eEhIro7Z9e6XK5mYXrfVwHbWKO4EhD4SKYrmQx+qlDvkvLNJjzBpG3q1MoiqYVRSpu7IH1F0igHnvHyvzepjIqPzWcgnZDsEHSgeOkoL2ffCG7eIqyo5O9xIHTvScBVzihabXFwIDAQABAoGBAKB5w62cLiGnirKi/Wv/Wwnpkm9C7zIYsi6msPCKRavd+FpXSeEfJ5bjhYw5PQ6K7Lukmn5wVamhR96d/JjHYTd74d6qhPAyorCGYSbLdNmtXT/kL2WeLclt4hfdYQM54eR0q0DPNc7Q4THnw8s2jpxdEpa3nKmyGhl3BgsrWpZxAkEA0l3c3TrxC7l2dcA7uYw3I2PYt7ORLdjdJ5eIK5+xnZ5UQHsPwTKN/OHj67gHJ1NcFdzcfCWjUQq6NY/fCBrnwwJBAM/ecrgLmwN5ZLF2J0nwX6EvyMr7Q6IpRNxIeAyhze00Xg1VL9jExzYbM9jFzezrSG7UJC2n+LlVpcR10GJnsh0CQQClkcSsxqBDRxRKNyOKtSYMj6BZbVY9jGr7p1NAam8EDEJpgbHzsBN6zltyAiR3Oi/G8U8D0yfIODY4w+SZX3u7AkEAmHH8Ugt42LhrZ1ZOhAQ8Ldr8eBiDxmZbsO2Y1TLI8iBIpaCG4YOW0ZBrmpueZRU8XsNH8Q/R8iHk20rH05NW5QJBAL51dx/IEQOZOUAwnlYWV4aE3XGmCyP8hP4fjQA0po7+CRV9Y9D4F44dtHvQylhLXP0DuAHyT47z+7JDannZdE8=
-----END RSA PRIVATE KEY-----
支付宝公钥
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
-----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDIgHnOn7LLILlKETd6BFRJ0GqgS2Y3mn1wMQmyh9zEyWlz5p1zrahRahbXAfCfSqshSNfqOmAQzSHRVjCqjsAw1jyqrXaPdKBmr90DIpIxmIyKXv4GGAkPyJ/6FTFY99uhpiq0qadD/uSzQsefWo0aTvP/65zi3eof7TcZ32oWpwIDAQAB -----END PUBLIC KEY-----
测试是否能生成支付宝链接
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# -*- coding: utf-8 -*- from alipay import AliPay # app_private_key_string = open('app_private_key.pem').read() app_private_key_string = open('app_private_key.pem').read() alipay_public_key_string = open( 'alipay_public_key.pem').read() def get_alipay_url(): alipay=AliPay( # 2016102600762709 appid="2016102600762709", # 沙箱appid app_notify_url=None, # 默认回调url app_private_key_string=app_private_key_string, # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥, alipay_public_key_string=alipay_public_key_string, sign_type="RSA", # RSA 或者 RSA2 debug=True, # 默认False,我们是沙箱,所以改成True(让访问沙箱环境支付宝地址) ) # 调用支付接口,生成支付链接 order_string = alipay.api_alipay_trade_page_pay( out_trade_no = "201612226", # 订单id,应该从前端获取 total_amount=str(0.01), # 订单总金额 subject="测试阿里云付款", # 付款标题信息 return_url=None, # 付款成功回调地址(可以为空) notify_url=None # 付款成功后异步通知地址(可以为空) ) pay_url = "https://openapi.alipaydev.com/gateway.do?" + order_string print( pay_url) # 将这个url复制到浏览器,就会打开支付宝支付页面 if __name__ == '__main__': get_alipay_url() # query_pay()
4创建订单并生成支付链接接口
4.1 goods/urls.py中注册路由
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from django.urls import path from . import views urlpatterns = [ path('getpayurl/', views.PayUrlView.as_view()), path('peyment/', views.PayMentView.as_view()) ]
4.2 goods/views.py中写视图
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from rest_framework.views import APIView from rest_framework.permissions import AllowAny,IsAuthenticated from rest_framework.response import Response from .models import Goods,Orders from course.models import UserCourse from goods.utils import get_order_id, get_pay_url, alipay from decimal import Decimal from user.models import User class PayUrlView(APIView): permission_classes = (IsAuthenticated,) def post(self,request): goods_id=request.data.get('goods_id') goods=Goods.objects.get(id=goods_id) user=request.user order_id = get_order_id() if user.vip.vip_type == '1': # 普通会员 goods_price = goods.price * Decimal('0.80').quantize(Decimal('0.00')) elif user.vip.vip_type == '2': # 高级会员 goods_price = goods.price * Decimal('0.60').quantize(Decimal('0.00')) else: # 普通用户 goods_price=goods.price goods_price = Decimal(goods_price).quantize(Decimal('0.00')) order = Orders(user=user, goods=goods, order_id=order_id, pay_method=1,total_amount=goods_price) order.save() print(order.total_amount,type(order.total_amount)) # 3. 根据订单 生成支付链接 subject="实验楼订单:%s, 价格:%s" % (order.order_id, order.total_amount) pay_url=get_pay_url(order.order_id, order.total_amount, subject) # 4. 返回链接 return Response({"code": 0, "msg": "下单成功", "data": {"pay_url": pay_url}}) from course.models import UserCourse class PayMentView(APIView): permission_classes = (AllowAny,) def post(self,request): data=request.data sign=data.pop('sign') order=Orders.objects.get(order_id=data['out_trade_no']) order.trade_no=data['trade_no'] order.pay_time=data['timestamp'] order.status=2 order.save() user=order.user course=order.goods.course UserCourse.objects.create(user=user,course=course) return Response({"code":0,"msg":"购买成功"})
4.3 goods/utils.py中生成随机订单函数和生成支付URL函数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import datetime import os import random from alipay import AliPay from syl import settings app_private_key_path = os.path.join(settings.BASE_DIR, "apps/goods/keys/app_private_key.pem") alipay_public_key_path = os.path.join(settings.BASE_DIR, "apps/goods/keys/alipay_public_key.pem") with open(app_private_key_path) as f: app_private_key_string = f.read() with open(alipay_public_key_path) as f: alipay_public_key_string = f.read() alipay = AliPay( appid=settings.ALIPAY_APPID, app_notify_url=None, # 默认回调url app_private_key_string=app_private_key_string, alipay_public_key_string=alipay_public_key_string, # app_private_key_path=app_private_key_path, # alipay_public_key_path=alipay_public_key_path, sign_type="RSA", debug=settings.ALIPAY_DEBUG ) def get_pay_url(out_trade_no, total_amount, subject): order_string = alipay.api_alipay_trade_page_pay( out_trade_no=out_trade_no, total_amount=str(total_amount), subject=subject, return_url=settings.ALIPAY_RETURN_URL, ) # 响应登录支付宝连接 # 真实环境电脑网站支付网关:https://openapi.alipay.com/gateway.do? + order_string # 沙箱环境电脑网站支付网关:https://openapi.alipaydev.com/gateway.do? + order_string alipay_url = settings.ALIPAY_URL + "?" + order_string return alipay_url alipay_url = settings.ALIPAY_URL + "?" + order_string return alipay_url def get_order_id(): """ SYL202008241212121200005/24 生成订单号: 格式: SYL + 年月日时分秒 + 5位随机数 :return: """ d = datetime.datetime.now() base = 'SYL' time_str = '%04d%02d%02d%02d%02d%02d' % (d.year, d.month, d.day, d.hour, d.minute, d.second) rand_num = str(random.randint(10000, 99999)) return base + time_str + rand_num
4.4syl/setings.py中配置支付相关参数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# 支付宝配置 ALIPAY_APPID = '2016102600762709' # 沙箱环境中alipay应用ID ALIPAY_DEBUG = True ALIPAY_URL = 'https://openapi.alipaydev.com/gateway.do' # alipay沙箱环 境支付宝网管 ALIPAY_RETURN_URL = 'http://127.0.0.1:8888/payment/callback/' # 支付完成后支 付宝回调我们应用的地址
关联购买记录表
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from goods.serializers import GoodsSerializer class CourseDeepSerializer(CourseSerializer): goods_set=GoodsSerializer(many=True) chapters = ChaptersSerializer(many=True)