保存支付结果
用户支付成功后,支付宝会将用户重定向到http://www.meiduo.site:8080/pay_success.html,并携带支付结果数据
前端页面将此数据发送给后端,后端检验并保存支付结果
1. 后端接口设计
请求方式: PUT /payment/status/?支付宝参数
请求参数: 查询字符串参数, 见上面表格
返回数据: JSON
返回值 | 类型 | 是否必须 | 说明 |
---|---|---|---|
trade_id | str | 否 | 支付宝流水号 |
2. 后端实现
在payment/views.py中创建视图
class PaymentStatusView(APIView):
"""
支付结果
"""
permission_classes = (IsAuthenticated,)
def put(self, request):
data = request.query_params.dict()
signature = data.pop("sign")
alipay = AliPay(
appid=settings.ALIPAY_APPID,
app_notify_url=None, # 默认回调url
app_private_key_path=os.path.join(os.path.dirname(os.path.abspath(__file__)), "keys/app_private_key.pem"),
alipay_public_key_path=os.path.join(os.path.dirname(os.path.abspath(__file__)),
"keys/alipay_public_key.pem"), # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥,
sign_type="RSA2", # RSA 或者 RSA2
debug=settings.ALIPAY_DEBUG # 默认False
)
success = alipay.verify(data, signature)
if not success:
return Response({'message': '非法请求'}, status=status.HTTP_403_FORBIDDEN)
# 获取订单编号和支付宝流水号
order_id = req_data.get('out_trade_no')
trade_id = req_data.get('trade_no')
# 校验订单id(order_id)
try:
order = OrderInfo.objects.get(
order_id=order_id,
user=request.user,
status=OrderInfo.ORDER_STATUS_ENUM['UNPAID']
)
except OrderInfo.DoesNotExist:
return Response({'message': '订单信息有误'}, status=status.HTTP_400_BAD_REQUEST)
# 添加支付记录
Payment.objects.create(
order_id=order_id,
trade_id=trade_id
)
# 更新订单的支付状态
order.status = OrderInfo.ORDER_STATUS_ENUM['UNSEND']
order.save()
return Response({'trade_id': trade_id})
3. 前端实现
创建pay_success.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>美多商城-支付成功</title>
<link rel="stylesheet" type="text/css" href="css/reset.css">
<link rel="stylesheet" type="text/css" href="css/main.css">
<script type="text/javascript" src="js/host.js"></script>
<script type="text/javascript" src="js/vue-2.5.16.js"></script>
<script type="text/javascript" src="js/axios-0.18.0.min.js"></script>
</head>
<body>
<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="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="common_list_con clearfix">
<div class="order_success">
<p><b>订单支付成功</b></p>
<p>您的订单已成功支付,支付交易号:{{trade_id}}</p>
<p><a href="/user_center_order.html">您可以在用户中心中我的订单中查看该订单</a></p>
</div>
</div>
<div class="footer">
<div class="foot_link">
<a href="#">关于我们</a>
<span>|</span>
<a href="#">联系我们</a>
<span>|</span>
<a href="#">招聘人才</a>
<span>|</span>
<a href="#">友情链接</a>
</div>
<p>CopyRight © 2016 北京美多商业股份有限公司 All Rights Reserved</p>
<p>电话:010-****888 京ICP备*******8号</p>
</div>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
host,
trade_id: '',
username: sessionStorage.username || localStorage.username,
token: sessionStorage.token || localStorage.token,
},
mounted: function(){
axios.put(this.host+'/payment/status/'+document.location.search,{}, {
responseType: 'json',
headers:{
'Authorization': 'JWT ' + this.token
},
})
.then(response => {
this.trade_id = response.data.trade_id;
})
.catch(error => {
console.log(error.response);
})
}
})
</script>
</body>
</html>