一、积分抵扣

1.修改用户模型

user/models.py

from django.db import models
from django.contrib.auth.models import AbstractUser
# Create your models here.
from lyapi.utils.models import BaseModelclass User(AbstractUser):phone = models.CharField(max_length=16,null=True,blank=True)wechat = models.CharField(max_length=16,null=True,blank=True)credit = models.IntegerField(default=0, blank=True, verbose_name="贝里")class Meta:db_table = 'ly_user'verbose_name = '用户表'verbose_name_plural = verbose_nameclass Credit(BaseModel):"""积分流水"""OPERA_OPION = ((1, "赚取"),(2, "消费"),)user = models.ForeignKey("User", related_name="user_credit", on_delete=models.CASCADE, verbose_name="用户")opera = models.SmallIntegerField(choices=OPERA_OPION,verbose_name="操作类型")number = models.SmallIntegerField(default=0, verbose_name="积分数值")class Meta:db_table = 'ly_credit'verbose_name = '积分流水'verbose_name_plural = verbose_namedef __str__(self):return "%s %s %s 贝壳" % ( self.user.username, self.OPERA_OPION[self.opera][1], self.number )from course.models import Course
class UserCourse(BaseModel):"""用户的课程购买记录"""pay_choices = ((1, '用户购买'),(2, '免费活动'),(3, '活动赠品'),(4, '系统赠送'),)# 1   1# 1   2# 1   3# 2   1# 2   2user = models.ForeignKey(User, related_name='user_courses', on_delete=models.DO_NOTHING, verbose_name="用户")course = models.ForeignKey(Course, related_name='course_users', on_delete=models.DO_NOTHING, verbose_name="课程")trade_no = models.CharField(max_length=128, null=True, blank=True, verbose_name="支付平台的流水号", help_text="将来依靠流水号到支付平台查账单")buy_type = models.SmallIntegerField(choices=pay_choices, default=1, verbose_name="购买方式")pay_time = models.DateTimeField(null=True, blank=True, verbose_name="购买时间")out_time = models.DateTimeField(null=True, blank=True, verbose_name="过期时间") #null表示永不过期class Meta:db_table = 'ly_user_course'verbose_name = '课程购买记录'verbose_name_plural = verbose_name

数据迁移

python manage.py makemigrations
python manage.py migrate

在xadmin运营站点中,给当前测试用户设置积分

2.设置积分比例

在配置文件中,设置积分和真实货币的换算比例
settings/contains.py增加配置:

# 积分兑换比例
CREDIT_MONEY = 10   # 10个积分顶一块钱

3.增加返回积分和换算比例的字段

在用户登录的代码中,增加返回积分和换算比例的字段

服务端中users/utils.py,代码;

...
from lyapi.settings import containsdef jwt_response_payload_handler(token, user=None, request=None):# print('>>>>>',user,type(user))return {'token': token,'username': user.username,'id':user.id,'credit':user.credit,'credit_to_money':contains.CREDIT_MONEY,}
...

在客户端中,保存积分到本地存储中.
Login.vue,在登录成功以后的代码中,

...loginHandle(){// 登录,用户名、密码、验证码数据var captcha1 = new TencentCaptcha('2041284967', (res) =>{ //生成图片验证码的if (res.ret === 0){console.log(res.randstr);console.log(res.ticket);this.$axios.post(`${this.$settings.Host}/users/login/`,{username:this.username,password:this.password,ticket:res.ticket,randstr:res.randstr,}).then((res)=>{console.log(res);// console.log(this.remember);if (this.remember){localStorage.token = res.data.token;localStorage.username = res.data.username;localStorage.id = res.data.id;localStorage.credit = res.data.credit;localStorage.credit_to_money = res.data.credit_to_money;sessionStorage.removeItem('token');sessionStorage.removeItem('username');sessionStorage.removeItem('id');sessionStorage.removeItem('credit');sessionStorage.removeItem('credit_to_money');}else {sessionStorage.token = res.data.token;sessionStorage.username = res.data.username;sessionStorage.id = res.data.id;sessionStorage.credit = res.data.credit;sessionStorage.credit_to_money = res.data.credit_to_money;localStorage.removeItem('token');localStorage.removeItem('username');localStorage.removeItem('id');localStorage.removeItem('credit');localStorage.removeItem('credit_to_money');}this.$confirm('下一步想去哪消费!', '提示', {confirmButtonText: '去首页',cancelButtonText: '回到上一页',type: 'success'}).then(() => {this.$router.push('/');}).catch(() => {this.$router.go(-1);});}).catch((error)=>{this.$alert('用户名或者密码错误', '登录失败', {confirmButtonText: '确定',});})}});captcha1.show(); // 显示验证码}
...

4.用户可以设置抵扣积分

在用户购买课程进入计算页面时把积分显示并让用户可以设置要抵扣的积分金额

Orde.vue

<template><div class="cart"><Vheader/><div class="cart-info"><h3 class="cart-top">购物车结算 <span>共1门课程</span></h3><div class="cart-title"><el-row><el-col :span="2">&nbsp;</el-col><el-col :span="10">课程</el-col><el-col :span="8">有效期</el-col><el-col :span="4">价格</el-col></el-row></div><div class="cart-item" v-for="(course,index) in course_list"><el-row><el-col :span="2" class="checkbox">&nbsp;&nbsp;</el-col><el-col :span="10" class="course-info"><img :src="course.course_img" alt=""><span>{{course.name}}</span></el-col><el-col :span="8"><span>{{course.expire_text}}</span></el-col><el-col :span="4" class="course-price">¥{{course.real_price}}</el-col></el-row></div><div class="discount"><div id="accordion"><div class="coupon-box"><div class="icon-box"><span class="select-coupon">使用优惠劵:</span><a class="select-icon unselect" :class="use_coupon?'is_selected':''" @click="use_coupon=!use_coupon"><img class="sign is_show_select" src="../../static/img/12.png" alt=""></a><span class="coupon-num">有{{coupon_list.length}}张可用</span></div><p class="sum-price-wrap">商品总金额:<span class="sum-price">0.00元</span></p></div><div id="collapseOne" v-if="use_coupon"><ul class="coupon-list"  v-if="coupon_list.length>0"><li class="coupon-item" :class="select_coupon(index,coupon.id)" v-for="(coupon,index) in coupon_list" @click="change_coupon(index,coupon.id)"><p class="coupon-name">{{coupon.coupon.name}}</p><p class="coupon-condition">满{{coupon.coupon.condition}}元可以使用</p><p class="coupon-time start_time">开始时间:{{coupon.start_time.replace('T',' ')}}</p><p class="coupon-time end_time">过期时间:{{coupon.end_time.replace('T',' ')}}</p></li></ul><div class="no-coupon" v-if="coupon_list.length<1"><span class="no-coupon-tips">暂无可用优惠券</span></div></div></div><div class="credit-box"><label class="my_el_check_box"><el-checkbox class="my_el_checkbox" v-model="use_credit"></el-checkbox></label><p class="discount-num1" v-if="!use_credit">使用我的贝里</p><p class="discount-num2" v-else><span>总积分:{{credit}},<el-input-number v-model="num" @change="handleChange" :min="0" :max="max_credit()" label="描述文字"></el-input-number>,已抵扣 ¥{{num / credit_to_money}},本次花费{{num}}积分</span></p></div><p class="sun-coupon-num">优惠券抵扣:<span>0.00元</span></p></div><div class="calc"><el-row class="pay-row"><el-col :span="4" class="pay-col"><span class="pay-text">支付方式:</span></el-col><el-col :span="8"><span class="alipay"  v-if="pay_type===0"><img src="../../static/img/alipay2.png"  alt=""></span><span class="alipay" @click="pay_type=0"  v-else><img src="../../static/img/alipay.png" alt=""></span><span class="alipay wechat" v-if="pay_type===1"><img src="../../static/img/wechat2.png" alt="" ></span><span class="alipay wechat"  @click="pay_type=1" v-else><img src="../../static/img/wechat.png" alt=""></span></el-col><el-col :span="8" class="count">实付款: <span>¥{{ (total_price - num/credit_to_money).toFixed(2)}}</span></el-col><el-col :span="4" class="cart-pay"><span @click="payhander">支付</span></el-col></el-row></div></div><Footer/></div>
</template><script>import Vheader from "./common/Vheader"import Footer from "./common/Footer"export default {name:"Order",data(){return {id: localStorage.id || sessionStorage.id,order_id:sessionStorage.order_id || null,course_list: [],coupon_list: [],total_price: 0,  //加上优惠券和积分计算之后的真实总价total_real_price: 0,pay_type:0,num:0,current_coupon:0, // 当前选中的优惠券iduse_coupon:false,use_credit:false,coupon_obj:{},  // 当前coupon对象  {}credit:0,  // 用户剩余积分credit_to_money:0,  //积分兑换比例}},components:{Vheader,Footer,},watch:{use_coupon(){if (this.use_coupon === false){this.current_coupon = 0;}},//当选中的优惠券发生变化时,重新计算总价current_coupon(){this.cal_total_price();}},created(){this.get_order_data();this.get_user_coupon();this.get_credit();},methods: {max_credit(){let a = parseFloat(this.total_price) * parseFloat(this.credit_to_money);if (this.credit >= a){return a}else {return parseFloat(this.credit)}},get_credit(){this.credit = localStorage.getItem('credit') || sessionStorage.getItem('credit')this.credit_to_money = localStorage.getItem('credit_to_money') || sessionStorage.getItem('credit_to_money')},handleChange(value){if (!value){this.num = 0}console.log(value);},cal_total_price(){if (this.current_coupon !== 0){let tt = this.total_real_price;let sales = this.coupon_obj.coupon.sale;let d = parseFloat(this.coupon_obj.coupon.sale.substr(1));if (sales[0] === '-'){tt = this.total_real_price - d// this.total_real_price -= d}else if (sales[0] === '*'){// this.total_real_price *= dtt = this.total_real_price * d}this.total_price = tt;}},// 记录切换的couponidchange_coupon(index,coupon_id){let current_c = this.coupon_list[index]if (this.total_real_price < current_c.coupon.condition){return false}let current_time = new Date() / 1000;let s_time = new Date(current_c.start_time) / 1000let e_time = new Date(current_c.end_time) / 1000if (current_time < s_time || current_time > e_time){return false}this.current_coupon = coupon_id;this.coupon_obj = current_c;},select_coupon(index,coupon_id){//      {//     "id": 2,//     "start_time": "2020-11-10T09:03:00",//     "coupon": {//         "name": "五十元优惠券",//         "coupon_type": 1,//         "timer": 30,//         "condition": 50,//         "sale": "-50"//     },//     "end_time": "2020-12-10T09:03:00"// },let current_c = this.coupon_list[index]if (this.total_real_price < current_c.coupon.condition){return 'disable'}let current_time = new Date() / 1000;let s_time = new Date(current_c.start_time) / 1000let e_time = new Date(current_c.end_time) / 1000if (current_time < s_time || current_time > e_time){return 'disable'}if (this.current_coupon === coupon_id){return 'active'}return ''},get_order_data(){let token = localStorage.token || sessionStorage.token;this.$axios.get(`${this.$settings.Host}/cart/expires/`,{headers:{'Authorization':'jwt ' + token}}).then((res)=>{this.course_list = res.data.data;this.total_real_price = res.data.total_real_price;this.total_price = res.data.total_real_price;})},get_user_coupon(){let token = localStorage.token || sessionStorage.token;this.$axios.get(`${this.$settings.Host}/coupon/list/`,{headers:{'Authorization':'jwt ' + token}}).then((res)=>{this.coupon_list = res.data;}).catch((error)=>{this.$message.error('优惠券获取错误')})},// 支付payhander(){let token = localStorage.token || sessionStorage.token;this.$axios.post(`${this.$settings.Host}/order/add_money/`,{"pay_type":this.pay_type,"coupon":this.current_coupon,"credit":this.num,},{headers:{'Authorization':'jwt ' + token}}).then((res)=>{this.$message.success('订单已经生成,马上跳转支付页面')let order_number = res.data.order_numberlet token = localStorage.token || sessionStorage.token;this.$axios.get(`${this.$settings.Host}/payment/alipay/?order_number=${order_number}`,{headers:{'Authorization':'jwt ' + token}}).then((res)=>{// res.data :  alipay.trade...?a=1&b=2....location.href = res.data.url;})}).catch((error)=>{this.$message.error(error.response.data.msg);})}}}
</script><style scoped>.coupon-box{text-align: left;padding-bottom: 22px;padding-left:30px;border-bottom: 1px solid #e8e8e8;
}
.coupon-box::after{content: "";display: block;clear: both;
}
.icon-box{float: left;
}
.icon-box .select-coupon{float: left;color: #666;font-size: 16px;
}
.icon-box::after{content:"";clear:both;display: block;
}
.select-icon{width: 20px;height: 20px;float: left;
}
.select-icon img{max-height:100%;max-width: 100%;margin-top: 2px;transform: rotate(-90deg);transition: transform .5s;
}
.is_show_select{transform: rotate(0deg)!important;
}
.coupon-num{height: 22px;line-height: 22px;padding: 0 5px;text-align: center;font-size: 12px;float: left;color: #fff;letter-spacing: .27px;background: #fa6240;border-radius: 2px;margin-left: 20px;
}
.sum-price-wrap{float: right;font-size: 16px;color: #4a4a4a;margin-right: 45px;
}
.sum-price-wrap .sum-price{font-size: 18px;color: #fa6240;
}.no-coupon{text-align: center;width: 100%;padding: 50px 0px;align-items: center;justify-content: center; /* 文本两端对其 */border-bottom: 1px solid rgb(232, 232, 232);
}
.no-coupon-tips{font-size: 16px;color: #9b9b9b;
}
.credit-box{height: 30px;margin-top: 40px;display: flex;align-items: center;justify-content: flex-end
}
.my_el_check_box{position: relative;
}
.my_el_checkbox{margin-right: 10px;width: 16px;height: 16px;
}
.discount{overflow: hidden;
}
.discount-num1{color: #9b9b9b;font-size: 16px;margin-right: 45px;
}
.discount-num2{margin-right: 45px;font-size: 16px;color: #4a4a4a;
}
.sun-coupon-num{margin-right: 45px;margin-bottom:43px;margin-top: 40px;font-size: 16px;color: #4a4a4a;display: inline-block;float: right;
}
.sun-coupon-num span{font-size: 18px;color: #fa6240;
}
.coupon-list{margin: 20px 0;
}
.coupon-list::after{display: block;content:"";clear: both;
}
.coupon-item{float: left;margin: 15px 8px;width: 180px;height: 100px;padding: 5px;background-color: #fa3030;cursor: pointer;
}
.coupon-list .active{background-color: #fa9000;
}
.coupon-list .disable{cursor: not-allowed;background-color: #fa6060;
}
.coupon-condition{font-size: 12px;text-align: center;color: #fff;
}
.coupon-name{color: #fff;font-size: 24px;text-align: center;
}
.coupon-time{text-align: left;color: #fff;font-size: 12px;
}
.unselect{margin-left: 0px;transform: rotate(-90deg);
}
.is_selected{transform: rotate(-1turn)!important;
}.coupon-item p{margin: 0;padding: 0;}.cart{margin-top: 80px;
}
.cart-info{overflow: hidden;width: 1200px;margin: auto;
}
.cart-top{font-size: 18px;color: #666;margin: 25px 0;font-weight: normal;
}
.cart-top span{font-size: 12px;color: #d0d0d0;display: inline-block;
}
.cart-title{background: #F7F7F7;height: 70px;
}
.calc{margin-top: 25px;margin-bottom: 40px;
}.calc .count{text-align: right;margin-right: 10px;vertical-align: middle;
}
.calc .count span{font-size: 36px;color: #333;
}
.calc .cart-pay{margin-top: 5px;width: 110px;height: 38px;outline: none;border: none;color: #fff;line-height: 38px;background: #ffc210;border-radius: 4px;font-size: 16px;text-align: center;cursor: pointer;
}
.cart-item{height: 120px;line-height: 120px;margin-bottom: 30px;
}
.course-info img{width: 175px;height: 115px;margin-right: 35px;vertical-align: middle;
}
.alipay{display: inline-block;height: 48px;
}
.alipay img{height: 100%;width:auto;
}.pay-text{display: block;text-align: right;height: 100%;line-height: 100%;vertical-align: middle;margin-top: 20px;
}
</style>

5.后端抵扣积分接口

在用户确定确认下单时, 在序列化器中计算实付金额时纳入积分抵扣
order/serializers.py

import datetimefrom rest_framework import serializers
from . import models
from django_redis import get_redis_connection
from users.models import User
from course.models import Course
from course.models import CourseExpire
from coupon.models import UserCoupon, Coupon
from django.db import transaction
from lyapi.settings import containsclass OrderModelSerializer(serializers.ModelSerializer):class Meta:model = models.Orderfields = ['id', 'order_number', 'pay_type', 'coupon', 'credit']extra_kwargs = {'id':{'read_only':True},'order_number':{'read_only':True},'pay_type':{'write_only':True},'coupon':{'write_only':True},'credit':{'write_only':True},}def validate(self, attrs):# 支付方式pay_type = int(attrs.get('pay_type',0))  #if pay_type not in [i[0] for i in models.Order.pay_choices]:raise serializers.ValidationError('支付方式不对!')# 优惠券校验coupon_id = attrs.get('coupon', 0)if coupon_id > 0:try:user_conpon_obj = UserCoupon.objects.get(id=coupon_id)except:raise serializers.ValidationError('订单创建失败,优惠券id不对')# condition = user_conpon_obj.coupon.conditionnow = datetime.datetime.now().timestamp()start_time = user_conpon_obj.start_time.timestamp()end_time = user_conpon_obj.end_time.timestamp()if now < start_time or now > end_time:raise serializers.ValidationError('订单创建失败,优惠券不在使用范围内,滚犊子')# 积分上限校验credit = attrs.get('credit')user_credit = self.context['request'].user.creditif credit > user_credit:raise serializers.ValidationError('积分超上限了,别乱搞')return attrsdef create(self, validated_data):try:# 生成订单号  [日期,用户id,自增数据]current_time = datetime.datetime.now()now = current_time.strftime('%Y%m%d%H%M%S')user_id = self.context['request'].user.idconn = get_redis_connection('cart')num = conn.incr('num')order_number = now + "%06d" % user_id + "%06d" % numtotal_price = 0  # 总原价total_real_price = 0  # 总真实价格with transaction.atomic():  # 添加事务sid = transaction.savepoint()  # 创建事务保存点# 生成订单order_obj = models.Order.objects.create(**{'order_title': '31期订单','total_price': 0,'real_price': 0,'order_number': order_number,'order_status': 0,'pay_type': validated_data.get('pay_type', 0),'credit': 0,'coupon': 0,'order_desc': '女朋友','pay_time': current_time,'user_id': user_id,# 'user':user_obj,})select_list = conn.smembers('selected_cart_%s' % user_id)ret = conn.hgetall('cart_%s' % user_id)  # dict {b'1': b'0', b'2': b'0'}for cid, eid in ret.items():expire_id = int(eid.decode('utf-8'))if cid in select_list:course_id = int(cid.decode('utf-8'))course_obj = Course.objects.get(id=course_id)# expire_text = '永久有效'if expire_id > 0:expire_text = CourseExpire.objects.get(id=expire_id).expire_text# 生成订单详情models.OrderDetail.objects.create(**{'order': order_obj,'course': course_obj,'expire': expire_id,'price': course_obj.price,'real_price': course_obj.real_price(expire_id),'discount_name': course_obj.discount_name(),})total_price += course_obj.pricetotal_real_price += course_obj.real_price(expire_id)coupon_id = validated_data.get('coupon')# condition = 100# if coupon_id > 0:try:user_conpon_obj = UserCoupon.objects.get(id=coupon_id)except:transaction.savepoint_rollback(sid)raise serializers.ValidationError('订单创建失败,优惠券id不对')condition = user_conpon_obj.coupon.conditionif total_real_price < condition:transaction.savepoint_rollback(sid)raise serializers.ValidationError('订单创建失败,优惠券不满足使用条件')sale = user_conpon_obj.coupon.saleif sale[0] == '-':total_real_price -= float(sale[1:])elif sale[0] == '*':total_real_price *= float(sale[1:])order_obj.coupon = coupon_id# 积分判断credit = float(validated_data.get('credit',0))if credit > contains.CREDIT_MONEY * total_real_price:transaction.savepoint_rollback(sid)raise serializers.ValidationError('使用积分超过了上线,别高事情')# 积分计算total_real_price -= credit / contains.CREDIT_MONEYorder_obj.credit = creditorder_obj.total_price = total_priceorder_obj.real_price = total_real_priceorder_obj.save()# 结算成功之后,再清除# conn = get_redis_connection('cart')# conn.delete('selected_cart_%s' % user_id)# print('xxxxx')except Exception:raise models.Order.DoesNotExist# order_obj.order_number = order_numberreturn order_obj

二、发起支付

支付宝开发平台
https://open.alipay.com/platform/home.htm

1.沙箱环境

  • 是支付宝提供给开发者的模拟支付的环境

  • 沙箱环境跟真实环境是分开的,项目上线时必须切换对应的配置服务器地址和开发者ID和密钥。

  • 沙箱账号:https://openhome.alipay.com/platform/appDaily.htm?tab=account

      真实的支付宝网关:   https://openapi.alipay.com/gateway.do沙箱的支付宝网关:   https://openapi.alipaydev.com/gateway.do
    

2.支付宝开发者文档

文档主页:https://openhome.alipay.com/developmentDocument.htm
产品介绍:https://docs.open.alipay.com/270

3.开发支付功能

cd lyapi/apps
python ../../manage.py startapp payment

注册子应用

INSTALLED_APPS = [...'payment',
]

4.配置秘钥

(1)生成应用的私钥和公钥

下载对应系统的秘钥生成工具: https://doc.open.alipay.com/docs/doc.htm?treeId=291&articleId=105971&docType=1

windows操作系统

生成如下,安装软件时需要管理员身份来安装.

Linux系统

生成如下:

openssl
OpenSSL> genrsa -out app_private_key.pem 2048                         # 生成私钥到指定文件中
OpenSSL> rsa -in app_private_key.pem -pubout -out app_public_key.pem  # 导出公钥
OpenSSL> exit

把软件生成的应用公钥复制粘贴到支付宝网站页面中.
点击修改以后,粘贴进去生成支付宝公钥。

(2)保存应用私钥文件

在payment应用中新建keys目录,用来保存秘钥文件。
将应用私钥文件app_private_key.pem复制到payment/keys目录下。
windows系统生成的私钥必须在上下两行加上以下标识:

-----BEGIN RSA PRIVATE KEY-----
私钥
-----END RSA PRIVATE KEY-----

(3)保存支付宝公钥到项目中

在payment/key目录下新建alipay_public_key.pem文件,用于保存支付宝的公钥文件。
将支付宝的公钥内容复制到alipay_public_key.pem文件中

-----BEGIN PUBLIC KEY-----
公钥
-----END PUBLIC KEY-----

(4)使用支付宝的sdk开发支付接口

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

5.后端提供发起支付的接口url地址

总urls.py

...path(r'payment/',include('payment.urls')),
...

payment/urls.py

from django.urls import path,re_path
from . import viewsurlpatterns = [path('alipay/',views.AlipayView.as_view(),),path('result/',views.AlipayResultView.as_view(),)]

payment/views.py

from django.shortcuts import render
import datetime
from rest_framework.views import APIView
# Create your views here.
from alipay import AliPay, DCAliPay, ISVAliPay
from alipay.utils import AliPayConfig
from django.conf import settings
from rest_framework.response import Response
from order.models import Order
from users.models import User, UserCourse
from course.models import CourseExpire
from rest_framework import status
from coupon.models import UserCoupon
from rest_framework.permissions import IsAuthenticated
from django.db import transaction
from django_redis import get_redis_connection
import logginglogger = logging.getLogger('django')class AlipayView(APIView):permission_classes = [IsAuthenticated, ]def get(self,request):order_number = request.query_params.get('order_number')order_obj = Order.objects.get(order_number=order_number)alipay = AliPay(appid=settings.ALIAPY_CONFIG['appid'],app_notify_url=None,  # 默认回调urlapp_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(),sign_type=settings.ALIAPY_CONFIG['sign_type'],  # RSA 或者 RSA2debug = settings.ALIAPY_CONFIG['debug'],  # 默认False)order_string = alipay.api_alipay_trade_page_pay(out_trade_no=order_obj.order_number,total_amount=float(order_obj.real_price),subject=order_obj.order_title,return_url=settings.ALIAPY_CONFIG['return_url'],notify_url=settings.ALIAPY_CONFIG['notify_url'] # 可选, 不填则使用默认notify url)url = settings.ALIAPY_CONFIG['gateway_url'] + order_stringreturn Response({'url': url})class AlipayResultView(APIView):permission_classes = [IsAuthenticated, ]def get(self,request):alipay = AliPay(appid=settings.ALIAPY_CONFIG['appid'],app_notify_url=None,  # 默认回调urlapp_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(),sign_type=settings.ALIAPY_CONFIG['sign_type'],  # RSA 或者 RSA2debug=settings.ALIAPY_CONFIG['debug'],  # 默认False)# 校验支付宝响应数据data = request.query_params.dict()out_trade_no = data.get('out_trade_no')sign = data.pop('sign')success = alipay.verify(data,sign)print('status>>>',success)if not success:logger.error('%s,支付宝响应数据校验失败' % out_trade_no)return Response('支付宝响应数据校验失败',status=status.HTTP_400_BAD_REQUEST)res_data = self.change_order_status(data)#  响应结果return Response({'msg':'这一脚没毛病','data':res_data})def post(self,request):alipay = AliPay(appid=settings.ALIAPY_CONFIG['appid'],app_notify_url=None,  # 默认回调urlapp_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(),sign_type=settings.ALIAPY_CONFIG['sign_type'],  # RSA 或者 RSA2debug=settings.ALIAPY_CONFIG['debug'],  # 默认False)# 校验支付宝响应数据data = request.data.dict()sign = data.pop('sign')success = alipay.verify(data,sign)if success and data["trade_status"] in ("TRADE_SUCCESS", "TRADE_FINISHED"):self.change_order_status(data)return Response('success')def change_order_status(self,data):with transaction.atomic():out_trade_no = data.get('out_trade_no')trade_no = data.get('trade_no')# 修改订单状态# try:order_obj = Order.objects.get(order_number=out_trade_no)order_obj.order_status = 1order_obj.save()# except Exception as e:# e 如何获取错误信息文本内容# return Response({'msg':'订单生成失败,没有找到该订单'},status=status.HTTP_400_BAD_REQUEST)# 修改优惠券的使用状态print('order_obj.coupon', order_obj.coupon)if order_obj.coupon > 0:user_coupon_obj = UserCoupon.objects.get(is_use=False, id=order_obj.coupon)user_coupon_obj.is_use = Trueuser_coupon_obj.save()# 扣积分use_credit = order_obj.creditself.request.user.credit -= use_creditself.request.user.save()# 保存支付宝的交易流水号(购买记录表)order_detail_objs = order_obj.order_courses.all()now = datetime.datetime.now()conn = get_redis_connection('cart')pipe = conn.pipeline()pipe.delete('selected_cart_%s' % self.request.user.id)res_data = {'pay_time': now,'course_list': [],'total_real_price': order_obj.real_price,}for order_detail in order_detail_objs:course = order_detail.coursecourse.students += 1course.save()res_data['course_list'].append(course.name)expire_id = order_detail.expireif expire_id > 0:expire_obj = CourseExpire.objects.get(id=expire_id)expire_time = expire_obj.expire_timeout_time = now + datetime.timedelta(days=expire_time)else:out_time = NoneUserCourse.objects.create(**{'user':self.request.user,'course':course,'trade_no':trade_no,'buy_type':1,'pay_time':now,'out_time':out_time,})# 购物车redis数据删除pipe.hdel('cart_%s' % self.request.user.id, course.id)pipe.execute()return res_data

Order.vue

...payhander(){let token = localStorage.token || sessionStorage.token;this.$axios.post(`${this.$settings.Host}/order/add_money/`,{"pay_type":this.pay_type,"coupon":this.current_coupon,"credit":this.num,},{headers:{'Authorization':'jwt ' + token}}).then((res)=>{this.$message.success('订单已经生成,马上跳转支付页面')let order_number = res.data.order_numberlet token = localStorage.token || sessionStorage.token;this.$axios.get(`${this.$settings.Host}/payment/alipay/?order_number=${order_number}`,{headers:{'Authorization':'jwt ' + token}}).then((res)=>{// res.data :  alipay.trade...?a=1&b=2....location.href = res.data.url;})}).catch((error)=>{this.$message.error(error.response.data.msg);})}
...

settings/dev.py

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

luffcc项目-13-积分抵扣、发起支付、相关推荐

  1. 快手小程序、网红探店小程序、多商户版(裂变分销+商家核验+集字卡片活动+积分抵扣)

    软件架构 - 前端开源 前端 uniapp.(uView ui框架)后端 TP6.0 + VUE + SWOOLE +Redis 功能说明 1.前后端分离   2.多商户管理   3.独立商家后台   ...

  2. 【项目】关于杉德支付接口对接

    文章目录 前言 对接杉德的一键快捷支付 杉德的商家中心 代码 问题 参考文献 前言 该支付就是调用他们的支付页面,绑卡无需我们操作,所有支付操作都有他们控制.对接的支付是,一键快捷支付,参考的文档是他 ...

  3. 下单购买商品启用积分抵扣功能

    启用模块 登录 后台,左侧菜单 --> 工厂设置 --> 模块管理,找到 "积分模块" ,启用后 F5 刷新页面,将能看到积分抵扣的菜单: 积分抵扣 创建积分抵扣规则 ...

  4. 支付+电商双系统项目笔记(七)支付系统:支付宝支付开发

    目录 一.支付系统介绍 二.代码解析 1.支付宝支付参数配置 2.controller类 3.service类 4.dao类 三.支付演示 一.支付系统介绍 该支付系统实现了支付宝的网站支付功能(微信 ...

  5. Payment:微信支付发起支付请求文档

    文档更新太慢,自己都忍不住要抱怨了.可能越来越慢了 Payment 3.0 微信的配置设置文档请 点击这里 项目GitHub地址:https://github.com/helei112g/paymen ...

  6. 支付宝和微信的JSSDK发起支付

    支付宝: 引入alipay的jsapi文件: <script src="https://a.alipayobjects.com/g/h5-lib/alipayjsapi/3.0.6/a ...

  7. 支付时报错java.lang.RuntimeException: 【微信统一支付】发起支付, returnCode != SUCCESS, returnMsg = appid和mch_id不匹配

    1.问题 Hibernate: select ordermaste0_.order_id as order_id1_1_0_, ordermaste0_.buyer_address as buyer_ ...

  8. ecmall购物获积分功能 积分抵扣设置 积分购物

    积分换购插件说明: 1. 管理员可以在后台设置积分功能的开启和关闭,关闭则网站不开启积分功能,反之,则启用积分功能.   2. 开启积分功能后,网站管理员需要设置一个积分比率,即积分和金币的兑换比率, ...

  9. payjs 源码_WordPress插件:Payjs For Ponits基于Payjs开发的积分充值微信支付插件

    前言 目前市面上能够安全靠谱使用的支付方案并不多,payjs就是其中极佳的一家,对于个人开发者也比较友好,正好在有赞停止新用户接入支付,云落将之前开发的支付插件改为payjs支付,其他的变化不大的 我 ...

最新文章

  1. Java 对象锁和类锁全面解析
  2. 网络协议枯燥难学?这个胖子要说No!
  3. Hibernate 一对一、一对多、多对多注解cascade属性的总结
  4. C语言建立有向图的邻接表及其遍历操作
  5. service worker之cache实践--sw-precache
  6. 如何用命令行查看服务器型号,服务器查看内存命令行
  7. 论文公式编号右对齐_如何编辑处理论文中的公式
  8. Hivesql-高级进阶技巧
  9. HTML5新增元素之Canvas-实现太极八卦图和扇子
  10. 菜鸟学Linux - 用户与用户组基础
  11. PDF转换成word转换器绿色版
  12. ecshop4.0php,ECSHOP安装教程【ECSHOP4.0安装教程】图解ECSHOP4.0安装教程流程和步骤-ECSHOP教程网...
  13. 高中数学40分怎么办_高中数学40分怎么办?
  14. Windows系统拦截广告弹窗
  15. 股票配对交易策略-最小距离法
  16. 采用面向对象的方法来实现留言板的添加和删除功能
  17. SVN Cleanup的意思
  18. easyexcel已存在的excel里追加数据
  19. php读取西门子plc_西门子PLC读取/修改V90 PN参数
  20. 通俗的解释卡尔曼滤波(Kalman Filter)以及其Python的实现

热门文章

  1. AxureRP9 中继器的简单使用
  2. 高数---曲线积分和曲面积分
  3. java根据开始日期和结束日期计算天数
  4. 有什么好用的低代码快速开发平台?
  5. kubernetes搭建dashboard-v1.10.1
  6. QQ群反向昵称、恶搞昵称的原理[附]
  7. 知识图谱-现代知识表示理论
  8. 教你写博客 快给俺点赞
  9. 服务器上蓝色常亮灯是干什么的功能作用
  10. ESP32学习笔记(5)——WiFi接口使用(STA和AP模式)