【小程序】requestSubscribeMessage:fail can only be invoked by user TAP gesture 头条小程序调起订阅消息失败及多端兼容解决方案

2023/07/12 12:18:13

在对接消息订阅功能时,出现了调用 uni.requestSubscribeMessage 后无法唤起订阅消息窗口的情况。

支付宝、微信小程序的行为

uni.requestSubscribeMessage 之前存在异步逻辑时无法唤起,但是在 uni.showModal 的回调中调用时可以唤起。

抖音、快手小程序的行为

抖音小程序中 uni.requestSubscribeMessage 事件必须手动点击直接触发,不能在回调中触发:见 tt.requestSubscribeMessage 返回错误open in new window 中的评论。

在抖音中必须在点击事件中直接调用 uni.requestSubscribeMessage 才可以唤起窗口,并且之前不能存在异步逻辑,因此如果模板 id 是通过后端接口获取的,就要在点击事件之前先获取到模板 id 才可以。

uni.requestSubscribeMessage 之前存在异步逻辑时无法唤起,在 uni.showModal 的回调中调用时也不能唤起。

解决方案

对于上述的问题,一个解决的思路是自己封装一个 modal 组件,而不是直接用小程序自带的 uni.showModal。在初始化 modal 组件时异步获取模板 id,在点击事件中调用 uni.requestSubscribeMessage,这样就可以统一多端的发起订阅消息请求逻辑。

需要注意的是必须直接在点击事件中调用,否则抖音和快手依然是不生效的。

  • 订阅消息组件:
<template>
  <HmModal :isShowModal="isShowRequestMessageModal" @closeModal="emitCancel">
    <view slot="body"> 为了通知您办理进度,需要向您推送相关消息 </view>
    <view slot="footer" class="c-modal-footer">
      <view class="c-modal-footer-btn cancel" @click="emitCancel">取消</view>
      <view class="c-modal-footer-btn confirm" @click="confirm">确认</view>
    </view>
  </HmModal>
</template>

<script>
// 抖音、快手需要由点击事件直接触发,不能在 uni.showModal 的回调中触发
import HmModal from "@/components/modal/HmModal";
import SubscribeService from "@/services/bussiness/subscribe/SubscribeService";
import Env from "@/env/Env";

export default {
  components: {
    HmModal,
  },
  data() {
    return {
      templIds: null,
    };
  },
  props: ["isShowModal"],
  computed: {
    isShowRequestMessageModal() {
      return this.templIds && this.templIds.length > 0 && this.isShowModal;
    },
  },
  methods: {
    async confirm() {
      await SubscribeService.requestSubscribeMessageByTmplIds(this.templIds);
      this.emitConfirm();
    },
    emitConfirm() {
      this.$emit("confirm");
    },
    emitCancel() {
      this.$emit("cancel");
    },
    emitNoTemplate() {
      this.$emit("not-support");
    },
  },
  async created() {
    if (Env.PLATFORM.ALIPAY) {
      this.emitNoTemplate();
    } else {
      this.templIds = await SubscribeService.getTemplIds().catch(console.error);
      if (!this.templIds || this.templIds.length === 0) {
        this.emitNoTemplate();
      }
    }
  },
};
</script>
  • 使用订阅消息组件:
<template>
  <view>
    <HmSubscribeMessageModal
      :isShowModal="isShowSubscribeMessageModal"
      @cancel="closeSubscribeMessageModal"
      @confirm="confirmSubscribeMessageModal"
      @not-support="isSportSubscribeMessage = false"
    />
  </view>
</template>
<script>
export default {
  data() {
    return {
      isShowSubscribeMessageModal: false,
      isSportSubscribeMessage: true, // 是否支持模板消息
    };
  },
  methods: {
    // 消息订阅确认框
    showSubscribeMessageModal() {
      this.isShowSubscribeMessageModal = true;
    },
    closeSubscribeMessageModal() {
      this.isShowSubscribeMessageModal = false;
      // 订阅失败
    },
    confirmSubscribeMessageModal() {
      this.isShowSubscribeMessageModal = false;
      // 订阅成功
    },
    submit() {
      if (this.isSportSubscribeMessage) {
        this.showSubscribeMessageModal();
      }
    },
  },
};
</script>

参考

tt.requestSubscribeMessage 返回错误open in new window

requestSubscribeMessage:fail can only be invoked by user TAP gesture 微信小程序调起订阅消息失败open in new window