diff --git a/package.json b/package.json index e323b41..da82bf5 100644 --- a/package.json +++ b/package.json @@ -79,6 +79,7 @@ "@vue/shared": "^3.0.0", "core-js": "^3.6.5", "flyio": "^0.6.2", + "js-util-all": "^1.0.6", "regenerator-runtime": "^0.12.1", "vue": "^2.6.11", "vuex": "^3.2.0" diff --git a/src/common/api/auth.js b/src/common/api/auth.js new file mode 100644 index 0000000..33c74df --- /dev/null +++ b/src/common/api/auth.js @@ -0,0 +1,27 @@ +/* + * @Author: ch + * @Date: 2022-07-09 16:28:10 + * @LastEditors: ch + * @LastEditTime: 2022-07-09 17:25:13 + * @Description: file content + */ + +import {ToAsyncAwait, MsbRequest} from '@/common/utils'; + +// 第三方鉴权服务 +const AUTH_URL = '/third'; +const APPID = 'wxd2015f0c56defa02'; + + +/** + * 获取授权页面地址 + * @param {*} data + */ +export const ApiGetAuthUrl = (params) => + ToAsyncAwait(MsbRequest.get(`${AUTH_URL}/wx/mp/getAuthorizationUrl/${params.appid}`, params)); +/** + * 获取openId + * @param {*} data + */ +export const ApiGetOpenId = ({code, appid}) => + ToAsyncAwait(MsbRequest.get(`${AUTH_URL}/wx/mp/getOpenId/${appid}`, { code })); \ No newline at end of file diff --git a/src/common/api/pay.js b/src/common/api/pay.js new file mode 100644 index 0000000..93ac043 --- /dev/null +++ b/src/common/api/pay.js @@ -0,0 +1,26 @@ +/* + * @Author: ch + * @Date: 2022-07-09 16:27:57 + * @LastEditors: ch + * @LastEditTime: 2022-07-09 18:29:05 + * @Description: file content + */ + +import {ToAsyncAwait, MsbRequest} from '@/common/utils'; + +// 第三方鉴权服务 +const AUTH_URL = '/third'; + + +/** + * 获取订单信息 + * @param {*} data + */ +export const ApiGetOrderInfo = ({payOrderNo}) => + ToAsyncAwait(MsbRequest.get(`/payCenter/payCenter/prepayOrder/${payOrderNo}`)); +/** + * 获取openId + * @param {*} data + */ +export const ApiPostH5Pay = (data) => + ToAsyncAwait(MsbRequest.put(`payCenter/payCenter/cashierPay`, data)); \ No newline at end of file diff --git a/src/common/plugins/msbUniRequest.js b/src/common/plugins/msbUniRequest.js new file mode 100644 index 0000000..58e2d65 --- /dev/null +++ b/src/common/plugins/msbUniRequest.js @@ -0,0 +1,123 @@ +/* + * @Author: ch + * @Date: 2022-03-17 16:36:59 + * @LastEditors: ch + * @LastEditTime: 2022-04-22 20:30:03 + * @Description: 针对uniapp request请求做了一次封装,使用思维参考axios + * + * + * 方法 + * method(option) 自定义请求,同uni.request + * get(url, params, header) url 请求地址 params 请求参数 + * header 请求头会针对当前请求头设置特定的请求头。传了此参数request拦截器会失效 + * post(url, data, header) 同上 + * put(url, data, header) 同上 + * delete(url, data, header) 同上 + * use(hookName, callback) 注入hook拦截器 hookName 拦截器名(request/response/error) callback拦截器具体见拦截器说明 + * + * 属性 + * baseUrl 请求地址前缀 + * + * 拦截器 + * request 请求前拦截,在这可统一设置请求头,请求体等参数。uni.request的第一个参数option都可以重置 + * success 请求成功结果拦截 + * error 请求错误拦截 + * + * 示例 + * const myReq = new MsbUniRequest(); + * myReq.baseUrl = 'xxxx' + * myReq.use('request', (option)=>{ + * // option 返回请求配置 + * .....这里可以对option做一系列操作 + * return option //最后返回一个正确的请求配置 + * }) + * myReq.use('success', (res)=>{ + * //res 返回请求结果 + * let newRes = ..... //这里可以对请求结果做统一处理 + * return newRes + * }) + * + * myReq.use('error', (error)=>{ + * //error 返回错误结果 + * let newError = ..... //这里可以对请求错误做统一处理 + * return newError + * }) + */ +class MsbUniRequest { + constructor (option){ + this.baseUrl = ''; + this.header = { + repeat : true + } + this.hook = { + request : null, + success : null, + error : null + } + + } + method(option){ + option.header = {...this.header,...option.header}; + option.url = this.baseUrl + option.url; + if(this.hook.request){ + option = this.hook.request(option); + }; + + if(!option){ + throw new Error('没有请求配置,或是request拦截未做return'); + } + if(option.constructor === Promise){ + return option + } + return new Promise((resolve, reject)=>{ + uni.request({ + ...option, + success: res => { + const response = res || res[1]; + // 200 - 399状态为正常 + if(response.statusCode >= 200 && response.statusCode < 400){ + if(!this.hook.success){ + resolve(response); + }else{ + let newRes = this.hook.success(response, option); + // 业务结果处理可能为一个Promise对象,根据结果调用错误或正确状态 + if(newRes && newRes.constructor === Promise){ + newRes.then(res => { + resolve(res); + }, error =>{ + reject(error); + }) + }else{ + resolve(newRes); + } + } + return false; + } + reject(this.hook.error ? this.hook.error(response, option) : response); + + }, + fail: error =>{ + reject(this.hook.error ? this.hook.error(error, option) : error); + + } + }); + }); + } + use(hookName, cb){ + this.hook[hookName] = cb; + } + get(url, data, header){ + return this.method({method : 'GET', url, data, header}); + } + post(url, data, header){ + return this.method({method : 'POST', url, data, header}); + } + put(url, data, header){ + return this.method({method : 'PUT', url, data, header}); + } + delete(url, data, header){ + return this.method({method : 'DELETE', url, data, header}); + } +} + +export default MsbUniRequest; \ No newline at end of file diff --git a/src/common/utils/alipay.js b/src/common/utils/alipay.js deleted file mode 100644 index dffee51..0000000 --- a/src/common/utils/alipay.js +++ /dev/null @@ -1,50 +0,0 @@ -/* - * @Author: ch - * @Date: 2022-04-29 14:26:10 - * @LastEditors: ch - * @LastEditTime: 2022-06-30 16:03:35 - * @Description: file content - */ - -import { ApiPostAliH5Pay, ApiPostAliAppPay } from '@/common/api/pay'; -import ENV from '@/common/config/env'; -export const Alipay = async ({orderId})=>{ - - // #ifdef APP-PLUS - const {error, result} = await ApiPostAliAppPay({orderId}); - if(error){ - uni.$u.toast(error.message); - return false; - } - const par = result.payDataInfo; - uni.requestPayment({ - provider: 'alipay', - orderInfo :par.payData, - success(res) { - uni.navigateTo({ - url : `/payResult?orderId=${orderId}&payType=appWx` - }); - }, - fail(e) { - uni.navigateTo({ - url : `/payResult?orderId=${orderId}&payType=appWx` - }); - } - }).then(res => { - console.log('res',res); - }) - // #endif - - // #ifdef H5 - const { error, result } = await ApiPostAliH5Pay({ - orderId, - returnUrl : decodeURIComponent(`${ENV.staticUrl}/payResult?orderId=${orderId}&payType=alih5`) - }); - if(error){ - uni.$u.toast(error.message); - return false; - } - window.location.href = result.payDataInfo.payUrl; - // #endif - -} \ No newline at end of file diff --git a/src/common/utils/index.js b/src/common/utils/index.js new file mode 100644 index 0000000..03d85af --- /dev/null +++ b/src/common/utils/index.js @@ -0,0 +1,14 @@ +/* + * @Author: ch + * @Date: 2022-03-22 16:52:28 + * @LastEditors: ch + * @LastEditTime: 2022-07-09 16:46:43 + * @LastEditTime: 2022-06-29 17:22:32 + * @Description: 所有工具类统一在这输出 + */ +import * as util from './utils'; +import * as requset from './requset'; +export * from './utils'; +export * from './requset'; + +export default { ...util, ...requset} diff --git a/src/common/utils/requset.js b/src/common/utils/requset.js new file mode 100644 index 0000000..54e3770 --- /dev/null +++ b/src/common/utils/requset.js @@ -0,0 +1,34 @@ +/* + * @Author: ch + * @Date: 2022-03-17 17:42:32 + * @LastEditors: ch + * @LastEditTime: 2022-07-09 16:56:53 + * @Description: 项目接口请求统一处理器,返回一个需要token和不需要token的请求封装方法 + */ + +import MsbUniRequest from '@/common/plugins/msbUniRequest'; + + +const MsbRequest = new MsbUniRequest(); +MsbRequest.baseUrl = process.env.VUE_APP_BASE_URL; + +MsbRequest.use('success', (response, option) =>{ + if(response.statusCode === 200){ + const result = response.data; + if(result.code === 'SUCCESS'){ + return result.data; + } + return Promise.reject(result); + } + return response; +}); +MsbRequest.use('error', (error, option) =>{ + return {message:error.errMsg,code:error.statusCode} +}); + + + +export { + MsbRequest +} + diff --git a/src/common/utils/uniUtilsIndex.js b/src/common/utils/uniUtilsIndex.js new file mode 100644 index 0000000..b9f0f3b --- /dev/null +++ b/src/common/utils/uniUtilsIndex.js @@ -0,0 +1,34 @@ +/* + * @Author: ch + * @Date: 2022-07-09 18:02:07 + * @LastEditors: ch + * @LastEditTime: 2022-07-09 18:35:59 + * @Description: 这个文件里面的方法都是直接挂载在uni对象和this上的 + */ +import Vue from 'vue'; +const _$toast = (msg, duration = 3000) => { + return new Promise((reverse, reject) => { + uni.showToast({ + title: msg, + icon: 'none', + duration, + success() { + setTimeout(() => { + reverse(true) + }, duration) + }, + fail() { + reject(false) + } + }); + + }) +} + +const utils = { + _$toast +} +for (let key in utils) { + uni[key] = utils[key]; + Vue.prototype[key] = utils[key]; +} \ No newline at end of file diff --git a/src/common/utils/utils.js b/src/common/utils/utils.js new file mode 100644 index 0000000..7a26991 --- /dev/null +++ b/src/common/utils/utils.js @@ -0,0 +1,27 @@ +/* + * @Author: ch + * @Date: 2022-03-17 19:15:10 + * @LastEditors: ch + * @LastEditTime: 2022-07-09 16:55:11 + * @Description: 一些无法归类的公共方法容器 + */ + +import { + toAsyncAwait as ToAsyncAwait, + isPhone as IsPhone, + formatDate as FormatDate, + creatUuid as CreateUUID, + formatSearchJson as FormatSearchJson, + formatJsonSearch as FormatJsonSearch + +} from "js-util-all"; + +// 工具类的文件需要把文件提供的工具类统一放最下方做一个统一输出 +export { + // async await 标识结果处理 + ToAsyncAwait, + // 判断是否为手机号 + IsPhone, + FormatSearchJson, + FormatJsonSearch, +} \ No newline at end of file diff --git a/src/common/utils/wxpay.js b/src/common/utils/wxpay.js deleted file mode 100644 index af75ff2..0000000 --- a/src/common/utils/wxpay.js +++ /dev/null @@ -1,78 +0,0 @@ -/* - * @Author: ch - * @Date: 2022-04-29 14:26:10 - * @LastEditors: ch - * @LastEditTime: 2022-07-08 17:38:48 - * @Description: file content - */ - -import { ApiPostWxH5Pay, ApiPostWxJsApiPay, ApiPostWxAppPay } from '@/common/api/pay'; -import ENV from '@/common/config/env'; -export const Wxpay = async ({orderId,openId})=>{ - - // #ifdef APP-PLUS - const {error, result} = await ApiPostWxAppPay({orderId}); - const par = result.payDataInfo; - uni.requestPayment({ - provider: 'wxpay', - orderInfo :{ - "appid": par.appId, // 微信开放平台 - 应用 - AppId - "noncestr": par.nonceStr, // 随机字符串 - "package": par.packageValue, // 固定值 - "partnerid": par.partnerId, // 微信支付商户号 - "prepayid": par.prepayId, // 统一下单订单号 - "timestamp": par.timeStamp ,// 时间戳(单位:秒) - "sign": par.sign // 签名,这里用的 MD5 签名 - }, - success(res) { - uni.navigateTo({ - url : `/payResult?orderId=${orderId}&payType=appWx` - }); - }, - fail(e) { - uni.navigateTo({ - url : `/payResult?orderId=${orderId}&payType=appWx` - }); - } - }).then(res => { - console.log('res',res); - }) - // #endif - - // #ifdef H5 - // 有openId则判断在微信浏览器内 - if(openId) { - // 微信JSAPI - const {error, result} = await ApiPostWxJsApiPay({orderId,openId}); - if(error){ - uni.$u.toast(error.message); - return false; - } - const par = result.payDataInfo; - WeixinJSBridge.invoke('getBrandWCPayRequest', { - appId : par.appId, - timeStamp : par.timeStamp, - nonceStr : par.nonceStr, - package: par.packageValue, - signType : par.signType, - paySign : par.paySign - }, res => { - if(res.err_msg !== 'get_brand_wcpay_request:cancel'){ - uni.navigateTo({ - url : `/payResult?orderId=${orderId}&payType=wxjsapi` - }); - } - }) - }else{ - // h5支付 - const {error, result} = await ApiPostWxH5Pay({orderId}); - if(error){ - uni.$u.toast(error.message); - return false; - } - const redirect_url = decodeURIComponent(`${ENV.staticUrl}/payResult?orderId=${orderId}&payType=wxh5`); - window.location.href = `${result.payDataInfo.h5Url}&redirect_url=${redirect_url}`; - } - // #endif - -} \ No newline at end of file diff --git a/src/main.js b/src/main.js index 7f88dd0..6caef2a 100644 --- a/src/main.js +++ b/src/main.js @@ -1,6 +1,59 @@ -import Vue from 'vue' -import App from './App' +/* + * @Author: ch + * @Date: 2022-07-08 11:46:30 + * @LastEditors: ch + * @LastEditTime: 2022-07-09 18:18:11 + * @Description: file content + */ +import {FormatSearchJson} from '@/common/utils'; +import {ApiGetOpenId, ApiGetAuthUrl} from '@/common/api/auth'; +import { ApiGetOrderInfo } from '@/common/api/pay'; +import Vue from 'vue'; +import App from './App'; +import '@/common/utils/uniUtilsIndex' + +// 微信打开需要授权 +const ua = navigator ? navigator.userAgent.toLowerCase() : ''; + +if (ua.includes('micromessenger')) { + const openId = localStorage.getItem('openId'); + if(!openId){ + let query = FormatSearchJson(window.location.search); + if(query.code){ + ApiGetOpenId({ + code : query.code + }).then(({error, result}) => { + if(error){ + // uni.$u.toast(error.message); + return false; + } + store.commit('SET_OPEN_ID', result.openId); + }) + } else { + + ApiGetOpenId({ payOrderNo: query.payOrderNo }).then(res => { + ApiGetAuthUrl({ + redirectUrl : window.location.href, + scope : 'snsapi_base' + }).then(({result, error}) => { + if(error){ + // uni.$u.toast(error.message); + uni.showToast({ + title: error.message, + icon: 'none', + duration : 2000 + }) + return false; + } + window.location.replace(result); + }) + }); + + } + } + +} Vue.config.productionTip = false App.mpType = 'app' diff --git a/src/pages/wapPay.vue b/src/pages/wapPay.vue index 42fc6cf..8c4bc85 100644 --- a/src/pages/wapPay.vue +++ b/src/pages/wapPay.vue @@ -2,7 +2,7 @@ * @Author: ch * @Date: 2022-07-08 11:46:30 * @LastEditors: ch - * @LastEditTime: 2022-07-09 15:43:47 + * @LastEditTime: 2022-07-09 18:34:53 * @Description: file content -->