47 前端支付页面
前台 - 支付生成页面
课程主页或是详情页或者搜索页
<template> ... <span class="buy-now" @click="buy_course(course)">立即购买</span> </template> <script> export default { methods: { // 购买课程 buy_course(course) { // es6语法下,变量必须定义才能使用 let token = this.$cookies.get('token'); if (!token) { this.$message({ message: '请先登录', type: 'warning' }); return false } this.$axios({ url: this.$settings.base_url + '/order/pay/', method: 'post', headers: { authorization: 'luffy ' + token, }, data: { subject: course.name, total_amount: course.price, pay_type: 1, // 现在只能默认1,为支付宝 courses: [course.id] // 后台完成的是基于购物车情况下的接口,所以单购物为群购1个 } }).then(response => { let pay_url = response.data; // console.log(pay_url) // 本页面标签调整:可以选择 _self 或 _blank open(pay_url, '_self'); }).catch(error => { console.log(error.response.data) }) }, } } </script>
或者参考这个(同上)
go_pay(total_amount, course_id) { // cookie中有token值,就是登录了 let token = this.$cookies.get('token') if (token) { this.$axios({ url: this.$settings.base_url + 'order/pay/', method: 'post', headers: { Authorization: 'jwt ' + token, }, data: { 'total_amount': total_amount, 'courses': [course_id,] } }).then(res => { if (res.data.code == 100) { // 跳转到支付页面 location.href = res.data.pay_url } }) // this.$axios.post( // this.$settings.base_url + 'order/pay/', // { // 'total_amount': total_amount, // 'courses': [course_id,] // }, { // headers: { // 'Authorization': 'jwt ' + token // }, // } // ).then(res => { // if (res.data.code == 100) { // // 跳转到支付页面 // location.href = res.data.pay_url // } // }) } else { this.$message({ message: "您没有登录,请先登录", }) } }
前台 - 支付成功的回调页面
router/index.js
import PaySuccess from '../views/PaySuccess.vue' // ... const routes = [ // ... { path: '/pay/success', name: 'pay-success', component: PaySuccess }, ];
同步回调的参数
charset=utf-8& out_trade_no=7f7c7d12d57d45b693e1b49a6b01e1dd& method=alipay.trade.page.pay.return& total_amount=39.00& sign=FUmceqiNMWvxcD%2BUPCHiOTaEwlJ%2FXIXL5UwZWOSI1TwRjPIZVzjRLB4j2G5CQpn472JO8X%2BwMx04dHqjLxqLcY3TRu0XurQ%2FwKTNpyfDrtNuNv0rfGPuVHw52y3blbS7%2FKFVsWryw4%2BBuF2fCrJ4qWH8Zg14Rct7qoMbu73N74WkQtDyzXefiKDbkMMRMfLbelE9TFyeIeygeMId8%2B58mcJMUOh6aQqwpr9bzuBbfJ17fkqU%2F0ys9zGr%2FlDtLL7aAh6BPViqZN%2F9T7byCoferD1BhcSzJNR6V6VuhOdTq8iEaH2XgJT9aIiyHgg3GT1taBBvZX2gK41FSmkguk%2BfsA%3D%3D& trade_no=2020030722001464020500585462& auth_app_id=2016093000631831& version=1.0& app_id=2016093000631831& sign_type=RSA2& seller_id=2088102177958114& timestamp=2020-03-07%2014%3A47%3A48 ` // 同步回调没与订单状态
views/PaySuccess.vue
<template> <div class="pay-success"> <!--如果是单独的页面,就没必要展示导航栏(带有登录的用户)--> <Header/> <div class="main"> <div class="title"> <div class="success-tips"> <p class="tips">您已成功购买 1 门课程!</p> </div> </div> <div class="order-info"> <p class="info"><b>订单号:</b><span>{{ result.out_trade_no }}</span></p> <p class="info"><b>交易号:</b><span>{{ result.trade_no }}</span></p> <p class="info"><b>付款时间:</b><span><span>{{ result.timestamp }}</span></span></p> </div> <div class="study"> <span>立即学习</span> </div> </div> </div> </template> <script> import Header from "@/components/Header" export default { name: "Success", data() { return { result: {}, }; }, created() { // url后拼接的参数:?及后面的所有参数 => ?a=1&b=2 // console.log(location.search); // 解析支付宝回调的url参数 let params = location.search.substring(1); // 去除? => a=1&b=2 let items = params.length ? params.split('&') : []; // ['a=1', 'b=2'] //逐个将每一项添加到args对象中 for (let i = 0; i < items.length; i++) { // 第一次循环a=1,第二次b=2 let k_v = items[i].split('='); // ['a', '1'] //解码操作,因为查询字符串经过编码的 if (k_v.length >= 2) { // url编码反解 let k = decodeURIComponent(k_v[0]); this.result[k] = decodeURIComponent(k_v[1]); // 没有url编码反解 // this.result[k_v[0]] = k_v[1]; } } // 解析后的结果 // console.log(this.result); // 把地址栏上面的支付结果,再get请求转发给后端 this.$axios({ url: this.$settings.base_url + '/order/success/' + location.search, method: 'get', }).then(response => { console.log(response.data); }).catch(() => { console.log('支付结果同步失败'); }) }, components: { Header, } } </script> <style scoped> .main { padding: 60px 0; margin: 0 auto; width: 1200px; background: #fff; } .main .title { display: flex; -ms-flex-align: center; align-items: center; padding: 25px 40px; border-bottom: 1px solid #f2f2f2; } .main .title .success-tips { box-sizing: border-box; } .title img { vertical-align: middle; width: 60px; height: 60px; margin-right: 40px; } .title .success-tips { box-sizing: border-box; } .title .tips { font-size: 26px; color: #000; } .info span { color: #ec6730; } .order-info { padding: 25px 48px; padding-bottom: 15px; border-bottom: 1px solid #f2f2f2; } .order-info p { display: -ms-flexbox; display: flex; margin-bottom: 10px; font-size: 16px; } .order-info p b { font-weight: 400; color: #9d9d9d; white-space: nowrap; } .study { padding: 25px 40px; } .study span { display: block; width: 140px; height: 42px; text-align: center; line-height: 42px; cursor: pointer; background: #ffc210; border-radius: 6px; font-size: 16px; color: #fff; } </style>