Compare commits

7 Commits

5 changed files with 1035 additions and 863 deletions

3
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,3 @@
{
"codingcopilot.enableCompletionLanguage": {}
}

View File

View File

@@ -73,25 +73,36 @@ export default {
return { return {
payIndex: 0, payIndex: 0,
payTypeList: [ payTypeList: [
// #ifdef H5 || MP-ALIPAY
{
name: '支付宝支付',
icon: 'icon-zhifubaozhifu-',
type: 'alipay'
},
// #endif
// #ifdef H5 || MP-WEIXIN
{ {
name: '微信支付', name: '微信支付',
icon: 'icon-weixin1', icon: 'icon-weixin1',
type: 'wechatpay' type: 'wechatpay',
description: '推荐微信用户使用'
},
{
name: '支付宝支付',
icon: 'icon-zhifubaozhifu-',
type: 'alipay',
description: '推荐支付宝用户使用'
},
{
name: '华为支付',
icon: 'icon-huawei-pay',
type: 'huaweipay',
description: '华为用户专属支付'
}, },
// #endif
{ {
name: '线下支付', name: '线下支付',
icon: 'icondiy icon-yuezhifu', icon: 'icondiy icon-yuezhifu',
type: 'offlinepay' type: 'offlinepay',
description: '到店支付或银行转账'
}, },
{
name: '余额支付',
icon: 'icon-balance',
type: 'balancepay',
description: '使用账户余额支付'
}
], ],
// #ifdef H5 // #ifdef H5
timer: null, timer: null,
@@ -105,6 +116,7 @@ export default {
//重置是否已完成没有完成不能调用api/pay/pay //重置是否已完成没有完成不能调用api/pay/pay
resetPayComplete: true, resetPayComplete: true,
repeatFlag: false, repeatFlag: false,
flag: false // 保留文件1的flag变量用于支付失败处理
}; };
}, },
created(e) { created(e) {
@@ -254,42 +266,48 @@ export default {
// #ifdef H5 // #ifdef H5
pay() { pay() {
var payType = this.payTypeList[this.payIndex]; var payType = this.payTypeList[this.payIndex];
// 保留文件2的线下支付逻辑
if (!payType || payType.type === 'offlinepay') {
this.payOffline();
return;
}
// 保留文件2的流程控制
if (!this.resetPayComplete) {
uni.hideLoading();
this.$util.showToast({
title: '支付取消中,请稍后再试!'
});
this.repeatFlag = false;
return;
}
// 复用文件1的核心逻辑调用后端/api/pay/pay接口
var return_url = ''; var return_url = '';
if (this.payInfo.event == 'BlindboxGoodsOrderPayNotify') { if (this.payInfo.event == 'BlindboxGoodsOrderPayNotify') {
return_url = '/pages_promotion/blindbox/index?outTradeNo='; return_url = '/pages_promotion/blindbox/index?outTradeNo=';
} else { } else {
return_url = '/pages_tool/pay/result?code='; return_url = '/pages_tool/pay/result?code=';
} }
this.$api.sendRequest({ this.$api.sendRequest({
url: '/api/pay/pay', url: '/api/pay/pay',
data: { data: {
out_trade_no: this.payInfo.out_trade_no, out_trade_no: this.payInfo.out_trade_no,
pay_type: payType ? payType.type : '', pay_type: payType.type,
return_url: encodeURIComponent(this.$config.h5Domain + return_url + this.payInfo.out_trade_no), return_url: encodeURIComponent(this.$config.h5Domain + return_url + this.payInfo.out_trade_no),
is_balance: this.isBalance is_balance: this.isBalance
}, },
success: res => { success: res => {
uni.hideLoading(); uni.hideLoading();
this.repeatFlag = false; // 重置文件2的防重复标记
if (res.code >= 0) { if (res.code >= 0) {
if (res.data.pay_success) { if (res.data.pay_success) {
this.paySuccess(); this.paySuccess();
return; return;
} }
switch (payType.type) { switch (payType.type) {
case 'alipay': // 保留文件1的微信支付逻辑新增空值判断
if (this.$util.isWeiXin()) {
var wx_alipay = encodeURIComponent(res.data.data);
this.$util.redirectTo('/pages_tool/pay/wx_pay', {
wx_alipay: wx_alipay,
out_trade_no: this.payInfo.out_trade_no
}, '', 'redirectTo');
this.repeatFlag = false;
} else {
this.repeatFlag = false;
location.href = res.data.data;
this.checkPayStatus();
}
break;
case 'wechatpay': case 'wechatpay':
if (this.$util.isWeiXin()) { if (this.$util.isWeiXin()) {
if (uni.getSystemInfoSync().platform == 'ios') { if (uni.getSystemInfoSync().platform == 'ios') {
@@ -306,25 +324,29 @@ export default {
success: jssdkRes => { success: jssdkRes => {
var wxJS = new Weixin(), var wxJS = new Weixin(),
payData = res.data.data; payData = res.data.data;
// 新增空值判断避免读取undefined属性
if (!payData) {
this.$util.showToast({ title: '微信支付参数获取失败' });
this.close();
return;
}
wxJS.init(jssdkRes.data); wxJS.init(jssdkRes.data);
wxJS.pay({ wxJS.pay({
timestamp: payData.timestamp ? payData.timestamp : payData.timeStamp, timestamp: payData.timestamp ? payData.timestamp : payData.timeStamp,
nonceStr: payData.nonceStr, nonceStr: payData.nonceStr,
package: payData.package, package: payData.package,
signType: payData.signType, signType: payData.signType,
paySign: payData.paySign paySign: payData.paySign
}, },
res => { res => {
if (res.errMsg == 'chooseWXPay:ok') { if (res.errMsg == 'chooseWXPay:ok') {
this.paySuccess(); this.paySuccess();
this.repeatFlag = false;
} else { } else {
this.$util.showToast({ this.$util.showToast({
title: res.errMsg title: res.errMsg
}); });
setTimeout(() => { setTimeout(() => {
this.close(); this.close();
this.repeatFlag = false;
}, 1500) }, 1500)
} }
}, },
@@ -333,41 +355,126 @@ export default {
title: '您已取消支付' title: '您已取消支付'
}); });
this.resetpay(); this.resetpay();
this.repeatFlag = false;
} }
); );
} }
}); });
} else { } else {
this.repeatFlag = false; // 新增判断res.data.url是否存在
if (!res.data.url) {
this.$util.showToast({ title: '微信支付链接获取失败' });
this.close();
return;
}
location.href = res.data.url; location.href = res.data.url;
this.checkPayStatus(); this.checkPayStatus();
} }
break; break;
case 'offlinepay': // 保留文件1的支付宝支付逻辑
this.$util.redirectTo('/pages_tool/pay/offlinepay', { case 'alipay':
outTradeNo: this.payInfo.out_trade_no if (this.$util.isWeiXin()) {
}); // 新增判断res.data.data是否存在
this.repeatFlag = false; if (!res.data.data) {
this.$util.showToast({ title: '支付宝支付参数获取失败' });
this.close();
return;
}
var wx_alipay = encodeURIComponent(res.data.data);
this.$util.redirectTo('/pages_tool/pay/wx_pay', {
wx_alipay: wx_alipay,
out_trade_no: this.payInfo.out_trade_no
}, '', 'redirectTo');
} else {
// 新增判断res.data.data是否存在
if (!res.data.data) {
this.$util.showToast({ title: '支付宝支付链接获取失败' });
this.close();
return;
}
location.href = res.data.data;
this.checkPayStatus();
}
break;
// 新增华为支付分支处理沿用文件1范式补充空值判断
case 'huaweipay':
// 新增先判断res.data.data是否存在
if (!res.data.data) {
this.$util.showToast({ title: '华为支付参数获取失败' });
this.close();
return;
}
const systemInfo = uni.getSystemInfoSync();
const isHuaweiQuickApp = systemInfo.platform === 'quickapp-huawei';
// 华为快应用尝试原生SDK唤起
if (isHuaweiQuickApp && res.data.data.orderInfo) {
try {
const huaweiPay = require('@service.pay.huawei');
huaweiPay.pay({
orderInfo: res.data.data.orderInfo,
success: () => {
this.paySuccess();
},
fail: (err) => {
// 原生失败跳H5链接
if (res.data.data.payUrl) {
location.href = res.data.data.payUrl;
this.checkPayStatus();
} else {
this.$util.showToast({
title: `华为支付失败:${err.message}`
});
this.close();
}
}
});
} catch (sdkErr) {
// SDK加载失败跳H5
if (res.data.data.payUrl) {
location.href = res.data.data.payUrl;
this.checkPayStatus();
} else {
this.$util.showToast({
title: '华为支付SDK加载失败'
});
this.close();
}
}
} else if (res.data.data.payUrl) {
// 非华为快应用直接跳H5链接
location.href = res.data.data.payUrl;
this.checkPayStatus();
} else {
this.$util.showToast({
title: '未获取到华为支付链接'
});
this.close();
}
break; break;
} }
} else { } else {
this.$util.showToast({ this.$util.showToast({
title: res.message title: res.message
}); });
this.repeatFlag = false;
} }
}, },
fail: res => { fail: res => {
uni.hideLoading(); uni.hideLoading();
this.repeatFlag = false; // 重置文件2的防重复标记
this.$util.showToast({ this.$util.showToast({
title: 'request:fail' title: 'request:fail'
}); });
this.repeatFlag = false;
} }
}); });
}, },
/**
* 线下支付处理保留文件2原有逻辑
*/
payOffline() {
this.$util.redirectTo('/pages_tool/pay/offlinepay', {
outTradeNo: this.payInfo.out_trade_no
});
this.repeatFlag = false;
},
checkPayStatus() { checkPayStatus() {
this.timer = setInterval(() => { this.timer = setInterval(() => {
this.$api.sendRequest({ this.$api.sendRequest({
@@ -392,114 +499,160 @@ export default {
// #ifdef MP // #ifdef MP
pay() { pay() {
var payType = this.payTypeList[this.payIndex]; var payType = this.payTypeList[this.payIndex];
// 保留文件2的线下支付逻辑
if (!payType || payType.type === 'offlinepay') {
this.$util.redirectTo('/pages_tool/pay/offlinepay', {
outTradeNo: this.payInfo.out_trade_no
});
this.repeatFlag = false;
return;
}
// 保留文件2的流程控制
if (!this.resetPayComplete) {
uni.hideLoading();
this.$util.showToast({
title: '支付取消中,请稍后再试!'
});
this.repeatFlag = false;
return;
}
// 复用文件1的小程序端核心逻辑调用/api/pay/pay
this.$api.sendRequest({ this.$api.sendRequest({
url: '/api/pay/pay', url: '/api/pay/pay',
data: { data: {
out_trade_no: this.payInfo.out_trade_no, out_trade_no: this.payInfo.out_trade_no,
pay_type: payType ? payType.type : '', pay_type: payType.type,
scene: uni.getStorageSync('is_test') ? 1175 : wx.getLaunchOptionsSync().scene, scene: uni.getStorageSync('is_test') ? 1175 : wx.getLaunchOptionsSync().scene,
is_balance: this.isBalance is_balance: this.isBalance
}, },
success: res => { success: res => {
uni.hideLoading(); uni.hideLoading();
this.repeatFlag = false; // 重置文件2的防重复标记
if (res.code >= 0) { if (res.code >= 0) {
if (res.data.pay_success) { if (res.data.pay_success) {
this.paySuccess(); this.paySuccess();
this.repeatFlag = false;
return; return;
} }
if (payType.type == 'offlinepay') { var payData = res.data.data;
this.$util.redirectTo('/pages_tool/pay/offlinepay', {
outTradeNo: this.payInfo.out_trade_no
});
this.repeatFlag = false;
} else {
var payData = res.data.data;
// #ifdef MP-WEIXIN switch (payType.type) {
var scene = uni.getStorageSync('is_test') ? 1175 : wx.getLaunchOptionsSync().scene; // 保留文件1的微信支付逻辑新增空值判断
if ([1175, 1176, 1177, 1191, 1195].indexOf(scene) != -1) { case 'wechatpay':
uni.requestOrderPayment({ // 新增:空值判断
timeStamp: payData.timeStamp, if (!payData) {
nonceStr: payData.nonceStr, this.$util.showToast({ title: '微信支付参数获取失败' });
package: payData.package, this.close();
signType: payData.signType, return;
paySign: payData.paySign, }
var scene = uni.getStorageSync('is_test') ? 1175 : wx.getLaunchOptionsSync().scene;
if ([1175, 1176, 1177, 1191, 1195].indexOf(scene) != -1) {
uni.requestOrderPayment({
timeStamp: payData.timeStamp,
nonceStr: payData.nonceStr,
package: payData.package,
signType: payData.signType,
paySign: payData.paySign,
success: res => {
this.paySuccess();
},
fail: res => {
this.handlePayFail(res);
}
});
return;
}
uni.requestPayment({
provider: 'wxpay',
...payData,
success: res => { success: res => {
this.paySuccess(); this.paySuccess();
this.repeatFlag = false;
}, },
fail: res => { fail: res => {
this.flag = false; this.handlePayFail(res);
if (res.errMsg == 'requestOrderPayment:fail cancel') {
this.$util.showToast({
title: '您已取消支付'
});
this.resetpay();
this.repeatFlag = false;
} else {
uni.showModal({
content: '支付失败,失败原因: ' + res.errMsg,
showCancel: false
});
setTimeout(() => {
this.close();
this.repeatFlag = false;
}, 1500)
}
} }
}); });
return break;
} // 保留文件1的支付宝支付逻辑新增空值判断
// #endif case 'alipay':
// 新增:空值判断
uni.requestPayment({ if (!payData) {
provider: payType.provider, this.$util.showToast({ title: '支付宝支付参数获取失败' });
...payData, this.close();
success: res => { return;
this.paySuccess();
this.repeatFlag = false;
},
fail: res => {
this.flag = false;
if (res.errMsg == 'requestPayment:fail cancel') {
this.$util.showToast({
title: '您已取消支付'
});
this.resetpay();
this.repeatFlag = false;
} else {
uni.showModal({
content: '支付失败,失败原因: ' + res.errMsg,
showCancel: false
});
setTimeout(() => {
this.close();
this.repeatFlag = false;
}, 1500)
}
} }
}); uni.requestPayment({
provider: 'alipay',
...payData,
success: res => {
this.paySuccess();
},
fail: res => {
this.handlePayFail(res);
}
});
break;
// 新增华为支付小程序端逻辑(补充空值判断)
case 'huaweipay':
// 新增:空值判断
if (!payData) {
this.$util.showToast({ title: '华为支付参数获取失败' });
this.close();
return;
}
if (payData.payUrl) {
// 小程序端跳WebView页面
this.$util.redirectTo('/pages/Pay/Pay', {
payUrl: payData.payUrl,
outTradeNo: this.payInfo.out_trade_no
});
} else {
this.$util.showToast({
title: '未获取到华为支付链接'
});
this.close();
}
break;
} }
} else { } else {
this.$util.showToast({ this.$util.showToast({
title: res.message title: res.message
}); });
this.repeatFlag = false;
} }
}, },
fail: res => { fail: res => {
uni.hideLoading(); uni.hideLoading();
this.repeatFlag = false; // 重置文件2的防重复标记
this.$util.showToast({ this.$util.showToast({
title: 'request:fail' title: 'request:fail'
}); });
this.repeatFlag = false;
} }
}); });
}, },
/**
* 统一处理支付失败复用文件1逻辑
*/
handlePayFail(res) {
this.flag = false;
if (res.errMsg.includes('cancel')) {
this.$util.showToast({
title: '您已取消支付'
});
this.resetpay();
} else {
uni.showModal({
content: '支付失败,失败原因: ' + res.errMsg,
showCancel: false
});
setTimeout(() => {
this.close();
}, 1500)
}
},
// #endif // #endif
/** /**
* 支付成功之后跳转 * 支付成功之后跳转(真实业务逻辑)
*/ */
paySuccess() { paySuccess() {
if (this.payInfo.event == 'BlindboxGoodsOrderPayNotify') { if (this.payInfo.event == 'BlindboxGoodsOrderPayNotify') {
@@ -516,7 +669,7 @@ export default {
} }
}, },
/** /**
* 重置支付单据 * 重置支付单据(真实业务逻辑)
*/ */
resetpay() { resetpay() {
this.resetPayComplete = false; this.resetPayComplete = false;
@@ -643,6 +796,9 @@ export default {
.icon-zhifubaozhifu- { .icon-zhifubaozhifu- {
color: #00a0e9; color: #00a0e9;
} }
.icon-huawei-pay {
color: #c7000b; // 华为支付品牌色
}
.icon-checkboxblank { .icon-checkboxblank {
font-size: 40rpx; font-size: 40rpx;

12
main.js
View File

@@ -27,7 +27,6 @@ Vue.prototype.$lang = Lang.lang; //解析语言包
Vue.prototype.$config = Config; Vue.prototype.$config = Config;
// #ifdef H5 // #ifdef H5
EventBus.setDomBridge(DomEventBridge) EventBus.setDomBridge(DomEventBridge)
// #endif // #endif
@@ -59,6 +58,17 @@ Vue.component('ns-login', NsLogin);
import PrivacyPopup from '@/components/wx-privacy-popup/privacy-popup.vue'; import PrivacyPopup from '@/components/wx-privacy-popup/privacy-popup.vue';
Vue.component('privacy-popup', PrivacyPopup) Vue.component('privacy-popup', PrivacyPopup)
// ========== 新增注册diy系列组件 ==========
import DiyBottomNav from '@/components/diy-components/diy-bottom-nav.vue'
import DiyGroup from '@/components/diy-components/diy-group.vue'
import DiyCategory from '@/components/diy-components/diy-category.vue'
import DiyIcon from '@/components/diy-components/diy-icon.vue' // 补充diy-icon
Vue.component('diy-bottom-nav', DiyBottomNav) // 修正拼写错误
Vue.component('diy-group', DiyGroup)
Vue.component('diy-category', DiyCategory)
Vue.component('diy-icon', DiyIcon) // 注册diy-icon
// ========== 新增结束 ==========
const app = new Vue({ const app = new Vue({
...App, ...App,
store store

View File

@@ -1,7 +1,8 @@
{ {
"description": "项目配置文件", "description": "项目配置文件",
"packOptions": { "packOptions": {
"ignore": [] "ignore": [],
"include": []
}, },
"setting": { "setting": {
"urlCheck": true, "urlCheck": true,
@@ -37,20 +38,20 @@
"userConfirmedBundleSwitch": false, "userConfirmedBundleSwitch": false,
"packNpmManually": false, "packNpmManually": false,
"packNpmRelationList": [], "packNpmRelationList": [],
"minifyWXSS": true "minifyWXSS": true,
"compileWorklet": false,
"minifyWXML": true,
"localPlugins": false,
"disableUseStrict": false,
"useCompilerPlugins": false,
"condition": false,
"swc": false,
"disableSWC": true
}, },
"compileType": "miniprogram", "compileType": "miniprogram",
"libVersion": "2.16.1", "libVersion": "3.12.0",
"appid": "wx29215aa1bd97bbd6", "appid": "wx29215aa1bd97bbd6",
"projectname": "niushop_b2c_v4_uniapp", "projectname": "niushop_b2c_v4_uniapp",
"debugOptions": {
"hidedInDevtools": []
},
"scripts": {},
"staticServerOptions": {
"baseURL": "",
"servePath": ""
},
"isGameTourist": false, "isGameTourist": false,
"condition": { "condition": {
"search": { "search": {
@@ -71,5 +72,7 @@
"miniprogram": { "miniprogram": {
"list": [] "list": []
} }
} },
"simulatorPluginLibVersion": {},
"editorSetting": {}
} }