import { ref, reactive } from "vue"; import { orderPayAli, orderPayWx, orderCheck, orderPayApple } from "@/api/shop"; import { toast } from "@/utils/common"; export function usePay(opt = {}) { const { createOrderError, // 创建订单失败 checkError, // 校验失败 payError, // 支付失败 paySuccess, //支付成功 applePayError, // 苹果内购失败 } = opt; const aliData = reactive({ orderId: null, // 订单编号 text: '', // 订单数据 }) const wxData = reactive({ appid: '', // 应用ID(AppID) mchid: '', noncestr: '', // 随机字符串 orderId: '', packageVal: '', partnerid: '', // 商户号(PartnerID) pid: '', prepayid: '', // 预支付交易会话ID timestamp: '', // 时间戳(单位:秒) sign: '', // 签名,这里用的 MD5 签名 package: '', // 固定值 }) const appleData = reactive({ chanpinId: null, // 产品ID paynum: "", // 支付号 receipt: "", // 票据 taocanId: null, // 套餐ID }) function resetStatus() { Object.assign(aliData, { orderId: null, // 订单编号 text: '', // 订单数据 }) Object.assign(wxData, { appid: '', // 应用ID(AppID) mchid: '', noncestr: '', // 随机字符串 orderId: '', packageVal: '', partnerid: '', // 商户号(PartnerID) pid: '', prepayid: '', // 预支付交易会话ID timestamp: '', // 时间戳(单位:秒) sign: '', // 签名,这里用的 MD5 签名 package: '', // 固定值 }) Object.assign(appleData, { chanpinId: null, // 产品ID paynum: "", // 支付号 receipt: "", // 票据 taocanId: null, // 套餐ID }) } // 支付入口 type:业务类型:wx|ali|apple; options: 入参chanpinId,taocanId,applePid function OrderPay(type, options) { // 初始化支付状态 resetStatus(); const { chanpinId, taocanId, applePid, // 苹果商品Id ---> 用来获取支付号+票据 } = options; if (!chanpinId) { toast('数据异常,产品信息丢失') return; } if (!taocanId) { toast('数据异常,套餐信息丢失') return; } if (type == 'wx') { uni.showLoading({ title: '订单创建中...', mask: true }); // 微信 orderPayWx({ chanpinId, taocanId }).then(res => { uni.hideLoading(); if (res.data.code == 0) { Object.assign(wxData, res.data); // 开始支付 wxPay(res.data); } else { toast('订单创建失败') // 业务异常 createOrderError && createOrderError({ type: 'CreateOrderError', msg: '业务异常,创建订单返回状态异常', err: new Error('业务异常,创建订单返回状态异常'), form: 'wx' }) } }).catch(err => { uni.hideLoading(); toast('订单创建失败') createOrderError && createOrderError({ type: 'CreateOrderError', msg: '创建微信订单失败', err, form: 'wx' }) }) } if (type == 'ali') { uni.showLoading({ title: '订单创建中...', mask: true }); // 支付宝 orderPayAli({ chanpinId, taocanId }).then(res => { uni.hideLoading(); if (res.data.code == 0) { Object.assign(aliData, res.data); // 开始支付 aliPay(res.data); } else { toast('订单创建失败') // 业务异常 createOrderError && createOrderError({ type: 'CreateOrderError', msg: '业务异常,创建订单返回状态异常', err: new Error('业务异常,创建订单返回状态异常'), form: 'ali' }) } }).catch(err => { uni.hideLoading(); createOrderError && createOrderError({ type: 'CreateOrderError', msg: '创建微信订单失败', err, form: 'ali' }) }) } if (type == 'apple') { if (!applePid) { toast('数据异常,商品信息丢失') return; } uni.showLoading({ title: '订单创建中...', mask: true }); applePay(options) } } // 微信支付 function wxPay(options) { Object.assign(wxData, options); try { uni.requestPayment({ provider: "wxpay", orderInfo: options, success: (res) => { uni.showLoading({ title: '订单支付中...', mask: true }); // 校验支付结果 setTimeout(() => OrderCheckWx(), 1000) }, fail: (err) => { payError && payError({ type: 'wxPay', msg: '微信支付失败', err, from: 'uni.requestPayment.fail' }) } }) } catch (err) { payError && payError({ type: 'wxPay', msg: '微信支付API唤起失败', err, from: 'uni.requestPayment' }) } } // 校验 function OrderCheckWx() { orderCheck({ id: wxData.orderId }).then(res => { if (res.code == 0 && res.data) { // 校验通过,支付成功 paySuccessResult(); } else { setTimeout(() => { orderCheck({ id: wxData.orderId }).then(res2 => { if (res2.code == 0 && res2.data) { // 校验通过,支付成功 paySuccessResult(); } }).catch(err1 => { uni.hideLoading() toast('支付二次查验失败,请联系管理员') checkError && checkError({ type: 'OrderCheckWx', msg: '支付二次查验失败,请联系管理员', err: err1, form: 'wx' }) }) }, 5000) } }).catch(err => { uni.hideLoading() toast('支付查验失败,请联系管理员') checkError && checkError({ type: 'OrderCheckWx', msg: '支付查验失败,请联系管理员', err: err, form: 'wx' }) }) } // 支付宝支付 function aliPay(options) { Object.assign(aliData, options); try { uni.requestPayment({ provider: "alipay", orderInfo: options.text, //此处为服务器返回的订单信息字符串 success: (res) => { uni.showLoading({ title: '订单支付中...', mask: true }); // 校验支付结果 setTimeout(() => OrderCheckAli(), 1000) }, fail: (err) => { payError && payError({ type: 'aliPay', msg: '支付宝支付失败', err, from: 'uni.requestPayment.fail' }) } }) } catch (err) { payError && payError({ type: 'aliPay', msg: '支付宝API唤起失败', err, from: "uni.requestPayment" }) } } // 校验 function OrderCheckAli() { orderCheck({ id: aliData.orderId }).then(res => { if (res.code == 0 && res.data) { // 校验通过,支付成功 paySuccessResult(); } else { setTimeout(() => { orderCheck({ id: aliData.orderId }).then(res2 => { if (res2.code == 0 && res2.data) { // 校验通过,支付成功 paySuccessResult(); } }).catch(err1 => { uni.hideLoading() toast('支付二次查验失败,请联系管理员') checkError && checkError({ type: 'OrderCheckAli', msg: '支付二次查验失败,请联系管理员', err: err1, form: 'ali' }) }) }, 5000) } }).catch(err => { uni.hideLoading() toast('支付查验失败,请联系管理员') checkError && checkError({ type: 'OrderCheckAli', msg: '支付查验失败,请联系管理员', err: err, form: 'ali' }) }) } // 苹果支付 --- 无需check 直接购买成功 function applePay(options) { Object.assign(appleData, options) try { plus.payment.getChannels(function(channels) { uni.hideLoading(); // 获取 id 为 'appleiap' 的 channel // 开通了app应用内支付,在manifest.josn中设置,开通后需打自定议基座 // iapChannel 为应用内支付对象 const iapChannel = channels.find((item) => item.id == "appleiap"); // ids 数组中的项为 App Store Connect 配置的内购买项目产品ID(productId) if (!iapChannel) { toast('未找到产品内购信息,请联系管理员') applePayError && applePayError({ type: "applePay", msg: "内购商品Id丢失,请确认是否已成功配置", err: new Error("内购商品Id丢失,请确认是否已成功配置"), from: "apple", }); return; } const ids = [options.applePid]; iapChannel.requestOrder( ids, function(e) { // 获取订单信息成功回调方法 uni.requestPayment({ provider: "appleiap", orderInfo: { productid: options.applePid, //产品id,来自于苹果 quantity: 1, //产品数量 manualFinishTransaction: true, }, success: (e) => { // 苹果内购成功 const { transactionIdentifier: paynum, transactionReceipt: receipt, } = e; Object.assign(appleData, { paynum, receipt, }); orderPayApple({ chanpinId: appleData.chanpinId, // 产品ID paynum: paynum, // 支付号 receipt: receipt, // 票据 taocanId: chanpinId.taocanId, // 套餐ID }) .then((res) => { uni.hideLoading(); if (res.code == 0 && res.data) { // 完成内购 iapChannel.finishTransaction(data .transactionIdentifier); // 购买成功 paySuccessResult(); } else { iapChannel.finishTransaction(data .transactionIdentifier); toast("业务异常,订单支付失败,请联系管理员"); applePayError && applePayError({ type: "orderPayApple", msg: "业务异常,订单支付失败", err: e, from: "apple", }); } }) .catch((err) => { uni.hideLoading(); applePayError && applePayError({ type: "orderPayApple", msg: "订单支付校验失败", err: e, from: "apple", }); }); }, fail: (e) => { uni.hideLoading(); toast("苹果购买失败,请联系管理员"); applePayError && applePayError({ type: "uni.requestPayment", msg: "苹果内购失败", err: e, from: "apple", }); }, }); }, function(e) { // 获取订单信息失败回调方法 uni.hideLoading(); toast('内购订单获取失败,请联系管理员') applePayError && applePayError({ type: "uni.requestPayment", msg: "苹果内购失败", err: e, from: "apple", }); }, ); }); } catch (err) { applePayError && applePayError({ type: "uni.requestPayment", msg: "苹果内购API唤起失败", err: e, from: "plus.payment.getChannels", }); } } // 支付成功 function paySuccessResult() { uni.hideLoading() toast('支付成功') paySuccess && paySuccess(); } return { OrderPay } } /** * 错误 * 1. 创建订单错误 * 2. 支付SDK错误 * 3. 支付成功后,后台错误 * * * * * * * * * * * * */