项目初始化
This commit is contained in:
175
sheep/platform/index.js
Normal file
175
sheep/platform/index.js
Normal 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-es';
|
||||
// #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, flag) => {
|
||||
return new Pay(payment, orderType, orderSN, flag);
|
||||
};
|
||||
|
||||
/**
|
||||
* 检查更新 (只检查小程序和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;
|
372
sheep/platform/pay.js
Normal file
372
sheep/platform/pay.js
Normal file
@@ -0,0 +1,372 @@
|
||||
import sheep from '@/sheep';
|
||||
// #ifdef H5
|
||||
import $wxsdk from '@/sheep/libs/sdk-h5-weixin';
|
||||
// #endif
|
||||
import { getRootUrl } from '@/sheep/helper';
|
||||
import PayOrderApi from '@/sheep/api/pay/order';
|
||||
|
||||
/**
|
||||
* 支付
|
||||
*
|
||||
* @param {String} payment = ['wechat','alipay','wallet','mock'] - 支付方式
|
||||
* @param {String} orderType = ['goods','recharge','groupon'] - 订单类型
|
||||
* @param {String} id - 订单号
|
||||
*/
|
||||
|
||||
export default class SheepPay {
|
||||
constructor(payment, orderType, id, flag) {
|
||||
this.payment = payment;
|
||||
this.id = id;
|
||||
this.orderType = orderType;
|
||||
this.flag = flag;
|
||||
this.payAction();
|
||||
}
|
||||
|
||||
payAction() {
|
||||
const payAction = {
|
||||
WechatOfficialAccount: {
|
||||
wechat: () => {
|
||||
this.wechatOfficialAccountPay();
|
||||
},
|
||||
alipay: () => {
|
||||
this.redirectPay(); // 现在公众号可以直接跳转支付宝页面
|
||||
},
|
||||
wallet: () => {
|
||||
this.walletPay();
|
||||
},
|
||||
mock: () => {
|
||||
this.mockPay();
|
||||
}
|
||||
},
|
||||
WechatMiniProgram: {
|
||||
wechat: () => {
|
||||
this.wechatMiniProgramPay();
|
||||
},
|
||||
alipay: () => {
|
||||
this.copyPayLink();
|
||||
},
|
||||
wallet: () => {
|
||||
this.walletPay();
|
||||
},
|
||||
mock: () => {
|
||||
this.mockPay();
|
||||
}
|
||||
},
|
||||
App: {
|
||||
wechat: () => {
|
||||
this.wechatAppPay();
|
||||
},
|
||||
alipay: () => {
|
||||
this.alipay();
|
||||
},
|
||||
wallet: () => {
|
||||
this.walletPay();
|
||||
},
|
||||
mock: () => {
|
||||
this.mockPay();
|
||||
}
|
||||
},
|
||||
H5: {
|
||||
wechat: () => {
|
||||
this.wechatWapPay();
|
||||
},
|
||||
alipay: () => {
|
||||
this.redirectPay();
|
||||
},
|
||||
wallet: () => {
|
||||
this.walletPay();
|
||||
},
|
||||
mock: () => {
|
||||
this.mockPay();
|
||||
}
|
||||
},
|
||||
};
|
||||
return payAction[sheep.$platform.name][this.payment]();
|
||||
}
|
||||
|
||||
// 预支付
|
||||
prepay(channel) {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
let data = {
|
||||
id: this.id,
|
||||
channelCode: channel,
|
||||
channelExtras: {}
|
||||
};
|
||||
// 特殊逻辑:微信公众号、小程序支付时,必须传入 openid
|
||||
if (['wx_pub', 'wx_lite'].includes(channel)) {
|
||||
const openid = await sheep.$platform.useProvider('wechat').getOpenid();
|
||||
// 如果获取不到 openid,微信无法发起支付,此时需要引导
|
||||
if (!openid) {
|
||||
this.bindWeixin();
|
||||
return;
|
||||
}
|
||||
data.channelExtras.openid = openid;
|
||||
}
|
||||
// 发起预支付 API 调用
|
||||
PayOrderApi.submitOrder(data).then((res) => {
|
||||
// 成功时
|
||||
res.code === 0 && resolve(res);
|
||||
// 失败时
|
||||
if (res.code !== 0 && res.msg.indexOf('无效的openid') >= 0) {
|
||||
// 特殊逻辑:微信公众号、小程序支付时,必须传入 openid 不正确的情况
|
||||
if (res.msg.indexOf('无效的openid') >= 0 // 获取的 openid 不正确时,或者随便输入了个 openid
|
||||
|| res.msg.indexOf('下单账号与支付账号不一致') >= 0) { // https://developers.weixin.qq.com/community/develop/doc/00008c53c347804beec82aed051c00
|
||||
this.bindWeixin();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
// #ifdef H5
|
||||
// 微信公众号 JSSDK 支付
|
||||
async wechatOfficialAccountPay() {
|
||||
let { code, data } = await this.prepay('wx_pub');
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
const payConfig = JSON.parse(data.displayContent);
|
||||
$wxsdk.wxpay(payConfig, {
|
||||
success: () => {
|
||||
this.payResult('success');
|
||||
},
|
||||
cancel: () => {
|
||||
sheep.$helper.toast('支付已手动取消');
|
||||
},
|
||||
fail: (error) => {
|
||||
if (error.errMsg.indexOf('chooseWXPay:没有此SDK或暂不支持此SDK模拟') >= 0) {
|
||||
sheep.$helper.toast('发起微信支付失败,原因:可能是微信开发者工具不支持,建议使用微信打开网页后支付');
|
||||
return
|
||||
}
|
||||
this.payResult('fail');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// 浏览器微信 H5 支付 TODO 芋艿:待接入
|
||||
async wechatWapPay() {
|
||||
const { error, data } = await this.prepay();
|
||||
if (error === 0) {
|
||||
const redirect_url = `${getRootUrl()}pages/pay/result?id=${this.id}&payment=${this.payment}&orderType=${this.orderType}`;
|
||||
location.href = `${data.pay_data.h5_url}&redirect_url=${encodeURIComponent(redirect_url)}`;
|
||||
}
|
||||
}
|
||||
|
||||
// 支付链接 TODO 芋艿:待接入
|
||||
async redirectPay() {
|
||||
let { error, data } = await this.prepay();
|
||||
if (error === 0) {
|
||||
const redirect_url = `${getRootUrl()}pages/pay/result?id=${this.id}&payment=${this.payment}&orderType=${this.orderType}`;
|
||||
location.href = data.pay_data + encodeURIComponent(redirect_url);
|
||||
}
|
||||
}
|
||||
|
||||
// #endif
|
||||
|
||||
// 微信小程序支付
|
||||
async wechatMiniProgramPay() {
|
||||
// let that = this;
|
||||
let { code, data } = await this.prepay('wx_lite');
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
// 调用微信小程序支付
|
||||
const payConfig = JSON.parse(data.displayContent);
|
||||
uni.requestPayment({
|
||||
provider: 'wxpay',
|
||||
timeStamp: payConfig.timeStamp,
|
||||
nonceStr: payConfig.nonceStr,
|
||||
package: payConfig.packageValue,
|
||||
signType: payConfig.signType,
|
||||
paySign: payConfig.paySign,
|
||||
success: (res) => {
|
||||
this.payResult('success');
|
||||
},
|
||||
fail: (err) => {
|
||||
if (err.errMsg === 'requestPayment:fail cancel') {
|
||||
sheep.$helper.toast('支付已手动取消');
|
||||
} else {
|
||||
this.payResult('fail');
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// 余额支付
|
||||
async walletPay() {
|
||||
const { code } = await this.prepay('wallet');
|
||||
code === 0 && this.payResult('success');
|
||||
}
|
||||
|
||||
// 模拟支付
|
||||
async mockPay() {
|
||||
const { code } = await this.prepay('mock');
|
||||
code === 0 && this.payResult('success');
|
||||
}
|
||||
|
||||
// 支付宝复制链接支付 TODO 芋艿:待接入
|
||||
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);
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 支付宝支付 TODO 芋艿:待接入
|
||||
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');
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 微信支付 TODO 芋艿:待接入
|
||||
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) {
|
||||
if(this.flag == 'worker'){
|
||||
sheep.$router.redirect('/pages/pay/worker/result', {
|
||||
id: this.id,
|
||||
orderType: this.orderType,
|
||||
payState: resultType
|
||||
});
|
||||
}else if(this.flag == 'reward'){
|
||||
sheep.$helper.toast('打赏成功');
|
||||
uni.navigateBack();
|
||||
}else if(this.flag == 'point'){
|
||||
sheep.$router.redirect('/pages/point/result', {
|
||||
id: this.id,
|
||||
orderType: this.orderType,
|
||||
payState: resultType
|
||||
});
|
||||
}else if(this.flag == 'vip'){
|
||||
sheep.$helper.toast('开通成功');
|
||||
sheep.$router.redirect('/pages/user/vip');
|
||||
}else {
|
||||
sheep.$router.redirect('/pages/pay/result', {
|
||||
id: this.id,
|
||||
orderType: this.orderType,
|
||||
payState: resultType
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 引导绑定微信
|
||||
bindWeixin() {
|
||||
uni.showModal({
|
||||
title: '微信支付',
|
||||
content: '请先绑定微信再使用微信支付',
|
||||
success: function (res) {
|
||||
if (res.confirm) {
|
||||
sheep.$platform.useProvider('wechat').bind();
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export function getPayMethods(channels) {
|
||||
const payMethods = [
|
||||
{
|
||||
icon: '/static/img/shop/pay/wechat.png',
|
||||
title: '微信支付',
|
||||
value: 'wechat',
|
||||
disabled: true,
|
||||
},
|
||||
{
|
||||
icon: '/static/img/shop/pay/alipay.png',
|
||||
title: '支付宝支付',
|
||||
value: 'alipay',
|
||||
disabled: true,
|
||||
},
|
||||
{
|
||||
icon: '/static/img/shop/pay/wallet.png',
|
||||
title: '余额支付',
|
||||
value: 'wallet',
|
||||
disabled: true,
|
||||
},
|
||||
{
|
||||
icon: '/static/img/shop/pay/apple.png',
|
||||
title: 'Apple Pay',
|
||||
value: 'apple',
|
||||
disabled: true,
|
||||
},
|
||||
{
|
||||
icon: '/static/img/shop/pay/wallet.png',
|
||||
title: '模拟支付',
|
||||
value: 'mock',
|
||||
disabled: true,
|
||||
}
|
||||
];
|
||||
const platform = sheep.$platform.name
|
||||
|
||||
// 1. 处理【微信支付】
|
||||
const wechatMethod = payMethods[0];
|
||||
if ((platform === 'WechatOfficialAccount' && channels.includes('wx_pub'))
|
||||
|| (platform === 'WechatMiniProgram' && channels.includes('wx_lite'))
|
||||
|| (platform === 'H5' && channels.includes('wx_pub'))
|
||||
|| (platform === 'App' && channels.includes('wx_app'))) {
|
||||
wechatMethod.disabled = false;
|
||||
}
|
||||
|
||||
// 2. 处理【支付宝支付】
|
||||
const alipayMethod = payMethods[1];
|
||||
if ((platform === 'WechatOfficialAccount' && channels.includes('alipay_wap'))
|
||||
|| platform === 'WechatMiniProgram' && channels.includes('alipay_wap')
|
||||
|| platform === 'App' && channels.includes('alipay_app')) {
|
||||
alipayMethod.disabled = false;
|
||||
}
|
||||
// 3. 处理【余额支付】
|
||||
const walletMethod = payMethods[2];
|
||||
if (channels.includes('wallet')) {
|
||||
walletMethod.disabled = false;
|
||||
}
|
||||
// 4. 处理【苹果支付】TODO 芋艿:未来接入
|
||||
// 5. 处理【模拟支付】
|
||||
const mockMethod = payMethods[4];
|
||||
if (channels.includes('mock')) {
|
||||
mockMethod.disabled = false;
|
||||
}
|
||||
return payMethods;
|
||||
}
|
36
sheep/platform/provider/apple/app.js
Normal file
36
sheep/platform/provider/apple/app.js
Normal file
@@ -0,0 +1,36 @@
|
||||
// import third from '@/sheep/api/third';
|
||||
// TODO 芋艿:等后面搞 App 再弄
|
||||
|
||||
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
sheep/platform/provider/apple/index.js
Normal file
9
sheep/platform/provider/apple/index.js
Normal 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
sheep/platform/provider/wechat/index.js
Normal file
15
sheep/platform/provider/wechat/index.js
Normal 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;
|
213
sheep/platform/provider/wechat/miniProgram.js
Normal file
213
sheep/platform/provider/wechat/miniProgram.js
Normal file
@@ -0,0 +1,213 @@
|
||||
import AuthUtil from '@/sheep/api/member/auth';
|
||||
import SocialApi from '@/sheep/api/member/social';
|
||||
import UserApi from '@/sheep/api/member/user';
|
||||
|
||||
const socialType = 34; // 社交类型 - 微信小程序
|
||||
|
||||
let subscribeEventList = [];
|
||||
|
||||
// 加载微信小程序
|
||||
function load() {
|
||||
checkUpdate();
|
||||
getSubscribeTemplate();
|
||||
}
|
||||
|
||||
// 微信小程序静默授权登陆
|
||||
const login = async () => {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
// 1. 获得微信 code
|
||||
const codeResult = await uni.login();
|
||||
if (codeResult.errMsg !== 'login:ok') {
|
||||
return resolve(false);
|
||||
}
|
||||
|
||||
// 2. 社交登录
|
||||
const loginResult = await AuthUtil.socialLogin(socialType, codeResult.code, 'default');
|
||||
if (loginResult.code === 0) {
|
||||
setOpenid(loginResult.data.openid);
|
||||
return resolve(true);
|
||||
} else {
|
||||
return resolve(false);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 微信小程序手机号授权登陆
|
||||
const mobileLogin = async (e) => {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
if (e.errMsg !== 'getPhoneNumber:ok') {
|
||||
return resolve(false);
|
||||
}
|
||||
|
||||
// 1. 获得微信 code
|
||||
const codeResult = await uni.login();
|
||||
if (codeResult.errMsg !== 'login:ok') {
|
||||
return resolve(false);
|
||||
}
|
||||
|
||||
// 2. 一键登录
|
||||
const loginResult = await AuthUtil.weixinMiniAppLogin(e.code, codeResult.code, 'default');
|
||||
if (loginResult.code === 0) {
|
||||
setOpenid(loginResult.data.openid);
|
||||
return resolve(true);
|
||||
} else {
|
||||
return resolve(false);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 微信小程序绑定
|
||||
const bind = () => {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
// 1. 获得微信 code
|
||||
const codeResult = await uni.login();
|
||||
if (codeResult.errMsg !== 'login:ok') {
|
||||
return resolve(false);
|
||||
}
|
||||
|
||||
// 2. 绑定账号
|
||||
const bindResult = await SocialApi.socialBind(socialType, codeResult.code, 'default');
|
||||
if (bindResult.code === 0) {
|
||||
setOpenid(bindResult.data);
|
||||
return resolve(true);
|
||||
} else {
|
||||
return resolve(false);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 微信小程序解除绑定
|
||||
const unbind = async (openid) => {
|
||||
const { code } = await SocialApi.socialUnbind(socialType, openid);
|
||||
return code === 0;
|
||||
};
|
||||
|
||||
// 绑定用户手机号
|
||||
const bindUserPhoneNumber = (e) => {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
const { code } = await UserApi.updateUserMobileByWeixin(e.code);
|
||||
if (code === 0) {
|
||||
resolve(true);
|
||||
}
|
||||
resolve(false);
|
||||
});
|
||||
};
|
||||
|
||||
// 设置 openid 到本地存储,目前只有 pay 支付时会使用
|
||||
function setOpenid(openid) {
|
||||
uni.setStorageSync('openid', openid);
|
||||
}
|
||||
|
||||
// 获得 openid
|
||||
async function getOpenid(force = false) {
|
||||
let openid = uni.getStorageSync('openid');
|
||||
if (!openid && force) {
|
||||
const info = await getInfo();
|
||||
if (info && info.openid) {
|
||||
openid = info.openid;
|
||||
setOpenid(openid);
|
||||
}
|
||||
}
|
||||
return openid;
|
||||
}
|
||||
|
||||
// 获得社交信息
|
||||
async function getInfo() {
|
||||
const { code, data } = await SocialApi.getSocialUser(socialType);
|
||||
if (code !== 0) {
|
||||
return undefined;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
// ========== 非登录相关的逻辑 ==========
|
||||
|
||||
// 小程序更新
|
||||
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,
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 获取订阅消息模板
|
||||
async function getSubscribeTemplate() {
|
||||
const { code, data } = await SocialApi.getSubscribeTemplateList();
|
||||
if (code === 0) {
|
||||
subscribeEventList = data;
|
||||
}
|
||||
}
|
||||
|
||||
// 订阅消息
|
||||
function subscribeMessage(event, callback= undefined) {
|
||||
let tmplIds = [];
|
||||
if (typeof event === 'string') {
|
||||
const temp = subscribeEventList.find(item => item.title.includes(event));
|
||||
if (temp) {
|
||||
tmplIds.push(temp.id);
|
||||
}
|
||||
}
|
||||
if (typeof event === 'object') {
|
||||
event.forEach((e) => {
|
||||
const temp = subscribeEventList.find(item => item.title.includes(e));
|
||||
if (temp) {
|
||||
tmplIds.push(temp.id);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (tmplIds.length === 0) return;
|
||||
|
||||
uni.requestSubscribeMessage({
|
||||
tmplIds,
|
||||
success: ()=>{
|
||||
// 不管是拒绝还是同意都触发
|
||||
callback && callback()
|
||||
},
|
||||
fail: (err) => {
|
||||
console.log(err);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export default {
|
||||
load,
|
||||
login,
|
||||
bind,
|
||||
unbind,
|
||||
bindUserPhoneNumber,
|
||||
mobileLogin,
|
||||
getInfo,
|
||||
getOpenid,
|
||||
subscribeMessage,
|
||||
checkUpdate,
|
||||
};
|
106
sheep/platform/provider/wechat/officialAccount.js
Normal file
106
sheep/platform/provider/wechat/officialAccount.js
Normal file
@@ -0,0 +1,106 @@
|
||||
import $wxsdk from '@/sheep/libs/sdk-h5-weixin';
|
||||
import { getRootUrl } from '@/sheep/helper';
|
||||
import AuthUtil from '@/sheep/api/member/auth';
|
||||
import SocialApi from '@/sheep/api/member/social';
|
||||
|
||||
const socialType = 31; // 社交类型 - 微信公众号
|
||||
|
||||
// 加载微信公众号JSSDK
|
||||
async function load() {
|
||||
$wxsdk.init();
|
||||
}
|
||||
|
||||
// 微信公众号登陆
|
||||
async function login(code = '', state = '') {
|
||||
// 情况一:没有 code 时,去获取 code
|
||||
if (!code) {
|
||||
const loginUrl = await getLoginUrl();
|
||||
if (loginUrl) {
|
||||
uni.setStorageSync('returnUrl', location.href);
|
||||
window.location = loginUrl;
|
||||
}
|
||||
// 情况二:有 code 时,使用 code 去自动登录
|
||||
} else {
|
||||
// 解密 code 发起登陆
|
||||
const loginResult = await AuthUtil.socialLogin(socialType, code, state);
|
||||
if (loginResult.code === 0) {
|
||||
setOpenid(loginResult.data.openid);
|
||||
return loginResult;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// 微信公众号绑定
|
||||
async function bind(code = '', state = '') {
|
||||
// 情况一:没有 code 时,去获取 code
|
||||
if (code === '') {
|
||||
const loginUrl = await getLoginUrl('bind');
|
||||
if (loginUrl) {
|
||||
uni.setStorageSync('returnUrl', location.href);
|
||||
window.location = loginUrl;
|
||||
}
|
||||
} else {
|
||||
// 情况二:有 code 时,使用 code 去自动绑定
|
||||
const loginResult = await SocialApi.socialBind(socialType, code, state);
|
||||
if (loginResult.code === 0) {
|
||||
setOpenid(loginResult.data);
|
||||
return loginResult;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// 微信公众号解除绑定
|
||||
const unbind = async (openid) => {
|
||||
const { code } = await SocialApi.socialUnbind(socialType, openid);
|
||||
return code === 0;
|
||||
};
|
||||
|
||||
// 获取公众号登陆地址
|
||||
async function getLoginUrl(event = 'login') {
|
||||
const page = getRootUrl() + 'pages/index/login'
|
||||
+ '?event=' + event; // event 目的,区分是 login 还是 bind
|
||||
const { code, data } = await AuthUtil.socialAuthRedirect(socialType, page);
|
||||
if (code !== 0) {
|
||||
return undefined;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
// 设置 openid 到本地存储,目前只有 pay 支付时会使用
|
||||
function setOpenid(openid) {
|
||||
uni.setStorageSync('openid', openid);
|
||||
}
|
||||
|
||||
// 获得 openid
|
||||
async function getOpenid(force = false) {
|
||||
let openid = uni.getStorageSync('openid');
|
||||
if (!openid && force) {
|
||||
const info = await getInfo();
|
||||
if (info && info.openid) {
|
||||
openid = info.openid;
|
||||
setOpenid(openid);
|
||||
}
|
||||
}
|
||||
return openid;
|
||||
}
|
||||
|
||||
// 获得社交信息
|
||||
async function getInfo() {
|
||||
const { code, data } = await SocialApi.getSocialUser(socialType);
|
||||
if (code !== 0) {
|
||||
return undefined;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
export default {
|
||||
load,
|
||||
login,
|
||||
bind,
|
||||
unbind,
|
||||
getInfo,
|
||||
getOpenid,
|
||||
jsWxSdk: $wxsdk,
|
||||
};
|
64
sheep/platform/provider/wechat/openPlatform.js
Normal file
64
sheep/platform/provider/wechat/openPlatform.js
Normal file
@@ -0,0 +1,64 @@
|
||||
// 登录
|
||||
import third from '@/sheep/api/migration/third';
|
||||
import SocialApi from '@/sheep/api/member/social';
|
||||
import $share from '@/sheep/platform/share';
|
||||
|
||||
// TODO 芋艿:等后面搞 App 再弄
|
||||
const socialType = 32; // 社交类型 - 微信开放平台
|
||||
|
||||
const load = async () => {};
|
||||
|
||||
// 微信开放平台移动应用授权登陆
|
||||
const login = () => {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
const loginRes = await uni.login({
|
||||
provider: 'weixin',
|
||||
onlyAuthorize: true,
|
||||
});
|
||||
debugger
|
||||
if (loginRes.errMsg == 'login:ok') {
|
||||
// TODO third.wechat.login 函数未实现
|
||||
const res = await third.wechat.login({
|
||||
platform: 'openPlatform',
|
||||
shareInfo: uni.getStorageSync('shareLog') || {},
|
||||
payload: encodeURIComponent(
|
||||
JSON.stringify({
|
||||
code: loginRes.code,
|
||||
}),
|
||||
),
|
||||
});
|
||||
|
||||
if (res.error === 0) {
|
||||
$share.bindBrokerageUser()
|
||||
resolve(true);
|
||||
}
|
||||
} else {
|
||||
uni.showToast({
|
||||
icon: 'none',
|
||||
title: loginRes.errMsg,
|
||||
});
|
||||
}
|
||||
resolve(false);
|
||||
});
|
||||
};
|
||||
|
||||
// 微信 App 解除绑定
|
||||
const unbind = async (openid) => {
|
||||
const { code } = await SocialApi.socialUnbind(socialType, openid);
|
||||
return code === 0;
|
||||
};
|
||||
|
||||
// 获得社交信息
|
||||
async function getInfo() {
|
||||
const { code, data } = await SocialApi.getSocialUser(socialType);
|
||||
if (code !== 0) {
|
||||
return undefined;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
export default {
|
||||
load,
|
||||
login,
|
||||
getInfo
|
||||
};
|
207
sheep/platform/share.js
Normal file
207
sheep/platform/share.js
Normal file
@@ -0,0 +1,207 @@
|
||||
import $store from '@/sheep/store';
|
||||
import $platform from '@/sheep/platform';
|
||||
import $router from '@/sheep/router';
|
||||
import $url from '@/sheep/url';
|
||||
import BrokerageApi from '@/sheep/api/trade/brokerage';
|
||||
// #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'];
|
||||
|
||||
// TODO 芋艿:分享的接入
|
||||
// 设置分享信息参数
|
||||
const getShareInfo = (
|
||||
scene = {
|
||||
title: '', // 自定义分享标题
|
||||
desc: '', // 自定义描述
|
||||
image: '', // 自定义分享图片
|
||||
params: {}, // 自定义分享参数
|
||||
},
|
||||
poster = {
|
||||
// 自定义海报数据
|
||||
type: 'user',
|
||||
},
|
||||
) => {
|
||||
const 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);
|
||||
// 配置页面地址带参数
|
||||
shareInfo.path = buildSpmPath(query);
|
||||
|
||||
// 配置转发参数
|
||||
if (shareConfig.methods.includes('forward')) {
|
||||
// TODO puhui999: 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(scene.path, query);
|
||||
}
|
||||
|
||||
return shareInfo;
|
||||
};
|
||||
|
||||
/**
|
||||
* 构造 spm 分享参数
|
||||
*
|
||||
* @param params json 格式,其中包含:1)shareId 分享用户的编号;2)page 页面类型;3)query 页面 ID(参数);4)platform 平台类型;5)from 分享来源类型。
|
||||
* @return 分享串 `spm=${shareId}.${page}.${query}.${platform}.${from}`
|
||||
*/
|
||||
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=邀请参团,6=分销邀请...按需扩展
|
||||
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}`;
|
||||
};
|
||||
|
||||
// 构造页面分享参数: 所有的分享都先到首页进行 spm 参数解析
|
||||
const buildSpmPath = (query) => {
|
||||
// 默认是主页,页面 page,例如 pages/index/index,根路径前不要填加 /,
|
||||
// 不能携带参数(参数请放在scene字段里),如果不填写这个字段,默认跳主页面。scancode_time为系统保留参数,不允许配置
|
||||
return `pages/tabbar/index`;
|
||||
};
|
||||
|
||||
// 构造分享链接
|
||||
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/tabbar/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], // TODO 芋艿:接入分享后,应该统一成 id 参数
|
||||
};
|
||||
break;
|
||||
case '4':
|
||||
// 秒杀商品
|
||||
shareParams.page = '/pages/goods/seckill';
|
||||
query = shareParamsArray[2].split(',');
|
||||
shareParams.query = {
|
||||
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) {
|
||||
bindBrokerageUser(shareParams.shareId);
|
||||
} else {
|
||||
// 记录分享者编号
|
||||
uni.setStorageSync('shareId', shareParams.shareId);
|
||||
}
|
||||
}
|
||||
|
||||
if (shareParams.page !== '/pages/tabbar/index') {
|
||||
$router.go(shareParams.page, shareParams.query);
|
||||
}
|
||||
return shareParams;
|
||||
};
|
||||
|
||||
// 绑定推广员
|
||||
const bindBrokerageUser = async (val= undefined) => {
|
||||
try {
|
||||
const shareId = val || uni.getStorageSync('shareId');
|
||||
if (!shareId) {
|
||||
return;
|
||||
}
|
||||
await BrokerageApi.bindBrokerageUser({ bindUserId: shareId });
|
||||
uni.removeStorageSync('shareId');
|
||||
} catch {
|
||||
}
|
||||
};
|
||||
|
||||
// 更新公众号分享sdk
|
||||
const updateShareInfo = (shareInfo) => {
|
||||
// #ifdef H5
|
||||
if ($platform.name === 'WechatOfficialAccount') {
|
||||
$wxsdk.updateShareInfo(shareInfo);
|
||||
}
|
||||
// #endif
|
||||
};
|
||||
|
||||
export default {
|
||||
getShareInfo,
|
||||
updateShareInfo,
|
||||
decryptSpm,
|
||||
bindBrokerageUser,
|
||||
};
|
Reference in New Issue
Block a user