|
|
@@ -0,0 +1,501 @@
|
|
|
+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. 支付成功后,后台错误
|
|
|
+ *
|
|
|
+ *
|
|
|
+ *
|
|
|
+ *
|
|
|
+ *
|
|
|
+ *
|
|
|
+ *
|
|
|
+ *
|
|
|
+ *
|
|
|
+ *
|
|
|
+ *
|
|
|
+ *
|
|
|
+ */
|