目录

1.积分

2.支付

1.积分

1.关于积分的表结构

1.在user表中添加credit字段 + 设计一个积分的表结构

user/models.py

  1. class User(AbstractUser):
  2. phone = models.CharField(max_length=16,null=True,blank=True)
  3. wechat = models.CharField(max_length=16,null=True,blank=True)
  4.  
  5. # 为用户表添加积分字段 每个用户都有自己积分
  6. credit = models.IntegerField(default=0, blank=True, verbose_name="贝里")
  7.  
  8. class Credit(BaseModel):
  9. """积分流水"""
  10. OPERA_OPION = (
  11. (1, "赚取"),
  12. (2, "消费"),
  13. )
  14. user = models.ForeignKey("User", related_name="user_credit", on_delete=models.CASCADE, verbose_name="用户")
  15. opera = models.SmallIntegerField(choices=OPERA_OPION,verbose_name="操作类型")
  16. number = models.SmallIntegerField(default=0, verbose_name="积分数值")
  17.  
  18. class Meta:
  19. db_table = 'ly_credit'
  20. verbose_name = '积分流水'
  21. verbose_name_plural = verbose_name
  22.  
  23. def __str__(self):
  24. return "%s %s %s 贝壳" % ( self.user.username, self.OPERA_OPION[self.opera][1], self.number )

2.设置积分和现金的兑换比例

constant.py

  1. CREDIT_MONEY = 10 # 10积分顶一块钱

2.登录成功将积分回复给前端

1.登录成功 给前端回复除了[用户名 id token],也要把[积分和计算公式]回复给前端

user/utils.py

  1. def jwt_response_payload_handler(token, user=None, request=None):
  2. return {
  3. 'token': token,
  4. 'username': user.username,
  5. 'id':user.id,
  6.  
  7. # 登录成功将积分和兑换比例也要返回给前端
  8. 'credit':user.credit,
  9. 'credit_to_money':contains.CREDIT_MONEY,
  10. }

2.前端将积分存起来

login.vue

  1. if (this.remember){
  2. localStorage.token = res.data.token;
  3. localStorage.username = res.data.username;
  4. localStorage.id = res.data.id;
  5.  
  6. // 前端将积分存起来
  7. localStorage.credit = res.data.credit;
  8. localStorage.credit_to_money = res.data.credit_to_money;
  9. sessionStorage.removeItem('token');
  10. sessionStorage.removeItem('username');
  11. sessionStorage.removeItem('id');
  12. sessionStorage.removeItem('credit');
  13. sessionStorage.removeItem('credit_to_money');
  14.  
  15. }else {
  16. sessionStorage.token = res.data.token;
  17. sessionStorage.username = res.data.username;
  18. sessionStorage.id = res.data.id;
  19.  
  20. // 前端将积分存起来
  21. sessionStorage.credit = res.data.credit;
  22. sessionStorage.credit_to_money = res.data.credit_to_money;
  23. localStorage.removeItem('token');
  24. localStorage.removeItem('username');
  25. localStorage.removeItem('id');
  26. localStorage.removeItem('credit');
  27. localStorage.removeItem('credit_to_money');
  28. }

3.自行输入使用积分

在input标签中绑定一个change方法 当input标签输入的值发生变化的时候 触发@change下对应的方法

order.vue

  1. <!-- html -->
  2. <p class="discount-num2" v-else><span>总积分:xxxx,
  3. <el-input-number v-model="num" @change="handleChange" :min="0" :max="10000" label="描述文字"></el-input-number>,已抵扣xxx元,本次花费xxx积分</span></p>
  1. // js
  2. handleChange(value){
  3. // 如果用户在积分输入框中没有输入值,那么默认使用了0个积分
  4. if (!value){
  5. this.num = 0
  6. }
  7. console.log(value);
  8.  
  9. },

4.拿取积分

order.vue

  1. get_credit(){
  2. // 从前端拿取积分和兑换比例
  3. this.credit = localStorage.getItem('credit') || sessionStorage.getItem('credit')
  4. this.credit_to_money = localStorage.getItem('credit_to_money') || sessionStorage.getItem('credit_to_money')
  5. },

5.在页面展示出积分

order.vue

  1. <!-- html -->
  2. <p class="discount-num2" v-else><span>总积分:{{credit}},

6.计算可以使用的最大积分

order.vue

  1. max_credit(){
  2.  
  3. // 计算此课程能使用的最大积分数:比如100元的课程最多能使用1000积分
  4. let a = parseFloat(this.total_price) * parseFloat(this.credit_to_money);
  5.  
  6. // 如果此课程能使用的最大积分数[1000]小于你的总积分数[1500]:那么你能使用的最大积分数就是[1000]
  7. if (this.credit >= a){
  8. return a
  9. // 如果此课程能使用的最大积分数[1000]大于你的总积分数[600],那么你能使用的最大积分数就是你剩余的积分数[600]
  10. }else {
  11. return parseFloat(this.credit)
  12. }

7.前端发送请求

order.vue

  1. payhander(){
  2. let token = localStorage.token || sessionStorage.token;
  3. this.$axios.post(`${this.$settings.Host}/order/add_money/`,{
  4. "pay_type":this.pay_type,
  5. "coupon":this.current_coupon,
  6. "credit":this.num, // 将积分提交给后端,让后端对积分做校验
  7.  
  8. },{
  9. headers:{
  10. 'Authorization':'jwt ' + token
  11. }
  12. }).then((res)=>{
  13. this.$message.success('订单已经生成,马上跳转支付页面')
  14.  
  15. }).catch((error)=>{
  16. this.$message.error(error.response.data.msg);
  17. })
  18.  
  19. }

8.后端对积分做校验

order/serializers.py

  1. def validate(self, attrs):
  2.  
  3. # 获取前端发过来的积分
  4. credit = attrs.get('credit')
  5.  
  6. # 查询用户所拥有的的所有积分
  7. user_credit = self.context['request'].user.credit
  8.  
  9. # 如果前端积分大于用户积分,抛出异常
  10. if credit > user_credit:
  11. raise serializers.ValidationError('积分超上限了,别乱搞')
  12.  
  13. return attrs
  14.  
  15. def create(self, validated_data):
  16.  
  17. # 积分判断
  18. credit = float(validated_data.get('credit',0)) # 获取前端发过来的验证之后的积分
  19. if credit > constants.CREDIT_MONEY * total_real_price: # 如果使用积分超过你此课程能使用的最大积分
  20. transaction.savepoint_rollback(sid) # 回滚到断点处
  21. raise serializers.ValidationError('使用积分超过了上线,别高事情')
  22.  
  23. # 积分计算
  24. total_real_price -= credit / contains.CREDIT_MONEY

2.支付

1.准备工作

1.安装python-alipay-sdk

  1. pip install python-alipay-sdk --upgrade

2.创建应用payment,并配置INSTALLAPP

  1. python3 manage.py startapp payment

3.在payment应用目录创建keys文件夹

2.公钥和私钥

1.OpenSSL命令下生成私钥

  1. openssl
  2. OpenSSL> genrsa -out app_private_key.pem 2048 # 生成私钥到指定文件中

2.OpenSSL命令下生成公钥

  1. openssl
  2. OpenSSL> rsa -in app_private_key.pem -pubout -out app_public_key.pem # 导出公钥

3.沙箱环境应用公钥要更换成自己在openssl生成的应用公钥

4.支付宝公钥存到alipay_public_key.pem中

3.为支付页面配置路由

payment/urls.py

  1. from django.urls import path,re_path
  2. from . import views
  3.  
  4. urlpatterns = [
  5. path('alipay/',views.AlipayView.as_view(),),
  6.  
  7. ]

4.视图

payment/views.py

  1. from alipay import AliPay, DCAliPay, ISVAliPay
  2. from alipay.utils import AliPayConfig
  3.  
  4. class AlipayView(APIView):
  5.  
  6. def get(self,request):
  7. order_number = request.query_params.get('order_number')
  8. order_obj = Order.objects.get(order_number=order_number)
  9.  
  10. alipay = AliPay(
  11. appid=settings.ALIAPY_CONFIG['appid'],
  12. app_notify_url=None, # 默认回调url
  13. app_private_key_string=open(settings.ALIAPY_CONFIG['app_private_key_path']).read(),
  14. # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥,
  15. alipay_public_key_string=open(settings.ALIAPY_CONFIG['alipay_public_key_path']).read(),
  16. sign_type=settings.ALIAPY_CONFIG['sign_type'], # RSA 或者 RSA2
  17. debug = settings.ALIAPY_CONFIG['debug'], # 默认False
  18. )
  19.  
  20. order_string = alipay.api_alipay_trade_page_pay(
  21. out_trade_no=order_obj.order_number,
  22. total_amount=float(order_obj.real_price),
  23. subject=order_obj.order_title,
  24. return_url=settings.ALIAPY_CONFIG['return_url'],
  25. notify_url=settings.ALIAPY_CONFIG['notify_url'] # 可选, 不填则使用默认notify url
  26. )
  27.  
  28. url = settings.ALIAPY_CONFIG['gateway_url'] + order_string
  29.  
  30. return Response({'url': url})

5.支付宝配置信息

dev.py

  1. # 支付宝配置信息
  2. ALIAPY_CONFIG = {
  3. "gateway_url": "https://openapi.alipaydev.com/gateway.do?", # 沙箱支付宝网关地址
  4. "appid": "2016093000633754", # 沙箱中那个应用id
  5. "app_notify_url": None,
  6. "app_private_key_path": os.path.join(BASE_DIR, "apps/payment/keys/app_private_key.pem"),
  7.  
  8. "alipay_public_key_path": os.path.join(BASE_DIR, "apps/payment/keys/alipay_public_key.pem"),
  9. "sign_type": "RSA2",
  10. "debug": False,
  11. "return_url": "http://www.lycity.com:8080/payment/result", # 同步回调地址
  12. "notify_url": "http://www.lyapi.com:8001/payment/result", # 异步结果通知

6.前端发送请求获取到一个支付页面的url

  1. payhander(){
  2.  
  3. this.$axios.post(`${this.$settings.Host}/order/add_money/`,{
  4.  
  5. }).then((res)=>{
  6. this.$message.success('订单已经生成,马上跳转支付页面')
  7. let order_number = res.data.order_number
  8.  
  9. this.$axios.get(`${this.$settings.Host}/payment/alipay/?order_number=${order_number}`)
  10. .then((res)=>{
  11. // res.data : alipay.trade...?a=1&b=2....
  12. location.href = res.data.url;
  13.  
  14. })
  15.  
  16. }).catch((error)=>{
  17. this.$message.error(error.response.data.msg);
  18. })
  19.  
  20. }

7.支付成功的页面-初始化

Success.vue

  1. <template>
  2. <div class="success">
  3. <Header/>
  4. <div class="main">
  5. <div class="title">
  6. <!-- <img src="../../static/images/right.svg" alt="">-->
  7. <div class="success-tips">
  8. <p class="tips1">您已成功购买 1 门课程!</p>
  9. <p class="tips2">你还可以加入QQ群 <span>747556033</span> 学习交流</p>
  10. </div>
  11. </div>
  12. <div class="order-info">
  13. <p class="info1"><b>付款时间:</b><span>2019/04/02 10:27</span></p>
  14. <p class="info2"><b>付款金额:</b><span >0</span></p>
  15. <p class="info3"><b>课程信息:</b><span><span>《Pycharm使用秘籍》</span></span></p>
  16. </div>
  17. <div class="wechat-code">
  18. <!-- <img src="../../static/image/server.cf99f78.png" alt="" class="er">-->
  19. <!-- <p><img src="../../static/image/tan.svg" alt="">重要!微信扫码关注获得学习通知&amp;课程更新提醒!否则将严重影响学习进度和课程体验!</p>-->
  20. </div>
  21. <div class="study">
  22. <span>立即学习</span>
  23. </div>
  24. </div>
  25. <Footer/>
  26. </div>
  27. </template>
  28.  
  29. <script>
  30. import Header from "./common/Header"
  31. import Footer from "./common/Footer"
  32. export default{
  33. name:"Success",
  34. data(){
  35. return {
  36. current_page:0,
  37. };
  38. },
  39. created(){
  40. // 把地址栏上面的支付结果,转发给后端
  41.  
  42. },
  43. components:{
  44. Header,
  45. Footer,
  46. }
  47. }
  48. </script>
  49.  
  50. <style scoped>
  51. .success{
  52. padding-top: 80px;
  53. }
  54. .main{
  55. height: 100%;
  56. padding-top: 25px;
  57. padding-bottom: 25px;
  58. margin: 0 auto;
  59. width: 1200px;
  60. background: #fff;
  61. }
  62. .main .title{
  63. display: flex;
  64. -ms-flex-align: center;
  65. align-items: center;
  66. padding: 25px 40px;
  67. border-bottom: 1px solid #f2f2f2;
  68. }
  69. .main .title .success-tips{
  70. box-sizing: border-box;
  71. }
  72. .title img{
  73. vertical-align: middle;
  74. width: 60px;
  75. height: 60px;
  76. margin-right: 40px;
  77. }
  78. .title .success-tips{
  79. box-sizing: border-box;
  80. }
  81. .title .tips1{
  82. font-size: 22px;
  83. color: #000;
  84. }
  85. .title .tips2{
  86. font-size: 16px;
  87. color: #4a4a4a;
  88. letter-spacing: 0;
  89. text-align: center;
  90. margin-top: 10px;
  91. }
  92. .title .tips2 span{
  93. color: #ec6730;
  94. }
  95. .order-info{
  96. padding: 25px 48px;
  97. padding-bottom: 15px;
  98. border-bottom: 1px solid #f2f2f2;
  99. }
  100. .order-info p{
  101. display: -ms-flexbox;
  102. display: flex;
  103. margin-bottom: 10px;
  104. font-size: 16px;
  105. }
  106. .order-info p b{
  107. font-weight: 400;
  108. color: #9d9d9d;
  109. white-space: nowrap;
  110. }
  111. .wechat-code{
  112. display: flex;
  113. -ms-flex-align: center;
  114. align-items: center;
  115. padding: 25px 40px;
  116. border-bottom: 1px solid #f2f2f2;
  117. }
  118. .wechat-code>img{
  119. width: 100px;
  120. height: 100px;
  121. margin-right: 15px;
  122. }
  123. .wechat-code p{
  124. font-size: 14px;
  125. color: #d0021b;
  126. display: -ms-flexbox;
  127. display: flex;
  128. -ms-flex-align: center;
  129. align-items: center;
  130. }
  131. .wechat-code p>img{
  132. width: 16px;
  133. height: 16px;
  134. margin-right: 10px;
  135. }
  136. .study{
  137. padding: 25px 40px;
  138. }
  139. .study span{
  140. display: block;
  141. width: 140px;
  142. height: 42px;
  143. text-align: center;
  144. line-height: 42px;
  145. cursor: pointer;
  146. background: #ffc210;
  147. border-radius: 6px;
  148. font-size: 16px;
  149. color: #fff;
  150. }
  151. </style>

支付成功的页面-初始化

注册Success组件

  1. {
  2. path: '/payment/result/',
  3. component: Success
  4. },

day87:luffy:结算页面积分&支付宝接口的更多相关文章

  1. day86:luffy:前端发送请求生成订单&结算页面优惠劵的实现

    目录 1.前端发送请求生成订单 1.前端点击支付按钮生成订单 2.结算成功之后应该清除结算页面的数据 3.后端计算结算页面总原价格和总的真实价格并存到数据库订单表中 2.优惠劵 1.准备工作 2.前端 ...

  2. 调用支付宝接口Android客户端没有支付宝APP的情况下解决无法调用支付宝页面的问题

    这几天一直研究支付宝接口调用,因为当前应用中需要调用支付宝接口作移动支付. 遇到一个问题困扰几天,就是当我们的手机端未安装支付宝APP的时候,需要在自己应用中调用支付宝的登陆网页进行支付.我是Andr ...

  3. ThinkPHP实现支付宝接口功能

    最近做系统,需要实现在线支付功能,毫不犹豫,选择的是支付宝的接口支付功能.这里我用的是即时到帐的接口,具体实现的步骤如下:一.下载支付宝接口包下载地址:https://doc.open.alipay. ...

  4. (实用篇)php支付宝接口用法分析

    本文实例讲述了php支付宝接口用法.分享给大家供大家参考.具体分析如下: 现在流行的网站支持平台,支付宝当仁不让的老大了,现在我们就来告诉你如何使用支付宝api来做第三方支付,把支付宝放到自己网站来, ...

  5. 【转载】关于Alipay支付宝接口(Java版)

    转载自:http://blog.163.com/lai_chao/blog/static/70340789201412724619514/ 1.alipay 双功能支付简介 2.alipay 提交支付 ...

  6. android应用程序如何调用支付宝接口

    最近在做一个关于购物商城的项目,项目里面付款这块我选的是调用支付宝的接口,因为用的人比较多. 在网上搜索了以下,有很多这方面的教程,但大部分教程过于陈旧,而且描述的过于简单.而且支付宝提供的接口一直在 ...

  7. [转]支付宝接口程序、文档及解读(ASP.NET)

    本文转自:http://www.cnblogs.com/blodfox777/archive/2009/11/03/1595223.html 最近需要为网站加入支付宝的充值接口,而目前关于支付宝接口开 ...

  8. android应用程序如何调用支付宝接口(转)

    最近在做一个关于购物商城的项目,项目里面付款这块我选的是调用支付宝的接口,因为用的人比较多. 在网上搜索了以下,有很多这方面的教程,但大部分教程过于陈旧,而且描述的过于简单.而且支付宝提供的接口一直在 ...

  9. android开发支付宝接口开发流程(密钥篇)

    参考博客:http://blog.it985.com/12276.html 官方下载地址:http://download.alipay.com/public/api/base/WS_MOBILE_PA ...

随机推荐

  1. MySQL 日志详解

    一.MySQL 日志分类 MySQL 日志主要包含:错误日志.查询日志.慢查询日志.事务日志.二进制日志. 错误日志: -log-err (记录启动.运行.停止 MySQL 服务时出现的信息) 查询日 ...

  2. Fedora version history --- kernel version

    Fedora version history https://en.wikipedia.org/wiki/Fedora_version_history     Version (Code name)[ ...

  3. DX12龙书 02 - DirectXMath 库中与向量有关的类和函数

    0x00 需要用到的头文件 #include <DirectXMath> #include <DirectXPackedVector.h> using namespace Di ...

  4. 如何把base64格式的图片上传到到阿里云oss c#版

    今天碰到需要把canvas上的的图片转存到阿里云oss,于是百度了半天,一个能打的答案都没有.怒了,自己搞起. 代码超级简单,需要先引入nuget 中啊里云的oss api 1 byte[] arr ...

  5. rs232转rs485

    rs232转rs485 rs232转rs485 ZLAN9223E是上海卓岚科技开发的一款先进的无源RS232转RS485转换器.具有如下优点: 支持最高达230400bps的波特率.高波特率下供电能 ...

  6. ERP订单管理的操作与设计--开源软件诞生19

    赤龙ERP订单模块讲解--第19篇 用日志记录"开源软件"的诞生 [点亮星标]----祈盼着一个鼓励 博主开源地址: 码云:https://gitee.com/redragon/r ...

  7. nginx集群:nginx配置负载均衡集群(nginx1.18.0)

    一,nginx的负载均衡集群的特点: 1,nginx集群和lvs的不同? lvs集群:工作在第4层(传输层) nginx集群:工作在第7层(应用层) lvs集群:性能更强 nginx集群:功能更强:可 ...

  8. Mosquitto服务器的日志分析

    启动Mosquitto后,我们可以看到Mosquitto的启动日志: 1515307521: mosquitto version 1.4.12 (build date 2017-06-01 13:03 ...

  9. MVC联想查询绑定下拉框

    前言 在做搜索时,输入些内容时需要弹出下拉框给用户进行选择,极大的方便了用户,会给用户带来不一样的体验 Controller public ActionResult SSAC(string UserN ...

  10. ubuntu JDK&SDK 环境变量配置

    ubuntu JDK&SDK 环境变量配置 一.下载JDK 1. 先卸载Ubuntu 带的openJDK: sudo apt-get purge openjdk* 2.到http://www. ...