Order.vue
<template> <div class="order container"> <header> <i class="iconfont icon-fanhui" @click="$router.back()"></i> <span>提交订单</span> <i class="iconfont icon-kefu"></i> </header> <section> <div class="path"> <h3 class="path-title">收货信息</h3> <div class="path-content" @click="goPath"> <div> <span>{
{ path.name }}</span> <span>{
{ path.tel }}</span> </div> <div> <span>{
{ path.province }}</span> <span>{
{ path.city }}</span> <span>{
{ path.county }}</span> <span>{
{ path.addressDetail }}</span> </div> </div> </div> <div class="payment"> <div class="payment-title">支付方式:</div> <van-radio-group v-model="radioPayment"> <van-radio name="wx">微信支付</van-radio> <van-radio name="ali">支付宝支付</van-radio> </van-radio-group> </div> <div class="goods"> <ul> <li v-for="(item, index) in goodsList" :key="index"> <div> <img :src="item.goods_imgUrl" alt="" /> </div> <div class="goods-content"> <h4>{
{ item.goods_name }}</h4> <div class="goods-total"> <span>¥{
{ item.goods_price }}</span> <span>x{
{ item.goods_num }}</span> </div> </div> </li> </ul> </div> </section> <footer> <div class="order-total"> <span>共</span> <b>{
{ total.num }}</b> <span>件,</span> <span>总金额:</span> <em>¥{
{ total.price }}</em> </div> <div class="order-topay" @click="goPayment">提交订单</div> </footer> </div> </template> <script> import { Toast } from "vant"; import http from "@/common/api/request.js"; import { mapState, mapGetters, mapMutations } from "vuex"; import bus from "@/common/bus.js"; import qs from "qs"; export default { data() { return { radioPayment: "wx", path: {}, item: [], total: { price: 0, num: 0, }, }; }, computed: { ...mapState({ order_id: (state) => state.order.order_id, selectList: (state) => state.cart.selectList, }), ...mapGetters(["defaultPath"]), }, created() { this.goodsList = JSON.parse(this.$route.query.goodsList); this.selectAddress(); }, activated() { bus.$on( "selectPath", function (data) { this.path = JSON.parse(data); }.bind(this) ); ///选中的商品id号 this.item = JSON.parse(this.$route.query.detail); this.goodsList = JSON.parse(this.$route.query.goodsList); this.selectOrder(); }, methods: { ...mapMutations(["initData", "initOrder"]), //查询地址 selectAddress() { http .$axios({ url: "/api/selectAddress", method: "post", headers: { token: true, }, }) .then((res) => { this.initData(res.data); //有默认收货地址 if (this.defaultPath.length) { this.path = this.defaultPath[0]; } else { this.path = res.data[0]; } }); }, ///查询订单 selectOrder() { http .$axios({ url: "/api/selectOrder", method: "post", headers: { token: true, }, data: { orderId: this.order_id, }, }) .then((res) => { this.initOrder(res.data); this.total = { price: res.data[0].goods_price, num: res.data[0].goods_num, }; }); }, //选择收货地址 goPath() { this.$router.push({ path: "/path", query: { type: "select", }, }); }, ///提交订单 goPayment() { ///判断是否选择收货地址 if (!this.path) return Toast("填写收货地址"); //发送请求==》1.修改订单状态2.删除购物车数据 http .$axios({ url: "/api/submitOrder", method: "post", headers: { token: true, }, data: { orderId: this.order_id, shopArr: this.selectList,
},
})
.then((res) => {
let newArr = [];
this.goodsList.forEach((v) => {
newArr.push(v.goods_name);
});
//支付传递的参数
let dataOrder = {
orderId: this.order_id,
name: newArr.join(""),
price: this.total.price,
};
if (res.success) {
//去支付
http
.$axios({
url: "/api/payment",
method: "post",
headers: {
token: true,
"Content-Type": "application/x-www-form-urlencoded",
},
//qs是增加安全性的序列化
data: qs.stringify(dataOrder),
})
.then((res) => {
if (res.success) {
//打开支付宝支付的页面
window.location.href = res.paymentUrl;
}
});
}
});
},
},
};
</script>
<style lang='less' scoped>
header {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
height: 1.173333rem;
color: #fff;
background-color: #b0352f;
i {
padding: 0 0.4rem;
font-size: 0.586666rem;
}
span {
font-weight: 300;
font-size: 0.48rem;
}
}
section {
background-color: #f7f7f7;
.path-title {
padding: 0.4rem;
font-size: 0.48rem;
}
.path-content {
padding: 0.16rem 0.4rem;
font-size: 0.373333rem;
background-color: #ffffff;
span {
padding-right: 0.16rem;
}
}
.payment {
padding: 0.16rem 0.4rem;
margin-top: 0.4rem;
font-size: 0.426666rem;
background-color: #ffffff;
.van-radio-group {
display: flex;
padding: 0.16rem 0;
.van-radio {
padding-right: 0.266666rem;
}
}
}
.goods {
padding: 0.16rem 0.4rem;
margin-top: 0.4rem;
font-size: 0.426666rem;
background-color: #ffffff;
ul {
width: 100%;
li {
display: flex;
width: 100%;
img {
width: 1.973333rem;
height: 1.973333rem;
}
.goods-content {
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
padding-left: 0.4rem;
.goods-total {
display: flex;
justify-content: space-between;
}
}
}
}
}
}
footer {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
height: 1.2rem;
border-top: 1px solid #ccc;
.order-total {
font-size: 0.426666rem;
span {
padding: 0 0.16rem;
}
b {
color: #b0352f;
}
em {
font-size: 0.48rem;
color: #b0352f;
}
}
.order-topay {
width: 3.2rem;
line-height: 1.2rem;
color: #fff;
font-size: 0.426666rem;
text-align: center;
background-color: #b0352f;
}
}
</style>
对接支付宝沙箱(进行支付)nodejs
api链接:https://github.com/alipay/alipay-sdk-nodejs-all
api链接:https://www.yuque.com/chenqiu/alipay-node-sdk/config-sdk
***测试支付,一定要用无痕浏览
后台 db---alipay.js
//引入sdk
const AlipaySdk = require('alipay-sdk').default;
const alipaySdk = new AlipaySdk({
//AppId
appId: '202100011768788888514',
//签名算法
signType:'RSA2',
//支付宝网关
gateway:'https://openapi.alipaydev.com/gateway.do',
//支付宝公钥
alipayPublicKey:'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkel1HVjCXwxoRRHg449wOcFaeLHI7AgZCQZzRx0VPymq1wdunJrRfOxAedbO+JCWi09o9BTy1zHhBsJ2A8dzyhhycOGJDS2gwWrZSrBHyLwqqRJJ7KVNyA1fKydHO7Bi0tJ1pL28jWiSANfklvw9b9kdaAuGAeswRkKHQ7YQeoOM1SVWJygJnKJEyhy5LE06hGUE0VjSBUgepUS/crYuCFi9UvIobqca38y0aqc+bI0I6TvJQ9wqUWpUoV9YNR8jhgOpU7aDuTEEFCvSpaLy0xNwSVTmWeu82MjOaGLNQmrVV4ymOozYgRfdpOcA1QrqyYlEBx9osiYsEAMevnx2bdhwIDAQAB',
//应用私钥
privateKey: 'MIIEowIBAAKCAQEAhk5HSR/+Yd1qtd/x16+7lYYpS7hkvH978Hr8Vo4p9sFGTr3iCAlHZ9ceEuIJZG6mAzJWTo0Nc0tJV889bAhYYgijiAvO5ImvVVtM3WJb//ST9zz3+PuOAezVbPnSuSHsVwsUuXNvPkJRlkKQffiNVHd2YM07nYAwZMt3iTop5R5KaSOlz0TFtOJKBsEsyIDl1Tuhlg33wUCcLm8em9gvu3hApubFBuQq6B/oEhlWPi7Xi0NIYDeKKIQuoaHBXK1E2aI67g2pBKHRbuzv6NuSRzMMhFecNRZAIVweVBqplSKhuSINbUm7p84lgmzTMZXtxpf2ub6mvbPvhnEmdpWNRQIDAQABAoIBAAU5yoBH5Gf+a4atyurEHi7cQZpBzB2MIS9MbpAe2O6tPWjCgG/T55WUdtjNf/gQH3lu7Lq3HLCVwG46AbKO977aXEYEPAixHO27hbz2fnkmuJmu9IrsLmHbt9zPUEabOd3GOiHw5m+I1E1B21bTZDfike01cL+3fJhWQovJdu85+iNWCfLAxcu/Ao55kKOGYdvKv+GGorDRPhlOzh09geqvss6rQE9j00JFqFuIPcA2Unxq5yszB1LGUVOPCYw5eznDDcBLx0N8UgUfpjASRdjJNL+1eezr0v6//J4HZ4VQmzJ2WMu+MmOyUHzYnoYb49Kh79RpSL8BdE/o8Vxb7mR7dwkCgYEAwDwFTgrIB8ouWXsNVkmf7SjUYHUlkYQHnf2o57/2d2pIw50vdhUnZKTmdKhaHh4zVoPLAoad9HWwwkdUQiTpfJD7nAglW4Tsw0kHu0vK2lYp3gjvoMVf1VQwM36r3tCnMyv6Yt3dNU/qXfEbbwJCGIowQdU3hidBfdatgOl8PAsCgYEAstsgS6sbiCiIQfRoznJefpGlrTSXZC0Rsn2DCULsNiwI1uzKHfFx0ZZ9Y04ICKpiWNyu1W43ZB4CGExYZP21xr4oK7jF0UTpIKXzEV63aow4M6mcmJfFVriweuy2BOM/eMhJYn1IXXe0Dl8Uj4B37X70I7JPx4DWTp6RYAnM3e8CgYBg315E/8Xhtw84ZHxKGXwQRV0Q5rfx5rj38xYlA2Wus87LVPDP7sUVQMwpyZTwTIPOe0fYlAIRaSWUIeHiGzvWXDGPZcN9pTSzDKBq0Dz/XiBnFdW8DPrIRE6uBI2UEU3Qyb66B9grv4P5p0EN5fNs7mZ3Jn1+i1XDlmWE6ySCFQKBgQCfulH9QbI0xv3o6P0wYbNCFZCAPpd1P0quvKhpfPq25lx+lLlsRFQBeQRBy04hbwilk3AP635MSwBT8tp+VpYgB3KYmUsQuRn5rjqFKLFk1hTbDn5rSB9Uc1woa32in8/vbe8bpgcacey7aO5TucdgsiAWQQg+gzDgxXvO6PGswQKBgBjP5vXcaz+WVzbY3mBi0B7Cd3G15wKQGpZRDy55WX/BCqlKnG41LJqeADxOPJKbZxHRxOYztR4742nzpNIEPddALV1uN/tNtb3MhpuH8QVvaDlfSqbNKaqaP/jY18QfMbS9q9dTCjoDcSUPzbSorq/4L6TV3pogOnQqqzV5kUkL'
});
module.exports = alipaySdk;
后台接口
index.js
//引入支付宝配置文件 const alipaySdk = require("../db/alipay.js"); const AlipayFormData = require("alipay-sdk/lib/form").default; //引入axiso const axios = require("axios");
//发起支付
router.post("/api/payment", function (req, res, next) {
//订单号
let orderId = req.body.orderId;
//商品总价
let price = req.body.price;
//购买商品的名称
let name = req.body.name;
//开始对接支付宝API
const formData = new AlipayFormData();
// 调用 setMethod 并传入 get,会返回可以跳转到支付页面的 url
formData.setMethod("get");
//支付时信息
formData.addField("bizContent", {
outTradeNo: orderId, //订单号
productCode: "FAST_INSTANT_TRADE_PAY", //写死的
totalAmount: price, //价格
subject: name, //商品名称
});
//支付成功或者失败跳转的链接
formData.addField("returnUrl", "http://localhost:8080/payment");
//返回promise
const result = alipaySdk.exec(
"alipay.trade.page.pay",
{},
{ formData: formData }
);
//对接支付宝成功,支付宝方返回的数据
result.then((resp) => {
res.send({
data: {
code: 200,
success: true,
msg: "支付中",
paymentUrl: resp,
},
});
});
});
Payment.vue
<template>
<div>
<div v-if='payStatus'>恭喜您支付成功~</div>
<div v-else>支付失败</div>
</div>
</template>
<script>
import http from '@/common/api/request.js'
import qs from 'qs'
export default{
data () {
return {
payStatus : false
}
},
created(){
this.getData();
},
methods:{
getData(){
let datas = {
out_trade_no:this.$route.query.out_trade_no,
trade_no:this.$route.query.trade_no
}
http.$axios({
url:'/api/successPayment',
method:"post",
headers:{
token:true
},
data:qs.stringify(datas)
}).then(res=>{
if( res.code == 2 ){
this.payStatus = true;
}
})
}
}
}
</script>
<style>
</style>
后台接口
//支付状态
router.post("/api/successPayment", function (req, res, next) {
//token
let token = req.headers.token;
let tokenObj = jwt.decode(token);
//订单号
let out_trade_no = req.body.out_trade_no;
let trade_no = req.body.trade_no;
//支付宝配置
const formData = new AlipayFormData();
// 调用 setMethod 并传入 get,会返回可以跳转到支付页面的 url
formData.setMethod("get");
//支付时信息
formData.addField("bizContent", {
out_trade_no,
trade_no,
});
//返回promise
const result = alipaySdk.exec(
"alipay.trade.query",
{},
{ formData: formData }
);
//后端请求支付宝
result.then((resData) => {
axios({
method: "GET",
url: resData,
})
.then((data) => {
let responseCode = data.data.alipay_trade_query_response;
if (responseCode.code == "10000") {
switch (responseCode.trade_status) {
case "WAIT_BUYER_PAY":
res.send({
data: {
code: 0,
data: {
msg: "支付宝有交易记录,没付款",
},
},
});
break;
case "TRADE_CLOSED":
res.send({
data: {
code: 1,
data: {
msg: "交易关闭",
},
},
});
break;
case "TRADE_FINISHED":
connection.query(
`select * from user where tel = ${tokenObj.tel}`,
function (error, results) {
//用户id
let uId = results[0].id;
connection.query(
`select * from store_order where uId = ${uId} and order_id = ${out_trade_no}`,
function (err, result) {
let id = result[0].id;
//订单的状态修改掉2==》3
connection.query(
`update store_order set order_status = replace(order_status,'2','3') where id = ${id}`,
function () {
res.send({
data: {
code: 2,
data: {
msg: "交易完成",
},
},
});
}
);
}
);
}
);
break;
case "TRADE_SUCCESS":
connection.query(
`select * from user where tel = ${tokenObj.tel}`,
function (error, results) {
//用户id
let uId = results[0].id;
connection.query(
`select * from store_order where uId = ${uId} and order_id = ${out_trade_no}`,
function (err, result) {
let id = result[0].id;
//订单的状态修改掉2==》3
connection.query(
`update store_order set order_status = replace(order_status,'2','3') where id = ${id}`,
function () {
res.send({
data: {
code: 2,
data: {
msg: "交易完成",
},
},
});
}
);
}
);
}
);
break;
}
} else if (responseCode.code == "40004") {
res.send({
data: {
code: 4,
msg: "交易不存在",
},
});
}
})
.catch((err) => {
res.send({
data: {
code: 500,
msg: "交易失败",
err,
},
});
});
});
});