ios mini.app.IPA

import { requestByGET, requestByPOST } from "@/utils/request";
const { default: WebTracking } = require("@/utils/webTracking");
Component({
  /**
   * 组件的属性列表
   */
  properties: {
    // 可以添加外部传入的属性
    showNavigation: {
      type: Boolean,
      value: true,
    },
    title: {
      type: String,
      value: "开通会员",
    },
  },

  /**
   * 组件的初始数据
   */
  data: {
    selectedCard: "", // 默认选择第一个卡片
    currentPrice: 0, // 当前价格
    bidData: [], // 标讯数据
    cardList: [], // 金额卡片列表
    loading: false,
    wxChat:
      "https://lianqiai-public.oss-accelerate.aliyuncs.com/app/vip/ic_wxChat.svg",
    ic_ok:
      "https://lianqiai-public.oss-accelerate.aliyuncs.com/app/vip/ic_ok.svg",
    openID: "",
    transactionObserver: null, // 保存交易观察者引用
  },

  /**
   * 组件的方法列表
   */
  methods: {
    /**
     * 组件初始化
     */
    init() {
      // 初始化已处理的交易记录
      this.processedTransactions = {}; // 已处理的交易ID
      this.verifiedReceipts = {}; // 已验证的收据

      this.loadBidData();
      this.initialize();
    },

    // 简单的哈希函数,用于生成字符串的哈希值
    simpleHash: function (str) {
      if (!str) return "empty";
      let hash = 0;
      for (let i = 0; i < str.length; i++) {
        const char = str.charCodeAt(i);
        hash = (hash << 5) - hash + char;
        hash = hash & hash; // 转换为32位整数
      }
      return Math.abs(hash).toString();
    },

    /**
     * 加载标讯数据
     */
    loadBidData() {
      this.setData({
        loading: true,
      });

      // 调用 /goods/bid/list 接口
      requestByGET(
        { type: "VIP_DATA" },
        "/goods/bid/list",
        (res) => {
          console.log("标讯数据加载成功:", res);
          if (res && res.data) {
            // 处理金额卡片数据
            const cardList = this.processCardData(res.data);

            // 找到第一个可购买的卡片作为默认选择
            const firstBuyableCard = cardList.find((card) => card.canBuy);

            this.setData({
              bidData: res.data.bidList || [],
              cardList: cardList,
              selectedCard: firstBuyableCard ? firstBuyableCard.code : "",
              currentPrice: firstBuyableCard
                ? firstBuyableCard.discountPrice || firstBuyableCard.price
                : 0,
              loading: false,
            });
            console.log(this.data.cardList);
          } else {
            // 如果没有数据,显示空状态
            this.setData({
              bidData: [],
              cardList: [],
              selectedCard: "",
              currentPrice: 0,
              loading: false,
            });
          }
        },
        (err) => {
          console.error("标讯数据加载失败:", err);
          // 加载失败时显示空状态
          this.setData({
            bidData: [],
            cardList: [],
            selectedCard: "",
            currentPrice: 0,
            loading: false,
          });
        }
      );
    },

    /**
     * 处理金额卡片数据
     */
    processCardData(data) {
      return data
        .map((card) => {
          // 计算每天价格
          const price = parseFloat(card.discountPrice || card.price);
          let dailyPrice = 0;
          if (card.code === "SVIP_data_year_1") {
            // 年卡:价格除以365天
            dailyPrice = (price / 365).toFixed(2);
          } else {
            // 月卡:价格除以30天
            dailyPrice = (price / 30).toFixed(2);
          }
          console.log(`卡片 ${card.name} 价格计算:`, {
            originalPrice: card.price,
            discountPrice: card.discountPrice,
            usedPrice: price,
            dailyPrice: dailyPrice,
            code: card.code,
          });
          return {
            id: card.id,
            name: card.name,
            code: card.code,
            price: card.price,
            discountPrice: card.discountPrice,
            description: card.description,
            canBuy: card.canBuy,
            tag: card.tag,
            discount: card.discount,
            expireTime: card.expireTime,
            functionTag: card.functionTag,
            itemCode: card.itemCode,
            daysLeft: card.daysLeft,
            dailyPrice: dailyPrice,
            appleProductId: card.appleProductId, // 添加Apple产品ID字段
          };
        })
        .reverse(); // 倒序排列
    },

    /**
     * 选择会员卡片
     */
    selectCard(e) {
      const cardCode = e.currentTarget.dataset.code;
      const selectedCard = this.data.cardList.find(
        (card) => card.code === cardCode
      );
      if (selectedCard && selectedCard.canBuy) {
        console.log("选中卡片:", {
          code: selectedCard.code,
          name: selectedCard.name,
          price: selectedCard.discountPrice || selectedCard.price,
          appleProductId: selectedCard.appleProductId, // 记录Apple产品ID
        });
        this.setData({
          selectedCard: cardCode,
          currentPrice: selectedCard.discountPrice || selectedCard.price,
        });
      } else if (selectedCard && !selectedCard.canBuy) {
        // 如果卡片不可购买,显示提示
        wx.showToast({
          title: "该套餐暂不可购买",
          icon: "none",
        });
      }
    },

    /**
     * 处理支付
     */
    handlePayment() {
      const { selectedCard, currentPrice, cardList } = this.data;
      const selectedCardData = this.data.cardList.find(
        (card) => card.code === selectedCard
      );
      if (!selectedCardData) {
        wx.showToast({
          title: "请选择会员套餐",
          icon: "none",
        });
        return;
      }
      // 检查选中的卡片是否可以购买
      if (!selectedCardData.canBuy) {
        wx.showToast({
          title: "该套餐暂不可购买",
          icon: "none",
        });
        return;
      }
      console.log("选中的卡片信息:", {
        code: selectedCardData.code,
        name: selectedCardData.name,
        price: currentPrice,
        originalPrice: selectedCardData.price,
        discountPrice: selectedCardData.discountPrice,
      });
      // #if IOS || ANDROID
      this.createOrder(selectedCardData.code);
      // #elif MP
      let that = this;
      wx.login({
        success(res) {
          console.log(res.code);
          that.setData(
            {
              openID: res.code,
            },
            () => {
              // setData 完成之后再调用 createOrder
              that.createOrder(selectedCardData.code, that.data.openID);
            }
          );
        },
      });
      // #endif
    },
    createOrder(code, opne_id) {
      let path;
      let params;
      // #if IOS || ANDROID
      path = "/order/createAppOrder";
      params = {
        goodsCode: code,
        quantity: 1,
        paymentMethod: "WECHAT",
      };
      // #elif MP
      path = "/order/createMnpOrder";
      params = {
        goodsCode: code,
        quantity: 1,
        paymentMethod: "WECHAT",
        code: opne_id,
      };
      // #endif
      requestByPOST(
        params,
        path,
        (res) => {
          console.log("createOrder res: ", res, path);
          const prepayId = "prepay_id=" + res.data.prepayId;
          // #if IOS || ANDROID
          wx.miniapp.requestPayment({
            timeStamp: res.data.timestamp,
            mchId: res.data.partnerId,
            prepayId: res.data.prepayId,
            package: res.data.packageValue,
            nonceStr: res.data.nonceStr,
            sign: res.data.sign,
            success: (res) => {
              console.warn("wx.miniapp.requestPayment success:", res);
              // 触发支付成功事件
              // this.triggerEvent("paySuccess", { result: res });
              wx.showToast({
                title: "支付成功",
                icon: "none",
              });
              setTimeout(() => {
                wx.navigateBack();
              }, 2000);
            },
            fail: (res) => {
              console.error("fail res:", res);
              wx.showToast({
                title: "取消支付",
                icon: "none",
              });
              // 触发支付失败事件
              this.triggerEvent("payFail", { result: res });
            },
            complete: (res) => {
              console.error("complete res:", res);
            },
          });

          // #elif MP
          wx.requestPayment({
            timeStamp: res.data.timestamp,
            nonceStr: res.data.nonceStr,
            package: prepayId,
            signType: res.data.signType,
            paySign: res.data.paySign,
            orderNo: res.data.orderId,
            appId: res.data.appId,
            success(res) {
              console.log("createOrder success res: ", res);
              // 触发支付成功事件
              // this.triggerEvent("paySuccess", { result: res });
              wx.showToast({
                title: "支付成功",
                icon: "none",
              });
              setTimeout(() => {
                wx.navigateBack();
              }, 2000);
              WebTracking.log("支付成功");
            },
            fail(res) {
              console.log("createOrder fail: ", res);
              wx.showToast({
                title: "取消支付",
                icon: "none",
              });
              // 触发支付失败事件
              this.triggerEvent("payFail", { result: res });
            },
          });
          // #endif
        },
        (err) => {
          console.error("createOrder err: ", err);
          // 触发支付失败事件
          this.triggerEvent("payFail", { error: err });
        }
      );
    },

    /**
     * 处理支付逻辑
     */
    processPayment(selectedCardData) {
      const { selectedCard, currentPrice } = this.data;

      console.log("开始支付,卡片code:", selectedCardData.code);

      wx.showLoading({
        title: "正在支付...",
      });

      // 这里可以调用支付接口,传递code参数
      // 目前只支持微信支付
      setTimeout(() => {
        wx.hideLoading();
        wx.showToast({
          title: "支付成功",
          icon: "success",
          duration: 2000,
        });

        // 支付成功后可以跳转到其他页面或刷新数据
        setTimeout(() => {
          wx.navigateBack();
        }, 2000);
      }, 1500);
    },

    //IOSAPP支付观察者
    initialize: function () {
      console.log("初始化交易观察者");
      // 如果已经存在观察者,先移除
      if (this.data.transactionObserver) {
        this.removeTransactionObserver();
      }

      const ob = {
        updatedTransactions: (args) => {
          console.log("处理交易状态更新,例如购买成功或失败。:", args);
          console.log(
            "收到的交易数量:",
            args.transactions ? args.transactions.length : 0
          );
          args.transactions.forEach((item, index) => {
            console.log(`处理第 ${index + 1} 个交易:`, item.transactionState);
            this.handleTransaction(item);
          });
        },
        restoreCompletedTransactionsFailedWithError: (args) => {
          console.log("处理恢复购买时出现的错误。", args);
        },
        paymentQueueRestoreCompletedTransactionsFinished: (args) => {
          console.log("在恢复购买交易完成时调用。", args);
        },
        shouldAddStorePayment: (args) => {
          console.log("询问是否应该添加商店付款。", args);
        },
        paymentQueueDidChangeStorefront: (args) => {
          console.log("处理 App Store 店面变化。", args);
        },
        didRevokeEntitlementsForProductIdentifiers: (args) => {
          console.log("处理撤销某些产品的权限。", args);
        },
      };

      // 保存观察者引用
      this.setData({
        transactionObserver: ob,
      });

      // 添加观察者
      wx.miniapp.IAP.addTransactionObserver(ob);
    },
    //ios支付按钮
    handlePaymentIOS() {
      // 获取选中的卡片数据
      const { selectedCard, cardList } = this.data;
      const selectedCardData = cardList.find(
        (card) => card.code === selectedCard
      );
      console.log(selectedCardData.appleProductId);
      if (!selectedCardData) {
        wx.showToast({
          title: "请选择会员套餐",
          icon: "none",
        });
        return;
      }
      wx.showLoading({
        title: "加载中",
      });
      let that = this;
      const requestObj = wx.miniapp.IAP.requestSKProducts({
        productIdentifiers: [selectedCardData.appleProductId],
        success(ret) {
          console.log(ret.invalidProductIdentifiers, "我是393",ret.products);
          // 先创建苹果订单,获取orderUuid
          that.createAppleOrder(selectedCardData.code, ret.products);
        },
        fail(error) {
          console.error(`requestSKProducts failed. ${error}`);
          wx.hideLoading();
        },
      });
      wx.miniapp.IAP.cancelRequestSKProducts(requestObj);
    },

    // 创建苹果订单
    createAppleOrder: function (goodsCode, products) {
      const params = {
        goodsCode: goodsCode,
        quantity: 1,
        paymentMethod: "APPLE",
      };

      requestByPOST(
        params,
        "/order/createAppleAppOrder",
        (res) => {
          console.log("createAppleOrder success: ", res);
          if (res && res.data && res.data.orderUuid) {
            // 创建订单成功,开始支付流程
            this.startPayment(null, products, res.data.orderUuid);
          } else {
            console.error("创建苹果订单失败: 未获取到orderUuid");
            wx.hideLoading();
            wx.showToast({
              title: "订单创建失败",
              icon: "none",
            });
          }
        },
        (err) => {
          console.error("createAppleOrder error: ", err);
          wx.hideLoading();
          wx.showToast({
            title: "订单创建失败",
            icon: "none",
          });
        }
      );
    },

    //IOSAPP支付请求结果
    startPayment: function (err, productIdentifier, orderUuid) {
      if (err) {
        wx.showToast({
          title: err,
          icon: "none",
        });
        wx.hideLoading();
        return;
      }
      wx.miniapp.IAP.addPaymentByProductIdentifiers({
        productIdentifier: productIdentifier[0].productIdentifier,
        applicationUsername: orderUuid,
        success: (args) => {
          console.log("拉起支付成功", args);
          // wx.hideLoading();
        },
        fail: (args) => {
          console.error("拉起支付失败", args);
          // wx.hideLoading();
        },
      });
    },
    //IOSAPP处理交易
    handleTransaction: function (transaction) {
      console.log( "处理交易状态:",transaction.transactionState,"交易ID:", transaction.transactionIdentifier);
      // 创建更可靠的交易唯一标识
      let transactionKey;
      if (transaction.transactionIdentifier) {
        // 如果有交易ID,使用交易ID + 状态
        transactionKey =
          transaction.transactionIdentifier +
          "_" +
          transaction.transactionState;
      } else if (transaction.transactionReceipt) {
        // 如果没有交易ID但有收据,使用收据的哈希值 + 状态
        transactionKey =
          this.simpleHash(transaction.transactionReceipt) +
          "_" +
          transaction.transactionState;
      } else {
        // 如果都没有,使用时间戳 + 状态(最后的兜底方案)
        transactionKey = Date.now() + "_" + transaction.transactionState;
        console.warn("交易缺少标识符,使用时间戳作为标识:", transactionKey);
      }
      console.log("生成的交易标识:", transactionKey);
      // 在观察者层面阻断重复处理同一交易
      if (this.processedTransactions[transactionKey]) {
        console.log("交易已处理过,跳过重复处理:", transactionKey);
        return;
      }
      // 标记交易为已处理
      this.processedTransactions[transactionKey] = true;
      console.log("标记交易为已处理:", transactionKey);
      if (
        transaction.transactionState === "SKPaymentTransactionStatePurchased" ||
        transaction.transactionState === "SKPaymentTransactionStateRestored"
      ) {
        console.log(transaction.transactionReceipt, "订单收据");
        this.finishTransaction(null, transaction);
      } else if (
        transaction.transactionState === "SKPaymentTransactionStateFailed"
      ) {
        this.finishTransaction("交易失败", transaction);
      } else if (
        transaction.transactionState === "SKPaymentTransactionStateDeferred"
      ) {
        this.finishTransaction("等待外部操作", transaction);
      }
    },

    //IOSAPP处理结束交易的结果。
    finishTransaction: function (err, transaction) {
      if (err) {
        wx.showToast({
          title: err,
          icon: "none",
        });
        return;
      }
      wx.miniapp.IAP.finishTransaction({
        transactionIdentifier: transaction.transactionIdentifier,
        success: (args) => {
          console.log("完成交易 success", args);
          // 调用苹果支付验证接口
          this.verifyApplePayment(transaction.transactionReceipt);
        },
        fail: (args) => {
          console.error("完成交易 fail", args);
          wx.hideLoading();
        },
      });
    },

    // 验证苹果支付凭据
    verifyApplePayment: function (transactionReceipt) {
      console.log("开始验证苹果支付凭据", transactionReceipt);
      console.log("收据类型:", typeof transactionReceipt);
      console.log(
        "收据长度:",
        transactionReceipt ? transactionReceipt.length : "undefined"
      );
      // 双重保护:检查收据是否已经验证过
      const receiptHash = this.simpleHash(transactionReceipt);
      if (this.verifiedReceipts[receiptHash]) {
        console.log("收据已验证过,跳过重复验证:", receiptHash);
        return;
      }
      // 标记收据为正在验证
      this.verifiedReceipts[receiptHash] = true;
      console.log("标记收据为验证中:", receiptHash);
      const params = {
        receipt: transactionReceipt,
      };
      // 调用验证接口
      requestByPOST(
        params,
        "/appleIap/verify",
        (res) => {
          console.log("苹果支付验证结果: ", res);
          wx.hideLoading();

          if (res && res.code === 200 && res.data === true) {
            // 验证成功,下发权益成功
            wx.showToast({
              title: "支付成功",
              icon: "none",
            });
            setTimeout(() => {
              wx.navigateBack();
            }, 2000);
          } else {
            // 验证失败或下发权益失败
            wx.showToast({
              title: "下发权益失败,请联系客服",
              icon: "none",
              duration: 3000,
            });
          }
        },
        (err) => {
          console.error("苹果支付验证失败: ", err);
          wx.hideLoading();
          wx.showToast({
            title: "下发权益失败,联系客服",
            icon: "none",
            duration: 3000,
          });
        }
      );
    },

    //IOSAPP恢复交易列表
    restoreTransactions: function (callback) {
      wx.miniapp.IAP.restoreCompletedTransactions({
        success: (transactions) => {
          console.log("恢复的交易", transactions);
          callback(null, transactions);
        },
        fail: (error) => {
          console.error("恢复交易失败", error);
          callback(error);
        },
      });
    },
    //IOSAPP交易收据
    getReceiptURL: function () {
      let that = this;
      ReceiptURL({
        success: (url) => {
          console.log("交易收据 URL", url);
          that.getReceiptData(null, url);
        },
        fail: (error) => {
          console.error("获取收据 URL 失败", error);
          that.getReceiptData("获取收据 URL 失败");
        },
      });
    },
    getReceiptData: function (err) {
      if (err) {
        wx.showToast({
          title: err,
          icon: "none",
        });
        return;
      }
      wx.miniapp.IAP.getAppStoreReceiptData({
        success: (data) => {
          console.log("交易收据数据", data);
          // 调用后端接口传送交易数据
        },
        fail: (error) => {
          console.error("获取收据数据失败", error);
        },
      });
    },

    //IOSAPP刷新收据结果
    refreshReceipt: function (err, callback) {
      if (err) {
        wx.showToast({
          title: err,
          icon: "none",
        });
        return;
      }
      wx.miniapp.IAP.requestSKReceiptRefreshRequest({
        success: (args) => {
          console.log("刷新收据成功", args);
          callback(null, args);
        },
        fail: (error) => {
          console.error("刷新收据失败", error);
          callback(error);
        },
      });
    },

    // 移除交易观察者
    removeTransactionObserver: function () {
      if (this.data.transactionObserver) {
        console.log("移除交易观察者");
        // 正确的移除方式:直接传递观察者对象
        wx.miniapp.IAP.removeTransactionObserver(this.data.transactionObserver);
        this.setData({
          transactionObserver: null,
        });
      }

      // 清理验证状态
      if (this.processedTransactions) {
        this.processedTransactions = {};
      }
      if (this.verifiedReceipts) {
        this.verifiedReceipts = {};
      }
    },

    /**
     * 刷新数据
     */
    refresh() {
      this.loadBidData();
    },

    /**
     * 返回上一页
     */
    goBack() {
      wx.navigateBack();
    },
  },

  /**
   * 组件生命周期
   */
  lifetimes: {
    attached() {
      this.init();
    },
    detached() {
      this.removeTransactionObserver();
    },
  },
});

handlePaymentIO 从这个按钮开始看

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值