You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

655 lines
14 KiB
Vue

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<!-- <isPhone>
</isPhone> -->
<view class="page-box">
<template v-if="info.id">
<view class="info">
<view class="logo">
<u--image :showLoading="true" :src="info.logo_url" width="60px" height="60px"></u--image>
</view>
<text>
{{ info.name }}
</text>
</view>
<view class="con">
<u--text text="付款金额" margin="0 0 8px 8px" bold color="#000000" size="14"></u--text>
<view class="price">
<view>
<u--text text="¥" margin="0 3px 0 0" size="32" bold color="#000000"></u--text>
</view>
<input ref="input" v-model.lazy="total_price" @blur="formatInput" :focus="focusState" border="none"
type="digit" class="input" />
</view>
<coupons v-if="coupon && coupon.length" :activeCoupon.sync="activeCoupon" :coupon="coupon"
:currentPrice="total_price">
</coupons>
</view>
<view class="payList">
<view class="item" @click="pay(3)" v-if="info.pay_type.includes(3)">
<view class="let">
<text>余额支付</text>
<!-- <text v-show="total_price">{{ price || 0 }} </text> -->
</view>
</view>
<!-- #ifdef MP-WEIXIN -->
<view style="background: #19be6b;" class="item" @click="pay(2)" v-if="info.pay_type.includes(2)">
<view class="let">
<text>微信</text>
<!-- <text v-show="total_price">{{ price || 0 }} </text> -->
</view>
</view>
<!-- #endif -->
<!-- #ifdef MP-ALIPAY -->
<view style="background: #2979ff;" class="item">
<view class="let" @click="pay(1)" v-if="info.pay_type.includes(1)">
<text>支付宝</text>
<!-- <text v-show="total_price">{{ price || 0 }} </text> -->
</view>
</view>
<!-- #endif -->
<!-- #ifdef H5 -->
<view v-if="$utils.isInWeChatBrowser() && info.pay_type.includes(2)" style="background: #19be6b;"
class="item" @click="pay(2)">
<view class="let">
<text>微信</text>
<!-- <text v-show="total_price">{{ price || 0 }} ¥</text> -->
</view>
</view>
<view v-if="$utils.isInAliBrowser() && info.pay_type.includes(1)" style="background: #2979ff;"
class="item" @click="pay(1)">
<view class="let">
<text>支付宝</text>
<!-- <text v-show="total_price">{{ price || 0 }} ¥</text> -->
</view>
</view>
<!-- #endif -->
</view>
</template>
<logins v-if="wcCode != -1" @isLogin="isLogin" :wcCode="wcCode" :type="$utils.isInAliBrowser() || $utils.isInWeChatBrowser() ? 0 : 2"></logins>
</view>
</template>
<script>
import isPhone from "@/components/tools/isPhone/index";
import coupons from '../compontents/coupons.vue';
import logins from '@/components/login/logins.vue'
// #ifndef MP
import wxConfig from '@/utils/wxConfig'
// #endif
export default {
components: {
coupons,
isPhone,
logins
},
data() {
return {
order_type: 1,
info: {
pay_type: []
},
total_price: "",
pop: false,
focusState: true,
payCurrent: false,
coupon: [],
activeCoupon: {},
mch_id: 0,
wcCode: -1
}
},
computed: {
price() {
console.log(this.activeCoupon);
if (this.activeCoupon?.coupon?.price) {
return (this.total_price - this.activeCoupon.coupon.price)?.toFixed?.(2)
} else {
return (this.total_price)
}
}
},
async onLoad(query) {
if (query.wxcode) {
this.wcCode = query.wxcode
query.mch_id = uni.getStorageSync('pay_mch_id')
} else {
if (query.state) {
return uni.showModal({
title: '提示',
content: '登录失败'
})
}
this.wcCode = ''
if (query.mch_id > 0) {
uni.setStorageSync('pay_mch_id', query.mch_id)
}
}
let qrCode = '';
const params = query
const {
mch_id
} = params;
this.mch_id = mch_id || 0
this.$nextTick(() => {
this.init()
})
},
onShow() {
this.watchToMonitor = this.$watch(
// 此处被监听的对象必须是一个函数,否则会报错
() => {
return this.total_price
},
() => {
// do some thing
uni.setStorageSync("支付" + this.mch_id, JSON.stringify(this.total_price))
}, {
deep: true
})
},
onHide() {
this.watchToMonitor()
if (!this.payCurrent) {
this.payCurrent = false
this.focusState = false
}
},
methods: {
isLogin() {
// this.init()
},
async init() {
const res = await this.$api.inPersonToPay.storeInfos({
mch_id: this.mch_id,
})
this.info = {
...res.data.store,
...res.data.shop
}
if (!this.info.pay_type) {
this.info.pay_type = []
}
this.coupon = res.data.coupon
},
formatInput() {
if (this.total_price !== null) {
let value = this.total_price.toString();
value = value.replace(/[^\d.]/g, ""); // 去掉非数字和小数点
value = value.replace(/^\./g, ""); // 去掉开头的小数点
value = value.replace(/\.{2,}/g, "."); // 去掉多余的小数点
value = value.replace(".", "$#$").replace(/\./g, "").replace("$#$", ".");
// 将第一个小数点替换成分隔符
value = parseFloat(value);
if (isNaN(value)) {
value = null;
} else {
value = value.toFixed(2); // 保留两位小数
}
this.total_price = value;
}
},
async pay(type) {
if (this.submit()) return
this.payCurrent = true
let {
order_type
} = this;
const payType = type // 支付类型
let order_no
const res = await this.$api.inPersonToPay.inpersonPaymentOrder({
total_price: this.total_price,
pay_type: type,
mch_id: this.mch_id,
user_coupon_id: this.activeCoupon.id || 0,
})
if (res.code !== 0) {
uni.$u.toast(res.message || "出错了");
return
}
order_no = res.data.order_no // 订单号
uni.showLoading({
title: "请稍等",
mask: true,
});
switch (payType) {
case 1:
await this.payTreasureToPay({
payType,
order_no,
order_type
})
break;
case 2:
// return uni.showModal({
// title: '提示',
// content: '请使用支付宝扫码',
// showCancel: false
// })
// #ifndef MP
await this.wechatPayNow({
payType,
order_no,
order_type
})
// #endif
// #ifdef MP-WEIXIN
await this.wechatPay({
payType,
order_no,
order_type
})
// #endif
break;
case 3:
console.log("余额");
await this.balancePayment({
payType,
order_no,
order_type
})
break;
default:
break;
}
uni.hideLoading();
},
// 余额支付
async balancePayment({
payType,
order_no,
order_type
}) {
try {
const res = await this.$api.pay.OrderPayment({
pay_type: payType,
order_no: order_no,
order_type,
});
if (res.code) {
// this.$u.toast(res.message)
throw new Error(res.message)
};
this.successSubmit(res)
} catch (error) {
this.$u.toast(error.message)
}
},
// H5 微信支付
async wechatPayNow({
payType,
order_no,
order_type
}) {
wxConfig.init(["chooseWXPay"]).then((wx) => {
console.log(wx.chooseWXPay);
})
try {
const res = await this.$api.pay.OrderPayment({
pay_type: payType,
order_no: order_no,
order_type
});
if (res.code) return this.$u.toast(res.message)
if (res.data == -1) {
return this.successSubmit();
}
wxConfig.init(["chooseWXPay"]).then(wx => {
wx.chooseWXPay({
// 支付签名时间戳注意微信jssdk中的所有使用timestamp字段均为小写。
// 但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
timestamp: res.data.timeStamp, // 时间戳
nonceStr: res.data.nonceStr, // 支付签名随机串,不长于 32 位
package: res.data.package, // 统一支付接口返回的prepay_id参数值提交格式如prepay_id=\*\*\*
signType: res.data.signType, // 签名算法
paySign: res.data.paySign, // 签名
success: function(res) {
if (res.err_msg == "get_brand_wcpay_request:ok" || res.err_Info ==
"success" || res.errMsg == "chooseWXPay:ok") {
this.successSubmit();
} else {
this.failSubmit();
}
},
complete: function(err) {
if (res.err_msg == "get_brand_wcpay_request:ok" || res.err_Info ==
"success" || res.errMsg == "chooseWXPay:ok" || res.errMsg ==
"getBrandWCPayRequest:ok") {
this.successSubmit();
} else {
this.failSubmit();
}
},
})
})
} catch (error) {
this.$u.toast(error.message)
}
},
// 微信支付
async wechatPay({
payType,
order_no,
order_type
}) {
try {
const res = await this.$api.pay.OrderPayment({
pay_type: payType,
order_no: order_no,
order_type,
});
if (res.code) return this.$u.toast(res.message)
// res为调起微信支付所需参数
// 调起微信支付
await uni.requestPayment({
provider: 'wxpay', // 服务提提供商
timeStamp: res.data.timeStamp, // 时间戳
nonceStr: res.data.nonceStr, // 随机字符串
package: res.data.package,
signType: res.data.signType, // 签名算法
paySign: res.data.paySign, // 签名
success: (res) => {
if (res.errMsg === 'requestPayment:ok') {
this.successSubmit();
}
console.log(res, 'success');
},
fail: (res) => {
console.log(res, 'fail')
if (res.errMsg == 'requestPayment:fail cancel') {
this.failSubmit();
}
},
complete(res) {
console.log(res, 'complete')
}
});
} catch (error) {
this.$u.toast(error.message)
console.log(error)
}
},
// 支付宝支付
async payTreasureToPay({
payType,
order_no,
order_type
}) {
try {
let that = this
const res = await this.$api.pay.OrderPayment({
pay_type: payType,
order_no: order_no,
order_type,
});
if (res.code) return this.$u.toast(res.message)
// #ifdef H5
if (this.$utils.isInAliBrowser()) {
AlipayJSBridge.call("tradePay", {
tradeNO: res.data.trade_no
}, function(data) {
if ("9000" == data.resultCode) {
that.successSubmit(res)
} else {
throw new Error('支付失败,状态码:' + data.resultCode)
}
});
} else {
return uni.showToast({
icon: 'none',
title: '请到支付宝或微信环境中支付'
})
}
// #endif
// #ifdef MP-ALIPAY
// res为调起支付宝支付所需参数
// 调起支付宝支付
uni.requestPayment({
provider: 'alipay', // 服务提供商
orderInfo: res.data.trade_no,
success: (res) => {
console.log(res);
if (res.errMsg === 'requestPayment:ok' && res.resultCode ===
'9000') { // 支付成功的判断条件
this.successSubmit(res)
}
},
fail: (err) => {
if (err.errMsg !== 'requestPayment:fail cancel') { // 不是取消支付的错误才抛出异常
throw new Error(err.errMsg)
}
},
complete: ({
errMsg
}) => {
// if (errMsg) {
// this.$u.toast(errMsg);
// }
}
});
// #endif
} catch (error) {
this.$u.toast(error.message)
}
},
failSubmit() {
this.$u.toast("支付失败")
},
successSubmit() {
this.pop = false
this.$u.toast("支付成功")
setTimeout(() => {
this.toUrl('/subPackages/inPersonToPay/result/index?price=' + this.total_price + '&mch_id=' +
this.mch_id)
uni.removeStorageSync("支付" + this.mch_id)
this.total_price = ""
this.payCurrent = false
}, 300);
},
submit() {
if (!this.total_price) {
this.$u.toast("请输入付款金额")
return true
}
if (this.total_price <= 0) {
this.$u.toast("付款金额低于0元")
return true
}
return false
}
}
}
</script>
<style lang="scss" scoped>
.info {
display: flex;
align-items: center;
margin: 20px;
grid-gap: 32rpx;
grid: 32rpx;
.logo {
border-radius: 26rpx;
border-right-color: rgb(212, 212, 212);
overflow: hidden;
}
}
.con {
padding: 19px;
box-shadow: 0 0.4125rem 2rem 2px rgba(215, 216, 217, .49);
margin: 20px;
border-radius: 20rpx;
}
::v-deep {
uni-input {
font-weight: 600 !important;
color: black;
transition: all 0.6s;
font-weight: 600;
min-height: 80px !important;
display: flex;
}
.u-border-bottom {
border-bottom-width: 0.5px !important;
border-color: rgb(224, 223, 223) !important;
border-bottom-style: solid;
}
.u-popup__content {
background-color: transparent;
}
}
.input {
font-size: 32px;
padding: 10rpx 2%;
height: 42px;
line-height: 42px;
}
.payList {
// position: fixed;
left: 0;
right: 0;
bottom: 0;
padding: 12rpx 36rpx 12rpx;
// padding: 12rpx 36rpx calc(constant(safe-area-inset-bottom) + 22rpx);
// padding: 12rpx 36rpx calc(env(safe-area-inset-bottom) + 22rpx);
background: #fff;
padding: 19px;
box-shadow: 0 0.4125rem 2rem 2px rgba(215, 216, 217, .49);
margin: 20px;
border-radius: 40rpx;
.item {
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(90deg, #f22407 0%, #f84d17 100%);
padding: 14rpx;
border-radius: 32px;
font-size: 26rpx;
font-weight: bold;
color: #fff;
box-sizing: border-box;
transition: all 1s cubic-bezier(0.075, 0.82, 0.165, 1);
&:hover {
opacity: 0.8;
}
}
.title {
padding-top: 34rpx;
font-weight: 600;
text-align: center;
}
.item {
display: flex;
align-items: center;
justify-content: space-between;
height: 80rpx;
.let {
display: flex;
align-items: center;
// justify-content: space-between;
justify-content: center;
}
padding: 0 28rpx;
&:not(:last-child) {
margin-bottom: 20rpx;
border-bottom: 1px solid #f8f8f8;
}
}
.m-tit {
margin-bottom: 20rpx;
}
.let {
flex: 1;
overflow: hidden;
display: flex;
align-items: center;
}
.img {
display: flex;
align-items: center;
justify-content: center;
margin-right: 20rpx;
width: 40rpx;
height: 40rpx;
}
image {
// width: 100%;
height: 40rpx;
}
}
.price {
display: flex;
align-items: center;
border-bottom: 1px solid #f8f8f8;
}
</style>
<style>
page {
background-color: white;
}
</style>