//抽离showToast
showToastLoading(title = '...', icon = 'none', duration = 2000) {
uni.showToast({
title,
icon,
duration,
mask: true,
});
},
//隐藏loading
hideLoading(title = '...') {
uni.showToast({
title,
icon: 'loading',
mask: true,
duration: 100,
});
},
//加载中
showLoading(title = '...') {
uni.showToast({
title,
icon: 'loading',
mask: true,
duration: 30000,
});
}
//获取元素信息
getRect(selector) {
return new Promise((resolve) => {
let view = uni.createSelectorQuery().in(this).select(selector);
view
.fields(
{
size: true,
scrollOffset: true,
rect: true,
},
(data) => {
resolve(data);
}
)
.exec();
});
},
//点击查看图片
previewImages(urls = [], current = 0) {
if (!Array.isArray(urls)) urls = [urls];
uni.previewImage({
urls,
current,
});
}
const pay = {
paypalPay: (params) => {
console.log(params)
let src = params.links.find(x => x.rel == 'approve')?.href
var urlStr = encodeURI(src)
plus.runtime.openURL(urlStr)
plus.nativeUI.closeWaiting()
return
//uniapp官方存在bug。使用webview方式实现paypal支付
let orderInfo = {
clientId: params.clientId, //开发者中心clientId
orderId: params.orderId, //订单id
userAction: params.userAction, //按钮样式 paynow/continue
currency: params.currency, //币种
environment: params.environment, //运行环境 sandbox(沙盒) / live(线上)
};
uni.getProvider({
service: 'payment',
success: function(res) {
console.log(res);
if (~res.provider.indexOf('paypal')) {
uni.requestPayment({
provider: 'paypal',
orderInfo: orderInfo,
success: function(response) {
console.log('success:' + JSON.parse(response.rawdata));
},
fail: function(err) {
console.log('fail:' + JSON.stringify(err));
},
});
} else {
uni.showToast({
title: 'error',
icon: 'none',
});
}
},
});
plus.nativeUI.closeWaiting()
},
applePay: function(params) {
uni.requestPayment({
provider: 'appleiap',
orderInfo: {
productid: params.iapPriceId,
username: params.orderId, // 用户标识
optimize: true, // 设置 optimize: true 解决丢单问题
},
/*
orderInfo可传参数一览
productid: (String 类型 )(必填) 商品的标识,你在苹果那里添加的商品标识
username: (String 类型 )(可选) 购买用户名称,我喜欢在这里传入订单号,这样支付成功时就可以获得订单号
quantity: (String 类型 )(可选) 商品数量,默认为 "1"
optimize:(Boolean)(可选) HX 3.1.10 版本新增参数,解决用户未绑定支付方式造成的丢单问题;
*/
success: (e) => {
console.log(e);
//这里把参数返回服务器进行二次验证
//这里再次验证是否订单真实有效
// 购买成功 更新用户vip时长
uni.showModal({
content: 'success: ' + e,
showCancel: false,
});
},
fail: (e) => {
console.log(e);
uni.showModal({
content: 'fail: ' + e.errMsg,
showCancel: false,
});
},
complete: () => {
console.log('payment结束');
plus.nativeUI.closeWaiting()
},
});
},
//初始化iap
initIap: function() {
plus.payment.getChannels(
(channels) => {
console.log(channels);
for (var i in channels) {
var channel = channels[i];
// 获取 id 为 'appleiap' 的 channel
if (channel.id == 'appleiap') {
iap = channel;
// my_accurate_weather支付参数
iap.requestOrder(
['my_accurate_weather_', 'my_accurate_weather_'],
(orderList) => {
//必须调用此方法才能进行 iap 支付
console.log('requestOrder success666: ' + JSON.stringify(orderList));
},
(e) => {
console.log('requestOrder failed: ' + JSON.stringify(e));
}
);
}
}
},
function(e) {
console.log('获取iap支付通道失败:' + e.message);
}
);
},
};
export default pay;
/hybrid/html/paypal.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>payapl</title>
</head>
<style>
#app {
padding-top: 10px;
}
</style>
<body>
<div id="app">
</div>
</body>
<script type="text/javascript" src="./js/uniWebview.js"></script>
<!-- client-id后边放你的 -->
<script
src="https://www.paypal.com/sdk/js?client-id=AWfC78tSqcrwXgjkdymrHinkjsVHJcwVjeQySYxj1x0wbBBClKCrB6SMDjvpiIrQogi6WnA3DiqtxKfL">
</script>
<script>
document.addEventListener('UniAppJSBridgeReady', function() {
var url = location.href.substring(location.href.indexOf('?') + 1)
console.log(url)
paypal.Buttons({
createOrder: (data, actions) => {
return url;
},
onApprove: function(data, actions) {
return actions.order.capture().then(function(details) {
console.log(details)
plus.nativeUI.alert('Payment succeeded')
uni.navigateBack({
delta: 1
});
return "";
});
}
}).render('#app');
// 把付款按钮放id为app的盒子里
});
</script>
</html>
//push 推送
export default {
// 获取所有推送消息
getAllMessages() {
return plus.push.getAllMessage;
},
/**
* 设置角标
* 1. 传入数字,设置角标为该数字
* 2. 不传入数字,设置角标为当前消息数量
* @param {*} number
*/
changeBadge(number) {
const message = this.getAllMessages();
plus.push.setBadgeNumber(number || message.length);
},
/**
* @param {*} content 消息内容
* @param {*} [payload={}] 消息附加数据
* @param {*} options 消息配置
* @param {*} isChange 是否改变角标
*/
createMessage(content, payload = {}, options, isChange = true) {
plus.push.createMessage(...arguments); // 创建消息
const delay = options.delay ? ~~options.delay * 1000 : 0; // 延迟时间
setTimeout(() => {
isChange && this.changeBadge(); // 改变角标
}, delay);
},
/**
* @param {number} message
* @description
* - 传入message时,删除消息列表中的message;
* - 不传参数:则全部清空
*/
remove(message, isChange) {
message ? plus.push.remove(message) : plus.push.clear();
isChange && this.changeBadge();
},
/**
* @description 需要在App.vue中onLaunch中调用
*/
init() {
// plus.push.setAutoNotification(true); // setAutoNotification 默认就是true
plus.push.addEventListener('click', (message) => {
let {
url
} = message.payload;
if (url) {
uni.navigateTo({
url,
success: () => {}, // 可以根据需求删除消息 this.remove(message);
complete: () => {}, // 可以根据需求删除消息 this.remove(message);
});
}
});
plus.push.addEventListener('receive', (message) => {
console.log('接收消息', ...message);
var platform = uni.getSystemInfoSync().platform;
if (platform == 'ios') {
//ios平台应用在前台时,不能收到通知消息,只能走透传,在创建一条本地消息
if (message.type == 'receive') {
// 创建本地消息,发送的本地消息也会被receive方法接收到,但没有type属性
this.createMessage(...message);
}
} else if (platform == 'android') {
this.createMessage(...message);
}
});
},
};
// 此vm参数为页面的实例,可以通过它引用vuex中的变量
import utils from '@/common/utils.js';
import {
HTTP_REQUEST_URL, //请求地址
HEADER, //请求头
PRE_URL //请求地址前缀
} from '@/config.js';
const returnCode = {
OK: 200,
logout: 301,
error: 404,
};
module.exports = (vm) => {
//请求携带参数
const QUERY = {};
// 初始化请求配置
uni.$u.http.setConfig((config) => {
/* config 为默认全局配置*/
config.baseURL = HTTP_REQUEST_URL + PRE_URL; /* 根域名 */
config.header = {
...HEADER,
// language: uni.getLocale().includes('zh') ? 'zh_CN' : 'en_US',
language: 'en_US',
'Accept-Language': 'en_US',
timezone: uni.$u.os() == 'ios' ? utils.getIosTimezone() : utils.getAnTimezone(),
platform: uni.$u.os(),
};
config.timeout = 60000;
return config;
});
// 请求拦截
uni.$u.http.interceptors.request.use(
(config) => {
if (!vm.$store.state.hasNet) {
// uni.showToast({
// title: vm.$store.state.tipsMsg.t_13,
// icon: 'error',
// });
return Promise.reject();
}
// 可使用async await 做异步操作
// 初始化请求拦截器时,会执行此方法,此时data为undefined,赋予默认{}
config.data = uni.$u.deepMerge(QUERY, config.data);
// 根据custom参数中配置的是否需要token,添加对应的请求头
if (config?.custom?.auth && vm.$store.state.token) {
// 可以在此通过vm引用vuex中的变量,具体值在vm.$store.state中
config.header = uni.$u.deepMerge(config.header, {
token: vm.$store.state.token,
});
}
return config;
},
(config) => {
console.log(config);
// 可使用async await 做异步操作
return Promise.reject(config);
}
);
// 响应拦截
uni.$u.http.interceptors.response.use(
(response) => {
/* 对响应成功做点什么 可使用async await 做异步操作*/
const data = response.data;
// 自定义参数
const custom = response.config?.custom;
if (data.statusCode == returnCode['logout']) {
uni.showToast({
title: data.statusMsg,
icon: 'error',
});
setTimeout(() => {
vm.$store.commit('SET_LOGOUT');
}, 800);
return Promise.reject();
}
if (data.statusCode == returnCode['error']) {
vm.$store.commit('SET_LOGOUT');
uni.showToast({
title: data.statusMsg,
icon: 'error',
});
return Promise.reject();
}
if (data.statusCode !== returnCode['OK']) {
// 如果没有显式定义custom的toast参数为false的话,默认对报错进行toast弹出提示
if (custom.toast !== false) {
uni.$u.toast(data.statusMsg);
}
// 如果需要catch返回,则进行reject
if (custom?.catch) {
return Promise.reject(data);
} else {
// 否则返回一个pending中的promise,请求不会进入catch中
return new Promise(() => {});
}
}
let res = '';
if (data.data || data.data == 0) {
res = data.data;
} else {
res = data;
}
return Promise.resolve(res);
},
(response) => {
if (response.statusCode == returnCode['error']) {
vm.$store.commit('SET_LOGOUT');
// uni.showToast({
// title: vm.$store.state.tipsMsg.t_13,
// icon: 'error',
// });
return Promise.reject();
} else {
// uni.showToast({
// title: vm.$store.state.tipsMsg.t_13,
// icon: 'error',
// });
}
// 对响应错误做点什么 (statusCode !== 200)
return Promise.reject(response);
}
);
};
//安卓获取时区
getAnTimezone() {
// #ifdef APP-PLUS
let TimeZone = plus.android.importClass("java.util.TimeZone");
let timeZone = TimeZone.getDefault()
let id = timeZone.getID() // 获取时区ID,“Asia/Shanghai”
return id
// #endif
// #ifdef H5
return Intl.DateTimeFormat().resolvedOptions().timeZone
// #endif
},
//ios 获取时区
getIosTimezone() {
return Intl.DateTimeFormat().resolvedOptions().timeZone
}
import api from '@/libs/api.js';
//阿里云oss上传
export const uploadOss = async (file) => {
let url = await submitUpload(file, getUUID(file));
return url;
};
function getUUID(file) {
let uuid = storeKey();
//获取文件后缀名最后一个点的位置
let name = file.path ? file.path : file.url
let suffix = name.substring(name.lastIndexOf('.') + 1);
return uuid + '.' + suffix;
}
/**
* 生成一个随机的Key
*/
function storeKey() {
let s = [];
let hexDigits = '0123456789abcdef';
for (let i = 0; i < 36; i++) {
s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
}
s[14] = '4';
s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);
s[8] = s[13] = s[18] = s[23] = '-';
return s.join('');
}
//阿里云直传OSS
function submitUpload(file, picName) {
return new Promise((resolve, reject) => {
api
.getOSSToken()
.then((res) => {
let keyValue = res.dir + picName;
let formData = {
name: picName,
key: keyValue,
OssAccessKeyId: res.accessid,
policy: res.policy,
Signature: res.signature,
success_action_status: 200,
};
uni.uploadFile({
url: res.host,
filePath: file.path || file.url,
name: 'file',
fileType: "image",
formData: formData,
success: () => {
let src = res.host + '/' + keyValue;
console.log(src)
resolve(src);
},
fail: (error) => {
reject(error);
},
});
})
.catch((err) => {
reject(err);
});
});
}
//浏览器打开app或下载
openAppMix() {
if (this.os == 'ios') {
location.href = `${packageName}://`
setTimeout(() => { // 未安装的情况
window.open(IOS_URL)
}, 2500);
} else {
let ifr = document.createElement('iframe');
ifr.src = `${packageName}://`;
ifr.style.display = 'none';
document.body.appendChild(ifr);
setTimeout(() => { // 未安装的情况
document.body.removeChild(ifr);
window.open(ADR_URL)
}, 2500)
}
}