初始化

This commit is contained in:
落日晚风
2023-12-13 11:35:02 +08:00
parent 56a0df6369
commit 98baaab9bc
533 changed files with 82087 additions and 0 deletions
+175
View File
@@ -0,0 +1,175 @@
/**
* Shopro 第三方平台功能聚合
* @version 1.0.3
* @author lidongtony
* @param {String} name - 厂商+平台名称
* @param {String} provider - 厂商
* @param {String} platform - 平台名称
* @param {String} os - 系统型号
* @param {Object} device - 设备信息
*/
import { isEmpty } from 'lodash';
// #ifdef H5
import { isWxBrowser } from '@/sheep/helper/utils';
// #endif
import wechat from './provider/wechat/index.js';
import apple from './provider/apple';
import share from './share';
import Pay from './pay';
const device = uni.getSystemInfoSync();
const os = device.platform;
let name = '';
let provider = '';
let platform = '';
let isWechatInstalled = true;
// #ifdef H5
if (isWxBrowser()) {
name = 'WechatOfficialAccount';
provider = 'wechat';
platform = 'officialAccount';
} else {
name = 'H5';
platform = 'h5';
}
// #endif
// #ifdef APP-PLUS
name = 'App';
platform = 'openPlatform';
// 检查微信客户端是否安装,否则AppleStore会因此拒绝上架
if (os === 'ios') {
isWechatInstalled = plus.ios.import('WXApi').isWXAppInstalled();
}
// #endif
// #ifdef MP-WEIXIN
name = 'WechatMiniProgram';
platform = 'miniProgram';
provider = 'wechat';
// #endif
if (isEmpty(name)) {
uni.showToast({
title: '暂不支持该平台',
icon: 'none',
});
}
// 加载当前平台前置行为
const load = () => {
if (provider === 'wechat') {
wechat.load();
}
};
// 使用厂商独占sdk name = 'wechat' | 'alipay' | 'apple'
const useProvider = (_provider = '') => {
if (_provider === '') _provider = provider;
if (_provider === 'wechat') return wechat;
if (_provider === 'apple') return apple;
};
// 支付服务转发
const pay = (payment, orderType, orderSN) => {
return new Pay(payment, orderType, orderSN);
};
/**
* 检查更新 (只检查小程序和App)
* @param {Boolean} silence - 静默检查
*/
const checkUpdate = (silence = false) => {
let canUpdate;
// #ifdef MP-WEIXIN
useProvider().checkUpdate(silence);
// #endif
// #ifdef APP-PLUS
// TODO: 热更新
// #endif
};
/**
* 检查网络
* @param {Boolean} silence - 静默检查
*/
async function checkNetwork() {
const networkStatus = await uni.getNetworkType();
if (networkStatus.networkType == 'none') {
return Promise.resolve(false);
}
return Promise.resolve(true);
}
// 获取小程序胶囊信息
const getCapsule = () => {
// #ifdef MP
let capsule = uni.getMenuButtonBoundingClientRect();
if (!capsule) {
capsule = {
bottom: 56,
height: 32,
left: 278,
right: 365,
top: 24,
width: 87,
};
}
return capsule;
// #endif
// #ifndef MP
return {
bottom: 56,
height: 32,
left: 278,
right: 365,
top: 24,
width: 87,
};
// #endif
};
const capsule = getCapsule();
// 标题栏高度
const getNavBar = () => {
return device.statusBarHeight + 44;
};
const navbar = getNavBar();
function getLandingPage() {
let page = '';
// #ifdef H5
page = location.href.split('?')[0];
// #endif
return page;
}
// 设置ios+公众号网页落地页 解决微信sdk签名问题
const landingPage = getLandingPage();
const _platform = {
name,
device,
os,
provider,
platform,
useProvider,
checkUpdate,
checkNetwork,
pay,
share,
load,
capsule,
navbar,
landingPage,
isWechatInstalled,
};
export default _platform;
+255
View File
@@ -0,0 +1,255 @@
import sheep from '@/sheep';
// #ifdef H5
import $wxsdk from '@/sheep/libs/sdk-h5-weixin';
// #endif
import { getRootUrl } from '@/sheep/helper';
/**
* 支付
*
* @param {String} payment = ['wechat','alipay','wallet','offline'] - 支付方式
* @param {String} orderType = ['goods','recharge','groupon'] - 订单类型
* @param {String} orderSN - 订单号
*/
export default class SheepPay {
constructor(payment, orderType, orderSN) {
this.payment = payment;
this.orderSN = orderSN;
this.orderType = orderType;
this.payAction();
}
payAction() {
const payAction = {
WechatOfficialAccount: {
wechat: () => {
this.wechatOfficialAccountPay();
},
alipay: () => {
this.redirectPay(); // 现在公众号可以直接跳转支付宝页面
},
money: () => {
this.moneyPay();
},
offline: () => {
this.offlinePay();
}
},
WechatMiniProgram: {
wechat: () => {
this.wechatMiniProgramPay();
},
alipay: () => {
this.copyPayLink();
},
money: () => {
this.moneyPay();
},
offline: () => {
this.offlinePay();
}
},
App: {
wechat: () => {
this.wechatAppPay();
},
alipay: () => {
this.alipay();
},
money: () => {
this.moneyPay();
},
offline: () => {
this.offlinePay();
}
},
H5: {
wechat: () => {
this.wechatWapPay();
},
alipay: () => {
this.redirectPay();
},
money: () => {
this.moneyPay();
},
offline: () => {
this.offlinePay();
}
},
};
return payAction[sheep.$platform.name][this.payment]();
}
// 预支付
prepay() {
return new Promise((resolve, reject) => {
let data = {
order_sn: this.orderSN,
payment: this.payment,
};
if (uni.getStorageSync('openid')) {
data.openid = uni.getStorageSync('openid');
}
sheep.$api.pay.prepay(data).then((res) => {
res.error === 0 && resolve(res);
if (res.error === -1 && res.msg === 'miss_openid') {
uni.showModal({
title: '微信支付',
content: '请先绑定微信再使用微信支付',
success: function (res) {
if (res.confirm) {
sheep.$platform.useProvider('wechat').bind();
}
},
});
}
});
});
}
// #ifdef H5
// 微信公众号JSSDK支付
async wechatOfficialAccountPay() {
let that = this;
let { error, data, msg } = await this.prepay();
if (error !== 0) {
console.log('支付错误', msg);
return;
}
$wxsdk.wxpay(data.pay_data, {
success: () => {
that.payResult('success');
},
cancel: () => {
sheep.$helper.toast('支付已手动取消');
},
fail: () => {
that.payResult('fail');
},
});
}
//浏览器微信H5支付
async wechatWapPay() {
const { error, data } = await this.prepay();
if (error === 0) {
const redirect_url = `${getRootUrl()}pages/pay/result?orderSN=${this.orderSN}&payment=${this.payment
}&orderType=${this.orderType}`;
location.href = `${data.pay_data.h5_url}&redirect_url=${encodeURIComponent(redirect_url)}`;
}
}
// 支付链接
async redirectPay() {
let { error, data } = await this.prepay();
if (error === 0) {
const redirect_url = `${getRootUrl()}pages/pay/result?orderSN=${this.orderSN}&payment=${this.payment
}&orderType=${this.orderType}`;
location.href = data.pay_data + encodeURIComponent(redirect_url);
}
}
// #endif
// 微信小程序支付
async wechatMiniProgramPay() {
let that = this;
let result = await this.prepay();
uni.requestPayment({
provider: 'wxpay',
...result.data.pay_data,
success: (res) => {
that.payResult('success');
},
fail: (err) => {
if (err.errMsg === 'requestPayment:fail cancel') {
sheep.$helper.toast('支付已手动取消');
} else {
that.payResult('fail');
}
},
});
}
// 余额支付
async moneyPay() {
const { error } = await this.prepay();
error === 0 && this.payResult('success');
}
// 货到付款
async offlinePay() {
const { error } = await this.prepay();
error === 0 && this.payResult('success');
}
// 支付宝复制链接支付
async copyPayLink() {
let that = this;
let { error, data } = await this.prepay();
if (error === 0) {
// 引入showModal 点击确认 复制链接;
uni.showModal({
title: '支付宝支付',
content: '复制链接到外部浏览器',
confirmText: '复制链接',
success: (res) => {
if (res.confirm) {
sheep.$helper.copyText(data.pay_data);
}
},
});
}
}
// 支付宝支付
async alipay() {
let that = this;
const { error, data } = await this.prepay();
if (error === 0) {
uni.requestPayment({
provider: 'alipay',
orderInfo: data.pay_data, //支付宝订单数据
success: (res) => {
that.payResult('success');
},
fail: (err) => {
if (err.errMsg === 'requestPayment:fail [paymentAlipay:62001]user cancel') {
sheep.$helper.toast('支付已手动取消');
} else {
that.payResult('fail');
}
},
});
}
}
// 微信支付
async wechatAppPay() {
let that = this;
let { error, data } = await this.prepay();
if (error === 0) {
uni.requestPayment({
provider: 'wxpay',
orderInfo: data.pay_data, //微信订单数据(官方说是string。实测为object)
success: (res) => {
that.payResult('success');
},
fail: (err) => {
err.errMsg !== 'requestPayment:fail cancel' && that.payResult('fail');
},
});
}
}
// 支付结果跳转,success:成功,fail:失败
payResult(resultType) {
sheep.$router.redirect('/pages/pay/result', {
orderSN: this.orderSN,
payment: this.payment, //重新支付的时候使用
payState: resultType,
orderType: this.orderType,
});
}
}
+35
View File
@@ -0,0 +1,35 @@
import third from '@/sheep/api/third';
const login = () => {
return new Promise(async (resolve, reject) => {
const loginRes = await uni.login({
provider: 'apple',
success: () => {
uni.getUserInfo({
provider: 'apple',
success: async (res) => {
if (res.errMsg === 'getUserInfo:ok') {
const payload = res.userInfo;
const { error } = await third.apple.login({
payload,
shareInfo: uni.getStorageSync('shareLog') || {},
});
if (error === 0) {
resolve(true);
} else {
resolve(false);
}
}
},
});
},
fail: (err) => {
resolve(false);
},
});
});
};
export default {
login,
};
+9
View File
@@ -0,0 +1,9 @@
// #ifdef APP-PLUS
import service from './app';
// #endif
let apple = {};
if (typeof service !== 'undefined') {
apple = service;
}
export default apple;
+15
View File
@@ -0,0 +1,15 @@
// #ifdef H5
import service from './officialAccount';
// #endif
// #ifdef MP-WEIXIN
import service from './miniProgram';
// #endif
// #ifdef APP-PLUS
import service from './openPlatform';
// #endif
const wechat = service;
export default wechat;
@@ -0,0 +1,251 @@
import { isEmpty } from 'lodash';
import third from '@/sheep/api/third';
import $store from '@/sheep/store';
let sessionId = uni.getStorageSync('sessionId');
let subscribeEventList = [];
// 加载微信小程序
function load() {
checkUpdate();
// const sessionStatus = await checkSession();
// 小程序的接口改动太频繁了 强制每次进入都重新获取
const sessionStatus = false;
if (!sessionStatus) {
getSessionId();
}
getSubscribeTemplate();
}
// 微信小程序静默授权登陆 TODO-ldh: code > 0 问题 改为error
const login = async () => {
return new Promise(async (resolve, reject) => {
const { error } = await third.wechat.login({
platform: 'miniProgram',
shareInfo: uni.getStorageSync('shareLog') || {},
payload: encodeURIComponent(
JSON.stringify({
sessionId: uni.getStorageSync('sessionId'),
}),
),
});
if (error === 0) {
resolve(true);
}
if (error === -1) {
getSessionId(false);
}
resolve(false);
});
};
// 微信小程序手机号授权登陆
const mobileLogin = async (e) => {
return new Promise(async (resolve, reject) => {
if (e.errMsg !== 'getPhoneNumber:ok') {
resolve(false);
return;
}
const { error } = await third.wechat.login({
platform: 'miniProgram',
shareInfo: uni.getStorageSync('shareLog') || {},
payload: encodeURIComponent(
JSON.stringify({
sessionId: uni.getStorageSync('sessionId'),
code: e.code,
iv: e.iv,
encryptedData: e.encryptedData,
}),
),
});
if (error === 0) {
resolve(true);
}
if (error === -1) {
getSessionId(false);
}
resolve(false);
});
};
// 微信小程序绑定
const bind = () => {
return new Promise(async (resolve, reject) => {
const loginRes = await third.wechat.bind({
platform: 'miniProgram',
payload: encodeURIComponent(
JSON.stringify({
sessionId: uni.getStorageSync('sessionId'),
}),
),
});
if (loginRes.error === -1) {
getSessionId(false);
} else if (loginRes.error === 0) {
resolve(true);
} else {
reject(false);
}
});
};
// 微信小程序解除绑定
const unbind = async () => {
const { error } = await third.wechat.unbind({
platform: 'miniProgram',
});
return !error;
};
// 获取最新sessionId
const getSessionId = async (auto_login = null) => {
// 获取code
let codeStr = '';
const loginResult = await uni.login();
if (loginResult.errMsg === 'login:ok') {
codeStr = loginResult.code;
} else {
getSessionId(auto_login);
return false;
}
if(auto_login === null) {
auto_login = !!($store('app').platform.auto_login && !$store('user').isLogin);
}
const { error, data } = await third.wechat.getSessionId({
platform: 'miniProgram',
payload: encodeURIComponent(
JSON.stringify({
code: codeStr,
auto_login,
}),
),
});
if (error === 0) {
uni.setStorageSync('sessionId', data.session_id);
return true;
}
return false;
};
// 检查sessionId是否可用
const checkSession = () => {
return new Promise((resolve, reject) => {
if (!sessionId) {
return resolve(false);
}
uni.checkSession({
success() {
return resolve(true);
},
fail() {
uni.removeStorageSync('sessionId');
return resolve(false);
},
});
});
};
// 小程序更新
const checkUpdate = async (silence = true) => {
if (uni.canIUse('getUpdateManager')) {
const updateManager = uni.getUpdateManager();
updateManager.onCheckForUpdate(function (res) {
// 请求完新版本信息的回调
if (res.hasUpdate) {
updateManager.onUpdateReady(function () {
uni.showModal({
title: '更新提示',
content: '新版本已经准备好,是否重启应用?',
success: function (res) {
if (res.confirm) {
// 新的版本已经下载好,调用 applyUpdate 应用新版本并重启
updateManager.applyUpdate();
}
},
});
});
updateManager.onUpdateFailed(function () {
// 新的版本下载失败
// uni.showModal({
// title: '已经有新版本了哟~',
// content: '新版本已经上线啦,请您删除当前小程序,重新搜索打开~',
// });
});
} else {
if (!silence) {
uni.showModal({
title: '当前为最新版本',
showCancel: false,
});
}
}
});
}
};
// 绑定用户手机号
const bindUserPhoneNumber = (e) => {
return new Promise(async (resolve, reject) => {
const { error } = await third.wechat.bindUserPhoneNumber({
platform: 'miniProgram',
payload: encodeURIComponent(
JSON.stringify({
sessionId: uni.getStorageSync('sessionId'),
iv: e.iv,
encryptedData: e.encryptedData,
code: e.code,
}),
),
});
if (error === 0) {
resolve(true);
}
resolve(false);
});
};
// 获取订阅消息模板
async function getSubscribeTemplate() {
const { error, data } = await third.wechat.subscribeTemplate();
if (error === 0) {
subscribeEventList = data;
}
}
// 订阅消息
function subscribeMessage(event) {
let tmplIds = [];
if (typeof event === 'string') {
tmplIds.push(subscribeEventList[event]);
}
if (typeof event === 'object') {
event.forEach((item) => {
if (typeof subscribeEventList[item] !== 'undefined') tmplIds.push(subscribeEventList[item]);
});
}
if (tmplIds.length === 0) return;
uni.requestSubscribeMessage({
tmplIds,
fail: (err) => {
console.log(err);
},
});
}
export default {
load,
login,
bind,
unbind,
checkUpdate,
bindUserPhoneNumber,
subscribeMessage,
};
@@ -0,0 +1,112 @@
import third from '@/sheep/api/third';
import $wxsdk from '@/sheep/libs/sdk-h5-weixin';
import $store from '@/sheep/store';
import $platform from '@/sheep/platform';
import { getRootUrl } from '@/sheep/helper';
// 加载微信公众号JSSDK
async function load() {
if (
$store('app').platform.auto_login &&
!$store('user').isLogin &&
location.href.search('pages/index/login') === -1
) {
// 发起自动登陆
login();
}
$wxsdk.init();
}
// 微信公众号登陆
async function login(code = '') {
// 获取登陆地址
if (!code) {
const loginResult = await getLoginUrl();
if (loginResult.error === 0 && loginResult.data.login_url) {
uni.setStorageSync('returnUrl', location.href);
window.location = loginResult.data.login_url;
}
} else {
// 解密code发起登陆
const loginResult = await loginByCode(code);
if (loginResult.error === 0) {
return loginResult;
}
}
return false;
}
// 微信公众号绑定
async function bind(code = '') {
// 获取绑定地址
if (code === '') {
const loginResult = await getLoginUrl('bind');
if (loginResult.error === 0 && loginResult.data.login_url) {
uni.setStorageSync('returnUrl', location.href);
window.location = loginResult.data.login_url;
}
} else {
// 解密code发起登陆
const loginResult = await bindByCode(code);
if (loginResult.error === 0) {
return loginResult;
}
}
return false;
}
// 微信公众号解除绑定
async function unbind() {
const { error } = await third.wechat.unbind({
platform: 'officialAccount',
});
return Promise.resolve(!error);
}
// 获取公众号登陆地址
function getLoginUrl(event = 'login') {
let page = getRootUrl() + 'pages/index/login';
return third.wechat.oauthLogin({
platform: 'officialAccount',
payload: encodeURIComponent(
JSON.stringify({
page,
event,
}),
),
});
}
// 此处使用前端发送code在后端解密,防止用户在后端过长时间停留
function loginByCode(code) {
return third.wechat.login({
platform: 'officialAccount',
shareInfo: uni.getStorageSync('shareLog') || {},
payload: encodeURIComponent(
JSON.stringify({
code,
}),
),
});
}
// 此处使用前端发送code在后端解密,防止用户在后端过长时间停留
function bindByCode(code) {
return third.wechat.bind({
platform: 'officialAccount',
payload: encodeURIComponent(
JSON.stringify({
code,
}),
),
});
}
export default {
load,
login,
bind,
unbind,
jssdk: $wxsdk,
};
@@ -0,0 +1,41 @@
// 登录
import { isEmpty } from 'lodash';
import third from '@/sheep/api/third';
const load = async () => {};
// 微信开放平台移动应用授权登陆
const login = () => {
return new Promise(async (resolve, reject) => {
const loginRes = await uni.login({
provider: 'weixin',
onlyAuthorize: true,
});
if (loginRes.errMsg == 'login:ok') {
const res = await third.wechat.login({
platform: 'openPlatform',
shareInfo: uni.getStorageSync('shareLog') || {},
payload: encodeURIComponent(
JSON.stringify({
code: loginRes.code,
}),
),
});
if (res.error === 0) {
resolve(true);
}
} else {
uni.showToast({
icon: 'none',
title: loginRes.errMsg,
});
}
resolve(false);
});
};
export default {
load,
login,
};
+182
View File
@@ -0,0 +1,182 @@
import $store from '@/sheep/store';
import $platform from '@/sheep/platform';
import $router from '@/sheep/router';
import $url from '@/sheep/url';
// #ifdef H5
import $wxsdk from '@/sheep/libs/sdk-h5-weixin';
// #endif
// 设置分享的平台渠道: 1=H5,2=微信公众号网页,3=微信小程序,4=App,...按需扩展
const platformMap = ['H5', 'WechatOfficialAccount', 'WechatMiniProgram', 'App'];
// 设置分享方式: 1=直接转发,2=海报,3=复制链接,...按需扩展
const fromMap = ['forward', 'poster', 'link'];
// 设置分享信息参数
const getShareInfo = (
scene = {
title: '', // 自定义分享标题
desc: '', // 自定义描述
image: '', // 自定义分享图片
params: {}, // 自定义分享参数
},
poster = {
// 自定义海报数据
type: 'user',
},
) => {
let shareInfo = {
title: '', // 分享标题
desc: '', // 描述
image: '', // 分享图片
path: '', // 分享页面+参数
link: '', // 分享Url+参数
query: '', // 分享参数
poster, // 海报所需数据
};
const app = $store('app');
const shareConfig = app.platform.share;
// 自动拼接分享用户参数
const query = buildSpmQuery(scene.params);
shareInfo.query = query;
// 配置分享链接地址
shareInfo.link = buildSpmLink(query, shareConfig.linkAddress);
// 配置转发参数
if (shareConfig.methods.includes('forward')) {
if (shareConfig.forwardInfo.title === '' || shareConfig.forwardInfo.image === '') {
console.log('请在平台设置中配置转发信息');
}
// 设置自定义分享信息
shareInfo.title = scene.title || shareConfig.forwardInfo.title;
shareInfo.image = $url.cdn(scene.image || shareConfig.forwardInfo.image);
shareInfo.desc = scene.desc || shareConfig.forwardInfo.subtitle;
shareInfo.path = buildSpmPath(query);
}
return shareInfo;
};
// 构造spm分享参数
const buildSpmQuery = (params) => {
const user = $store('user');
let shareId = '0'; // 设置分享者用户ID
if (typeof params.shareId === 'undefined') {
if (user.isLogin) {
shareId = user.userInfo.id;
}
}
let page = '1'; // 页面类型: 1=首页(默认),2=商品,3=拼团商品,4=秒杀商品,5=邀请参团...按需扩展
if (typeof params.page !== 'undefined') {
page = params.page;
}
let query = '0'; // 设置页面ID: 如商品ID、拼团ID等
if (typeof params.query !== 'undefined') {
query = params.query;
}
let platform = platformMap.indexOf($platform.name) + 1;
let from = '1';
if (typeof params.from !== 'undefined') {
from = platformMap.indexOf(params.from) + 1;
}
//spmParams = ... 可按需扩展
return `spm=${shareId}.${page}.${query}.${platform}.${from}`;
};
// 构造页面分享参数
const buildSpmPath = (query) => {
return `/pages/index/index?${query}`;
};
// 构造分享链接
const buildSpmLink = (query, linkAddress = '') => {
return `${linkAddress}?${query}`;
};
// 解析Spm
const decryptSpm = (spm) => {
const user = $store('user');
let shareParamsArray = spm.split('.');
let shareParams = {
spm,
shareId: 0,
page: '',
query: {},
platform: '',
from: '',
};
let query;
shareParams.shareId = shareParamsArray[0];
switch (shareParamsArray[1]) {
case '1':
// 默认首页不跳转
shareParams.page = '/pages/index/index';
break;
case '2':
// 普通商品
shareParams.page = '/pages/goods/index';
shareParams.query = {
id: shareParamsArray[2],
};
break;
case '3':
// 拼团商品
shareParams.page = '/pages/goods/groupon';
query = shareParamsArray[2].split(',');
shareParams.query = {
id: query[0],
activity_id: query[1],
};
break;
case '4':
// 秒杀商品
shareParams.page = '/pages/goods/seckill';
query = shareParamsArray[2].split(',');
shareParams.query = {
id: query[0],
activity_id: query[1],
};
break;
case '5':
// 参与拼团
shareParams.page = '/pages/activity/groupon/detail';
shareParams.query = {
id: shareParamsArray[2],
};
break;
}
shareParams.platform = platformMap[shareParamsArray[3] - 1];
shareParams.from = fromMap[shareParamsArray[4] - 1];
if (shareParams.shareId != 0) {
// 已登录 立即添加分享记录
if (user.isLogin) {
user.addShareLog(shareParams);
} else {
// 未登录 待用户登录后添加分享记录
uni.setStorageSync('shareLog', shareParams);
}
}
if (shareParams.page !== '/pages/index/index') {
$router.go(shareParams.page, shareParams.query);
}
return shareParams;
};
// 更新公众号分享sdk
const updateShareInfo = (shareInfo) => {
// #ifdef H5
if ($platform.name === 'WechatOfficialAccount') {
$wxsdk.updateShareInfo(shareInfo);
}
// #endif
};
export default {
getShareInfo,
updateShareInfo,
decryptSpm,
};