Files
ZangShiQi/addon/cashier/source/os/components/ns-payment/index.js
2026-04-04 17:27:12 +08:00

1023 lines
25 KiB
JavaScript
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import {payCalculate} from '@/api/order_create'
import {getOrderInfoById, orderRemark} from '@/api/order'
import {
getPayQrcode,
addPayCashierPay,
authCodepay,
getPayType,
getCashierPayInfo,
cashierConfirm,
checkPaymentCode
} from '@/api/oder_pay'
import {orderPrintTicket} from '@/api/order.js'
import {sendMemberVerifyCode, checkMemberVerifyCode} from '@/api/member'
import {mapGetters} from 'vuex';
export default {
props: {
outTradeNo: {
type: String,
default: ''
},
storeRoute: {
type: String,
default: ''
}
},
data() {
return {
type: 'third',
payType: {
third: {
type: 'third',
name: '付款码',
icon: 'iconsaomaqiang',
background: '#f7931e',
hotKey: 'N',
KeyCode: 'KeyN'
},
cash: {
type: 'cash',
name: '现金',
icon: 'iconxianjin1',
background: '#f5b719',
hotKey: 'C',
KeyCode: 'KeyC'
},
own_wechatpay: {
type: 'own_wechatpay',
name: '微信',
icon: 'iconwxpay',
background: '#09bb07',
hotKey: 'W',
KeyCode: 'KeyW'
},
own_alipay: {
type: 'own_alipay',
name: '支付宝',
icon: 'iconzhifubaozhifu',
background: '#1890ff',
hotKey: 'A',
KeyCode: 'KeyA'
},
own_pos: {
type: 'own_pos',
name: 'POS刷卡',
icon: 'iconyinhangqia',
background: '#ec6a55',
hotKey: 'P',
KeyCode: 'KeyP'
}
},
payInfo: null,
payStatus: 'pay',
isRepeat: false,
qrcodeShow: false,
payQrcode: [],
timer: null,
moneyPopup: {
money: 0,
type: '',
title: ''
},
cash: 0,
discount: {},
thirdPopupOpen:false,
scanCodeType: 'scancode',
scanCodeFocus: true,
authCode: '',
autoComplete: {
time: 8,
timer: null
},
remark: '',
autoPrintTicket: true,
balanceSafeVerify: false, // 余额使用安全验证
dynacodeData: {
key: '',
seconds: 120,
timer: null,
codeText: '获取验证码',
isSend: false
},
smsCode: '',
paymentCode: '',
safeVerifyType: 'payment_code',
_outTradeNo: '',
active: '' ,// 活动值
//扫码枪配置
scancodeList:''
}
},
computed: {
balance() {
if (this.globalMemberInfo) {
return parseFloat(this.globalMemberInfo.balance_money) + parseFloat(this.globalMemberInfo.balance);
}
return 0;
},
promotionShow() {
if (this.payInfo && (this.payInfo.offset.coupon_array || this.payInfo.collectmoney_config.reduction == 1)) {
return true;
}
return false;
},
...mapGetters(['billingActive', 'billingIsScanTrigger', 'buyCardActive', 'rechargeActive'])
},
created() {
this._outTradeNo = this.outTradeNo;
if (this._outTradeNo) this.calculation();
if (typeof uni.getStorageSync('payAutoPrintTicket') == 'boolean') this.autoPrintTicket = uni.getStorageSync('payAutoPrintTicket');
window.POS_PRINT_CALLBACK = function (text) {
uni.showToast({
title: text,
icon: 'none'
})
};
this.addKeyDownEvent();
},
destroyed() {
clearInterval(this.timer);
},
methods: {
getPayTypeFn(){
this.scancodeList = []
getPayType().then((res)=>{
this.scancodeList = res.data
this.$refs.thirdPopup.open('', () => {
this.active = '';
});
this.$forceUpdate()
})
},
/**
* 取消支付
*/
cancelPayment() {
this.$emit('cancel', {});
this.clearPay();
},
/**
* 支付成功
*/
paySuccess() {
this.$emit('success', {});
this.clearPay();
},
clearPay() {
clearInterval(this.timer);
this.type = 'third';
this.payInfo = null;
this.payStatus = 'pay';
this.payQrcode = [];
this.cash = 0;
this.discount = {};
this.isRepeat = false;
if (this.autoComplete.timer) clearInterval(this.autoComplete.timer);
this.autoComplete.time = 8;
this.remark = '';
this.balanceSafeVerify = false;
this.smsCode = '';
this.paymentCode = '';
this.safeVerifyType = 'payment_code';
this.active = '';
this.refreshDynacodeData();
},
confirm(callback) {
if (this.type == 'cash') {
setTimeout(() => {
// 打开付款码,设置焦点
this.scanCodeFocus = true;
}, 200);
if (!this.cash) {
this.cash = this.payInfo.pay_money;
} else if (isNaN(parseFloat(this.cash))) {
this.$util.showToast({
title: '现金收款金额错误'
});
return;
} else if (parseFloat(this.cash) < parseFloat(this.payInfo.pay_money)) {
this.$util.showToast({
title: '现金收款金额不能小于支付金额'
});
return;
}
}
if (this.isRepeat) return;
this.isRepeat = true;
uni.showLoading({});
let data = {
pay_type: this.type,
out_trade_no: this._outTradeNo,
member_id: this.globalMemberInfo ? this.globalMemberInfo.member_id : 0,
promotion: JSON.stringify(this.$util.deepClone(this.discount)),
cash: this.type == 'cash' ? this.cash : 0
};
cashierConfirm(data).then(res => {
uni.hideLoading();
if (res.code == 0) {
this.payStatus = 'success';
this.$emit('getMemberInfo');
if (callback) callback();
} else {
this.isRepeat = false;
this.$util.showToast({
title: res.message
})
}
}).catch(res => {
uni.hideLoading();
})
},
calculation(callback) {
let data = {
pay_type: this.type,
out_trade_no: this._outTradeNo,
member_id: this.globalMemberInfo ? this.globalMemberInfo.member_id : 0,
promotion: JSON.stringify(this.$util.deepClone(this.discount)),
cash: this.type == 'cash' ? this.cash : 0
};
payCalculate(data).then(res => {
if (res.code == 0) {
this.payInfo = res.data;
if (this.payInfo.pay_status == 1) {
this.payStatus = 'success';
} else if (this.payInfo.pay_money == 0) {
// 订单完成
// if (this.discount.coupon_id) this.$refs.couponPopup.close();
// this.confirm();
}
for (let key in this.payType) {
if (this.payInfo.collectmoney_config.pay_type.indexOf(key) == -1) {
delete this.payType[key];
}
}
// 如果 付款码没有开启,则取第一项支付方式
if (!this.payType[this.type]) {
this.type = Object.keys(this.payType)[0];
}
if (callback) callback();
} else {
this.$util.showToast({
title: res.message
})
}
})
},
/**
* 打印小票
*/
printTicket() {
orderPrintTicket(this.payInfo.order_id).then(res => {
if (res.code == 0) {
if (Object.values(res.data).length) {
let data = Object.values(res.data);
try {
let print = {
printer: []
};
data.forEach((item) => {
print.printer.push({
printer_type: item.printer_info.printer_type,
host: item.printer_info.host,
ip: item.printer_info.ip,
port: item.printer_info.port,
content: item.content,
print_width: item.printer_info.print_width
})
});
this.$pos.send('Print', JSON.stringify(print));
} catch (e) {
console.log('err', e, res.data)
}
} else {
this.$util.showToast({
title: '未开启收银小票打印'
})
}
} else {
this.$util.showToast({
title: res.message ? res.message : '小票打印失败'
})
}
})
},
thirdConfirm() {
this.authCode = '';
this.scanCodeType = 'scancode';
this.scanCodeFocus = true;
if (this.$refs.thirdPopup) {
this.active = 'thirdConfirm';
this.getPayTypeFn()
}
},
/**
* 获取支付二维码
*/
getQrcode() {
getPayQrcode(this._outTradeNo).then(res => {
if (res.code == 0 && res.data.length) {
this.payQrcode = res.data;
this._outTradeNo = this.payQrcode[0].out_trade_no;
this.checkPayStatus();
}
})
},
popupChange() {
this.thirdPopupOpen = !this.thirdPopupOpen;
if (this.timer) {
clearInterval(this.timer);
}
},
/**
* 扫码枪
*/
scanCode(e) {
if (!e.detail.value) return;
if (this.isRepeat) return;
this.isRepeat = true;
uni.showLoading({});
addPayCashierPay(this._outTradeNo).then(res => {
if (res.code == 0) {
this._outTradeNo = res.data;
this.calculation();
authCodepay({
out_trade_no: this._outTradeNo,
auth_code: e.detail.value
}).then(res => {
this.authCode = '';
// 扫码枪解除键盘占用
this.$store.commit('billing/setIsScanTrigger', false);
uni.hideLoading();
if (res.code >= 0) {
this.checkPayStatus();
this.$refs.thirdPopup.close();
this.payStatus = 'success';
} else {
//TODO 如果是支付已取消 要生成新的支付单号,但是这里的判断是否只适用于微信?
if(res.data.err_code && res.data.err_code == 'TRADE_ERROR'){
this.calculation('');
}else{
this.checkPayStatus();
this.isRepeat = false;
this.$util.showToast({
title: res.message
})
}
}
})
} else {
uni.hideLoading();
this.isRepeat = false;
this.$util.showToast({
title: res.message
});
// 扫码枪解除键盘占用
this.$store.commit('billing/setIsScanTrigger', false);
}
})
},
//失焦事件
scanCodeInputBlur(){
this.scanCodeFocus = false;
//强制聚焦处理
if( ( this.thirdPopupOpen && this.scanCodeType == 'scancode') || this.active == 'memberCodePopup' ){
this.$nextTick(() => {
this.scanCodeFocus = true;
});
}
},
// 清除付款码内容
clearAuthCode() {
this.authCode = '';
// 扫码枪解除键盘占用
this.$store.commit('billing/setIsScanTrigger', false);
},
/**
* 查询支付状态
*/
checkPayStatus() {
clearTimeout(this.timer);
this.timer = setInterval(() => {
getCashierPayInfo(this._outTradeNo).then(res => {
if (res.code == 0 && res.data) {
if(res.data.pay_status == 2){
// 查询订单状态
getOrderInfoById(this.payInfo.order_id).then(res => {
if (res.code == 0 && res.data) {
if (res.data.order_status == -1 && res.data.close_cause) {
// 订单关闭,显示退款原因
this.$util.showToast({
title: res.data.close_cause
});
clearInterval(this.timer)
} else if (res.data.order_status == 10) {
this.$refs.thirdPopup.close();
this.payStatus = 'success';
clearInterval(this.timer)
}
}
})
}else if(res.data.pay_status == -1){
this.$util.showToast({
title: '用户已取消支付',
});
clearInterval(this.timer);
this.calculation('');
}
}
})
}, 1500)
},
/**
* 打开金额弹窗
* @param {Object} data
*/
openMoneyPopup(data) {
this.moneyPopup = Object.assign(this.moneyPopup, data);
if (this.$refs.moneyPopup) {
this.active = 'OpenMoneyPopup';
this.$refs.moneyPopup.open('', () => {
this.active = '';
});
}
},
deleteCode() {
this.moneyPopup.money = this.moneyPopup.money.substr(0, this.moneyPopup.money.length - 1);
},
moneyPopupConfirm(callback) {
if (!this.moneyPopup.money.length) {
this.$util.showToast({
title: '请输入金额'
});
return;
}
if (this.moneyPopup.type == 'reduction') {
this.discount.reduction = parseFloat(this.moneyPopup.money);
} else if (this.moneyPopup.type == 'cash') {
this.cash = parseFloat(this.moneyPopup.money);
}
this.calculation(callback);
this.$refs.moneyPopup.close();
},
keydown(value) {
let arr = this.moneyPopup.money.split('.');
if (arr[1]) {
if (value == '.' || arr[1].length == 2) return;
if (value == '00' && arr[1].length == 1) value = '0';
}
if (this.moneyPopup.type == 'reduction' && parseFloat(this.moneyPopup.money + value) > parseFloat(this
.payInfo.pay_money)) {
this.$util.showToast({
title: `减免金额不能超过订单金额¥${this.payInfo.pay_money}`
});
return;
}
if (parseFloat(this.moneyPopup.money + value) > 1000000) {
this.$util.showToast({
title: '最大不能超过1000000'
});
return;
}
this.moneyPopup.money += value;
},
/**
* 切换支付方式
* @param {Object} type
* @param {Object} callback
*/
switchPayType(type, callback) {
this.type = type;
if (type == 'cash') {
if (this.cash) {
this.openMoneyPopup({
title: '收款金额',
money: this.$util.moneyFormat(this.cash),
type: 'cash'
})
} else {
this.openMoneyPopup({
title: '收款金额',
money: this.$util.moneyFormat(this.payInfo.pay_money),
type: 'cash'
})
}
} else {
this.calculation(callback);
}
},
/**
* 减免金额
*/
reduction() {
if (this.discount.reduction) {
delete this.discount.reduction;
this.calculation();
} else {
this.openMoneyPopup({
title: '减免金额',
money: '',
type: 'reduction'
})
}
},
/**
* 使用积分
*/
usePoint() {
if (this.payInfo.offset.point_array.point == 0) return;
if (this.discount.is_use_point) {
delete this.discount.is_use_point;
} else {
this.discount.is_use_point = 1;
}
this.calculation();
},
useBalance() {
if (this.balance == 0) return;
// 如果开启了余额安全验证
if (this.payInfo.collectmoney_config.balance_safe == 1 && !this.balanceSafeVerify) {
if (this.$refs.safeVerifyPopup) {
this.active = 'safeVerifyPopup';
this.$refs.safeVerifyPopup.open('', () => {
this.active = '';
});
return;
}
}
if (this.discount.is_use_balance) {
delete this.discount.is_use_balance;
} else {
this.discount.is_use_balance = 1;
}
this.calculation();
},
selectCoupon() {
if (!this.payInfo.offset.coupon_array.member_coupon_list.length) return;
if (this.$refs.couponPopup) {
this.active = 'couponPopup';
this.$refs.couponPopup.open('', () => {
this.active = '';
});
}
},
selectCouponItem(data) {
if (!this.discount.coupon_id) {
this.discount.coupon_id = data.coupon_id;
} else if (this.discount.coupon_id != data.coupon_id) {
this.discount.coupon_id = data.coupon_id;
} else {
delete this.discount.coupon_id;
}
this.$forceUpdate();
this.calculation();
},
openRemark() {
this.remark = this.payInfo.remark;
if (this.$refs.remarkPopup) {
this.active = 'RemarkPopup';
this.$refs.remarkPopup.open('', () => {
this.active = '';
});
}
},
/**
* 设置备注
*/
remarkConfirm() {
if (!this.remark) return;
orderRemark({
order_id: this.payInfo.order_id,
remark: this.remark
}).then(res => {
this.payInfo.remark = this.remark;
this.$refs.remarkPopup.close();
});
},
// 清除手机验证码内容
clearSmsCode() {
this.smsCode = '';
// 扫码枪解除键盘占用
this.$store.commit('billing/setIsScanTrigger', false);
},
/**
* 发送短信验证码
*/
sendMobileCode() {
if (this.dynacodeData.seconds != 120 || this.dynacodeData.isSend) return;
this.dynacodeData.isSend = true;
this.dynacodeData.timer = setInterval(() => {
this.dynacodeData.seconds--;
this.dynacodeData.codeText = this.dynacodeData.seconds + 's后可重新获取';
}, 1000);
sendMemberVerifyCode(this.payInfo.member_id).then(res => {
if (res.code >= 0) {
this.dynacodeData.key = res.data.key;
this.smsCode = '';
this.dynacodeData.isSend = false;
} else {
this.$util.showToast({
title: res.message
});
this.refreshDynacodeData();
}
}).catch(res => {
this.$util.showToast({
title: 'request:fail'
});
this.refreshDynacodeData();
});
},
refreshDynacodeData() {
clearInterval(this.dynacodeData.timer);
this.dynacodeData = {
key: '',
seconds: 120,
timer: null,
codeText: '获取动态码',
isSend: false
};
},
/**
* 验证短信验证码是否正确
*/
verifySmsCode() {
if (this.smsCode.trim() == '') {
this.$util.showToast({
title: '请输入验证码'
});
return;
}
if (this.isRepeat) return;
this.isRepeat = true;
checkMemberVerifyCode({
key: this.dynacodeData.key,
code: this.smsCode.trim()
}).then(res => {
if (res.code == 0) {
this.balanceSafeVerify = true;
this.$refs.safeVerifyPopup.close();
this.useBalance();
} else {
this.$util.showToast({
title: res.message
});
}
this.isRepeat = false;
})
},
// 清除付款码内容
clearPaymentCode() {
this.paymentCode = '';
// 扫码枪解除键盘占用
this.$store.commit('billing/setIsScanTrigger', false);
},
changeSafeVerifyType(type) {
this.safeVerifyType = type;
},
// 使用会员码,验证付款码,查询会员信息,并且使用余额
switchMemberCode() {
if (!this.balanceSafeVerify && this.$refs.safeVerifyPopup) {
this.active = 'memberCodePopup';
setTimeout(() => {
this.scanCodeFocus = true;
}, 200);
this.$refs.safeVerifyPopup.open('', () => {
this.active = '';
});
} else {
this.useBalance();
}
},
verifyPaymentCode(e) {
setTimeout(() => {
if (this.paymentCode.trim() == '') {
this.$util.showToast({
title: '请输入付款码'
});
return;
}
if (this.isRepeat) return;
this.isRepeat = true;
checkPaymentCode({
member_id: this.payInfo.member_id,
code: this.paymentCode.trim()
}).then(res => {
if (res.code == 0) {
this.balanceSafeVerify = true;
this.$store.commit('app/setGlobalMemberInfo', res.data.member_info);
this.$refs.safeVerifyPopup.close();
this.useBalance();
} else {
this.$util.showToast({
title: res.message
});
}
// 扫码枪解除键盘占用
this.$store.commit('billing/setIsScanTrigger', false);
this.isRepeat = false;
})
}, 200)
},
/**
* 快捷键支付
* @param {Object} code 快捷键KeyCode
*/
hotKeyPay(code) {
this.hotKeyPayCallback(code);
},
// 触发快捷键回调
hotKeyPayCallback(code) {
// 检查支付方式是否开启
var pay = null;
for (let key in this.payType) {
if (this.payType[key].KeyCode == code) {
pay = this.payType[key];
}
}
if (!pay) return;
if (pay.type == 'cash') {
// 现金支付
this.calculation(() => {
this.switchPayType(pay.type, () => {
if (this.type != 'third') {
// 个人微信、支付宝、POS刷卡
this.confirm();
} else {
// 付款码/扫码枪
this.thirdConfirm();
}
});
});
} else {
this.switchPayType(pay.type, () => {
if (this.type != 'third') {
// 个人微信、支付宝、POS刷卡
this.confirm();
} else {
// 付款码/扫码枪
this.thirdConfirm();
}
});
}
},
/**
* 添加键盘监听事件
*/
addKeyDownEvent() {
// #ifdef H5
window.addEventListener("keydown", this.listenerKeyDown, true);
// #endif
},
/**
* 移除键盘监听事件
*/
removeKeyDownEvent() {
// #ifdef H5
window.removeEventListener("keydown", this.listenerKeyDown, true);
// #endif
},
// 监听键盘按下事件
listenerKeyDown(e) {
var code = e.code;
// 正在使用扫码枪,禁用键盘
if (this.billingIsScanTrigger) return;
if ((this.storeRoute == 'billing' && this.billingActive == 'OrderCreate')
|| (this.storeRoute == 'buycard' && this.buyCardActive == 'OrderCreate')
|| (this.storeRoute == 'recharge' && this.rechargeActive == 'OrderCreate')
) {
// 创建订单
this.orderCreateCallback(code);
}
}, /**
* 订单创建 事件回调
* @param {string} code 按键代码
*/
orderCreateCallback(code) {
// 快捷支付KeyN付款码支付KeyC现金支付cashKeyW微信支付wechatA支付宝支付alipayKeyPPOS刷卡支付POS
let letterCode = ['KeyN', 'KeyC', 'KeyW', 'KeyA', 'KeyP'];
if (code == 'KeyM') {
// 会员码
this.switchMemberCode();
} else if (letterCode.indexOf(code) != -1) {
// 快捷下单
this.quickOrderCallback(code);
} else if (code == 'Escape') {
// 取消支付,回到上一步,检测当前没有弹出框
if (this.active == '') {
this.cancelPayment();
if (this.storeRoute == 'recharge') {
this.$store.commit(this.storeRoute + '/setActive', '');
} else {
this.$store.commit(this.storeRoute + '/setActive', 'SelectGoodsAfter');
}
}
} else if (this.active == 'OpenMoneyPopup') {
if (code == 'Enter' || code == 'NumpadEnter') {
if (this.moneyPopup.type == 'reduction') {
// 减免金额
this.moneyPopupConfirm();
} else if (this.moneyPopup.type == 'cash') {
// 现金支付
this.moneyPopupConfirm(() => {
this.confirm();
});
}
} else if (code == 'NumpadDecimal') {
this.keydown('.');
} else if (code.indexOf('Numpad') != -1) {
var num = code.replace('Numpad', '');
this.keydown(num);
} else if (code.indexOf('Digit') != -1) {
var num = code.replace('Digit', '');
this.keydown(num);
}
} else if (code == 'Enter' || code == 'NumpadEnter') {
if (this.payStatus == 'success') {
// 支付成功
this.paySuccess();
this.$store.commit(this.storeRoute + '/setActive', '');
} else if (this.active == 'RemarkPopup') {
// 备注
this.remarkConfirm();
} else if (this.active == 'safeVerifyPopup') {
// 使用付款码,出示付款码、验证手机号
setTimeout(() => {
// 打开付款码,设置焦点
this.scanCodeFocus = true;
}, 200);
if (this.safeVerifyType == 'payment_code') {
this.verifyPaymentCode({
detail: {
value: this.paymentCode
}
});
} else if (this.safeVerifyType == 'sms_code') {
this.verifySmsCode({
detail: {
value: this.smsCode
}
});
}
} else if (this.active == 'memberCodePopup') {
// 使用付款码,出示付款码、使用余额
this.verifyPaymentCode({
detail: {
value: this.paymentCode
}
});
} else if (this.active == 'thirdConfirm') {
// 打开付款码,设置焦点
setTimeout(() => {
// 打开付款码,设置焦点
this.scanCodeFocus = true;
}, 200);
} else if (this.type == 'cash') {
// 选择【现金支付】方式,打开现金支付弹出框
if (this.active == '') {
this.switchPayType(this.type);
}
} else if (this.type != 'third') {
this.confirm();
} else if (this.active == '') {
// 付款码/扫码枪
this.thirdConfirm();
setTimeout(() => {
// 初次打开,设置焦点
this.scanCodeFocus = true;
}, 200);
}
}
},
/**
* 快捷下单 事件回调
* @param {string} code 按键代码
*/
quickOrderCallback(code) {
// 不能存在操作
if (this.active) return;
if (this.payStatus == 'success') return;
// 快捷支付KeyN付款码支付KeyC现金支付cashKeyW微信支付wechatA支付宝支付alipayKeyPPOS刷卡支付POS
this.hotKeyPay(code);
},
},
watch: {
outTradeNo: function (nval, oval) {
if (nval) {
this._outTradeNo = nval;
this.calculation();
}
},
type: function (nval) {
if (nval != 'third' && this.timer) {
clearInterval(this.timer);
}
},
scanCodeType: function (nval) {
if (nval == 'scancode') {
this.scanCodeFocus = true;
} else {
this.getQrcode();
}
},
payStatus: function (nval) {
if (nval == 'success') {
if (this.autoPrintTicket) this.printTicket();
this.isRepeat = false;
this.autoComplete.timer = setInterval(() => {
if (this.autoComplete.time == 0) {
this.paySuccess();
} else {
this.autoComplete.time--;
}
}, 1000)
}
},
autoPrintTicket: function (nval) {
uni.setStorageSync('payAutoPrintTicket', nval)
},
'dynacodeData.seconds': {
handler(newValue, oldValue) {
if (newValue == 0) {
this.refreshDynacodeData();
}
},
immediate: true,
deep: true
}
}
}