Django实现支付宝沙箱操作
Django实现支付宝沙箱操作
环境即所需模块
-
Django == 3.1.0
-
python == 3.7.4
-
python-alipay-sdk=2.0.1
所需
- 下载模块 python-alipay-sdk=2.0.1
- 文档 非官方支付宝 Python SDK: https://github.com/fzlee/alipay/blob/master/README.zh-hans.md#alipay.trade.page.pay
沙箱环境配置
-
在支付宝开放平台---->开发者中心—>开发服务---->沙箱
-
RSA2密钥生成并上传 参考官方地址:https://opendocs.alipay.com/open/291/105971
-
下载支付宝开放平台开发助手
- 下载地址https://opendocs.alipay.com/open/291/introduce
- 下载后生成秘钥
- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iAJ4s57z-1602600230093)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20201013215751437.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RLkaGka3-1602600315452)(C:%5CUsers%5CASUS%5CAppData%5CRoaming%5CTypora%5Ctypora-user-images%5Cimage-20201013215646909.png#pic_center)]
)
4.将应用公钥复制到支付宝中
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pm1umRDQ-1602600230099)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20201013220238000.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xIM2Wwqr-1602600230101)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20201013220309533.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CZRSx4tY-1602600230104)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20201013220359867.png)]
5.配置app中支付宝公钥 开发助手秘钥
- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hzEeNDd6-1602600230107)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20201013220610210.png)]
- 在Django的app中创建文件夹置放支付宝公钥[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Bg9hMEFa-1602600230111)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20201013221108217.png)]
- 在Django的app中创建文件夹置放开放平台私钥[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0aGqpG4B-1602600230112)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20201013221548593.png)]
Django Models
# 支付状态表
class Status(BaseModel):
name = models.CharField(max_length=32)
class Meta:
db_table = 'status'
# 支付表
class Order(BaseModel):
out_trade_no = models.CharField(max_length=60)
trada_no = models.CharField(max_length=60, null=True, blank=True)
goods = models.ForeignKey(Goods, on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.CASCADE)
goods_num = models.IntegerField()
status = models.ForeignKey(Status, on_delete=models.CASCADE)
class Meta:
db_table = 'order'
Django Views配置
-
所需的包
import uuid import redis from app01.views import login_serializer from alipay import AliPay, AliPayConfig
# 绝对路径打开文件 {}代表从这里往前 app_private_key_string = open('{}\\app02\\alipay_key\\app_private_key'.format(settings.BASE_DIR)).read() alipay_public_key_string = open('{}\\app02\\alipay_key\\alipay_public'.format(settings.BASE_DIR)).read()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TU8ck5hJ-1602600230116)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20201013222520219.png)]
alipay = AliPay( appid="2016102500759596", app_notify_url=None, # 默认回调url app_private_key_string=app_private_key_string, # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥, alipay_public_key_string=alipay_public_key_string, sign_type="RSA2", # RSA 或者 RSA2 debug=True, # 默认False config=AliPayConfig(timeout=15) # 可选, 请求超时时间 )
3.注释的代码可以去掉
# 支付 class AlipayView(APIView): def post(self, request): # print(request.data) token = request.data.get('token') count = request.data.get('count') goods_info = request.data.get('goods_info') # print(goods_info) # 订单号 uuid唯一不重复 out_trade_no = str(uuid.uuid4()) # 订单金额初始 total_amount = 0 user_info = login_serializer.loads(token) user_id = user_info.get('user_id') # 判断是否是多个id 用,号分割 if goods_info.find(',') != -1: order_list = [] for i in goods_info.split(','): print(i) # 循环输出id # # 获取购物车商品数量 # goods_count = r3.hget(user_id, i).decode() # # get到等于i的商品 # goods_obj = Goods.objects.get(pk=i) # # 计算总价 # total_amount += int(goods_obj.price) * int(goods_count)\ # 列表添加类型 order_list.append(Order( out_trade_no=out_trade_no, goods_id=i, user_id=user_id, goods_num=count, status_id=1, )) print(order_list) # 批量添加 列表 ser = Order.objects.bulk_create(order_list) # ser.save() else: # print(r3.hget(user_id, goods_info)) # goods_count = r3.hget(user_id, goods_info).decode() # goods_obj = Goods.objects.get(pk=goods_info) # total_amount += int(goods_obj.price) * int(goods_count) # print(total_amount) # 单个添加 ser = OrderModelSer(data={ "out_trade_no": out_trade_no, "goods": goods_info, "user": user_id, "goods_num": count, "status": 1 }) if ser.is_valid(): ser.save() else: print(ser.errors) # 主题 subject = "京东" # 电脑网站支付,需要跳转到https://openapi.alipay.com/gateway.do? + order_string order_string = alipay.api_alipay_trade_page_pay( out_trade_no=out_trade_no, total_amount=count, subject=subject, return_url="http://127.0.0.1:8000/app02/callback_alipay", notify_url="http://127.0.0.1:8000/app02/callback_alipay" # 可选, 不填则使用默认notify url ) # 拼接的数据 # print(order_string) pay_url = 'https://openapi.alipaydev.com/gateway.do?' + order_string # 带参数跳转的路由 # print(pay_url) return Response({'pay_url': pay_url, 'msg': 'OK', "code": 200})
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m6WYKp5g-1602600230119)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20201013223018379.png)]
4.0
# 支付完回调地址 class CallBackAlipayView(APIView): def get(self, request): print(request.query_params) print("------------------------------") # 判断是否有数据 if request.query_params.get("sign"): # for i in request.query_params.get("out_trade_no"): # print(request.query_params.get("out_trade_no")) # 获取订单号 queryset = Order.objects.get(out_trade_no=request.query_params.get("out_trade_no")) # 修改订单状态为已购买 局部修改 ser = OrderModelSer(instance=queryset, data={"status": 2}, partial=True) if ser.is_valid(): ser.save() else: print(ser.errors) return Response({'msg': 'OK', "data": request.query_params})
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AFbrRopL-1602600230122)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20201013223126443.png)]
调用接口
addcart() { let data = new FormData(); data.append("token", sessionStorage.getItem("token")) data.append("goods_info", this.check) data.append("count", this.count2) axios({ url: "http://127.0.0.1:8000/app02/alipay", method: 'post', data: data }).then(res => { console.log(res.data) if (res.data.code === 200) { window.location.href = res.data.pay_url } }) },
调用的页面
<template>
<div>
<div id="app">
<div class="header_con">
<div class="header">
<div class="welcome fl">欢迎来到美多商城!</div>
<div class="fr">
<div v-if="username" class="login_btn fl">
欢迎您:<em>{{ username }}</em>
<span>|</span>
<a @click="logout">退出</a>
</div>
<div v-else class="login_btn fl">
<a href="login.html">登录</a>
<span>|</span>
<a href="register.html">注册</a>
</div>
<div class="user_link fl">
<span>|</span>
<a href="user_center_info.html">用户中心</a>
<span>|</span>
<a href="cart.html">我的购物车</a>
<span>|</span>
<a href="user_center_order.html">我的订单</a>
</div>
</div>
</div>
</div>
<div class="search_bar clearfix">
<a href="index.html" class="logo fl"><img src="/static/images/logo.png"></a>
<div class="sub_page_name fl">| 购物车</div>
<form method="get" action="/search.html" class="search_con fr mt40">
<input type="text" class="input_text fl" name="q" placeholder="搜索商品">
<input type="submit" class="input_btn fr" name="" value="搜索">
</form>
</div>
<div class="total_count">全部商品<em>{{cart.length}}</em>件</div>
<ul class="cart_list_th clearfix">
<li class="col01">商品名称</li>
<li class="col03">商品价格</li>
<li class="col04">数量</li>
<li class="col05">小计</li>
<li class="col06">操作</li>
</ul>
<ul class="cart_list_td clearfix" v-for="(sku,index) in cart">
<li class="col01"><input type="checkbox" name="" v-model="check" :value="sku.id"
@click="checkbox(sku.id,sku.count,sku.price)"></li>
<li class="col02"><img :src="'http://127.0.0.1:8000'+sku.img"></li>
<li class="col03">{{ sku.name }}</li>
<li class="col05">{{ sku.price }}元</li>
<li class="col06">
<div class="num_add">
<a @click="on_add(sku.id)" class="add fl">+</a>
<input v-model="sku.count" @focus="origin_input=sku.count" @blur="on_input(index)" type="text"
class="num_show fl">
<a @click="on_minus(sku.id)" class="minus fl">-</a>
</div>
</li>
<li class="col07">{{sku.price * sku.count}}元</li>
<li class="col08"><a @click="del(sku.id)">删除</a></li>
</ul>
<ul class="settlements">
<li class="col01"><input type="checkbox" @click="check_count" v-model="isChecked"></li>
<li class="col02">全选</li>
<li class="col03">合计(不含运费):<span>¥</span><em>{{count2}}</em><br>共计<b>{{total_selected_count}}</b>件商品
</li>
<li class="col04"><a @click="addcart">去结算</a></li>
</ul>
</div>
<fooder></fooder>
</div>
</template>
<script>
import axios from 'axios'
import fooder from '../components/Fooder'
export default {
name: "Cart",
data() {
return {
cart: [
],
check: [],
username: "",
total_selected_amount: "",
total_selected_count: "",
on_selected_all: "",
selected_all: "",
count2: 0,
isChecked: false,
}
},
components: {
'fooder': fooder
},
methods: {
del(goods_id) {
let data = new FormData();
data.append("token", sessionStorage.getItem("token"))
data.append("goods_id", goods_id)
axios({
url: 'http://127.0.0.1:8000/app02/delcart',
method: 'delete',
data: data
}).then(res => {
console.log(res)
this.$router.go(0)
})
},
addcart() {
let data = new FormData();
data.append("token", sessionStorage.getItem("token"))
data.append("goods_info", this.check)
data.append("count", this.count2)
axios({
url: "http://127.0.0.1:8000/app02/alipay",
method: 'post',
data: data
}).then(res => {
console.log(res.data)
if (res.data.code === 200) {
window.location.href = res.data.pay_url
}
})
},
on_add(goods_id) {
let data = new FormData();
data.append("token", sessionStorage.getItem("token"))
data.append("goods_id", goods_id)
axios({
url: 'http://127.0.0.1:8000/app02/addcart',
method: 'post',
data: data
}).then(res => {
console.log(res)
this.$router.go(0)
})
},
on_minus(goods_id) {
let data = new FormData();
data.append("token", sessionStorage.getItem("token"))
data.append("goods_id", goods_id)
axios({
url: 'http://127.0.0.1:8000/app02/minuscart',
method: 'post',
data: data
}).then(res => {
console.log(res)
this.$router.go(0)
})
},
show() {
axios({
url: 'http://127.0.0.1:8000/app02/showcart',
method: 'get',
params: {"token": sessionStorage.getItem("token")}
}).then(res => {
console.log(res)
this.cart = res.data.data
})
},
//全选并调用总价
check_count() {
//默认值为false
this.count2 = 0;
this.check = [];
if (this.isChecked) {
this.check = []
} else {
this.cart.forEach(item => {
console.log(item.id);
this.check.push(item.id);
this.count()
})
}
},
//计算总价
count() {
// let count = 0
this.count2 = 0
for (let i in this.cart) {
console.log(this.cart[i])
this.count2 += this.cart[i].price * this.cart[i].count
}
},
//计算单选框
checkbox(gid, count, price) {
//第一次执行都为空 false
console.log(this.check)
if (this.check.includes(gid)) {
// 包含则说明已经选中 再次点击删除 false 并减去相应的价格
this.count2 -= count * price
this.check.splice(this.check.indexOf(gid), 1)
} else {
//推送 也就是添加 变为true
this.check.push[gid]
//计算总价 选中相加
this.count2 += count * price
}
},
},
created() {
this.show()
}
}
</script>
<style scoped>
</style>
次点击删除 false 并减去相应的价格
this.count2 -= count * price
this.check.splice(this.check.indexOf(gid), 1)
} else {
//推送 也就是添加 变为true
this.check.push[gid]
//计算总价 选中相加
this.count2 += count * price
}
},
},
created() {
this.show()
}
}
</script>
<style scoped>
</style>
本文地址:https://blog.csdn.net/weixin_45954124/article/details/109062783