uniapp 小程序跳转

uniapp 支付宝小程序之间跳转?

Posted by My on February 28, 2025

前言

目前遇到这么一个需求,在业务中,需要对接第三方平台的功能,使用他们的插件。在调用他们插件时,需要提供 userId,但随着支付宝小程序版本的迭代,新申请的支付宝小程序都默认是返回 openId,因此,针对这个问题,有几种不同的方案。

  • 方案一: 第三方插件使用 openId 进行用户鉴权。

  • 方案二: 使用 userId 接入第三方插件。 将当前小程序进行降级回退处理,后续都使用 userId 进行鉴权。

  • 方案三: 使用 userId 接入第三方插件。 再申请一个同主体的旧版小程序,在处理业务时,跳到到旧版小程序获取 userId,再返回当前下程序进行相关业务处理。

经过多方讨论,决定采用方案二。

准备工作

1.小程序准备

在支付宝开发平台重新申请一个旧版小程序,并拉入开发人员和配置好域名白名单等信息。

2.小程序配置

一些 uniapp 项目的基本配置,如 appid 等。

1. appId 配置

使用 HBuilderX 创建一个 ``项目,并在manifest.json文件中配置appid

2. 自定义运行配置

新增 package.json 文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{
  "uni-app": {
    "scripts": {
      "dev": {
        "title": "租车-开发环境",
        "env": {
          "ENV_TYPE": "dev",
          "UNI_PLATFORM": "mp-alipay"
        }
      },
      "prod": {
        "title": "租车-生产环境",
        "env": {
          "ENV_TYPE": "prod",
          "UNI_PLATFORM": "mp-alipay"
        }
      }
    }
  }
}

开发时,在 HBuilderX 中,点击 「运行」 就可以看到自定义运行的路径。 image.png

3. 简单的 api 环境配置

正常情况下,应该封装一个 request 方法,用来处理请求,并根据环境变量配置不同的请求地址。但这里只是为了为了获取 userId,因此仅一个接口,就不需要封装了,简单判断一下即可。

1
2
3
4
5
6
7
// config.js
const enObj = {
  dev: "https://dev.hldian.cn/cloud-user",
  prod: "https://prod.hldian.cn/cloud-user",
};
const env = process.env.ENV_TYPE;
export const apiUrl = enObj[env] || enObj.dev;

实现

需要从当前小程序(以下称为 A 程序)跳转到旧版小程序(以下称为 B 程序),并获取 userId,然后返回到 A 程序进行相关业务处理。

1. 跳转到 B 程序

根据支付宝开发文档提供的 api 进行跳转。因为是【同主体】下的两个小程序,因此不需要再做额外的跳转申请。

1
2
3
4
5
6
7
8
9
<script setup>

const getUserId = () => {
     my.navigateToMiniProgram({
        appId: "233222111000xxxx",
        success: (res) => {},
  });
}
<script>

注意: 如果是使用开发者工具进行模拟,那将无法跳转,需要使用【真机调试】。

如果已经真机调试并且跳转了,你会发现,还是无法跳转,错误提示如下:

image.jpeg

2. 跳转配置与方案

需要同时启动 A 程序和 B 程序。A 程序为了方便后续查看参数,可使用【真机调试】。B 程序使用 【预览】。

在小程序被打开后,点击右上角的胶囊【…】,在弹出来的弹窗中,点击【联调设置】,把「联调扫码版本」的开关打开。

3. B 程序获取 userId 并返回

B 程序在启动时,会触发 onLoad 方法,在这里可以获取 userId,并调用 navigateBackMiniProgram 方法返回 A 程序。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<script setup>
 const  getCode = ()=> {
      my.getAuthCode({
        scopes: "auth_user",
        success: (res) => {
          const authCode = res.authCode;
          uni.request({
            url: apiUrl + "/yourapi/apli?authCode=" + authCode,
            method: "POST",
            success: (res) => {
              const id = res.data.result;
              my.navigateBackMiniProgram({
                extraData: {
                  result: id,
                },
                success: (res) => {
                  console.log("返回 A 小程序成功", res);
                },
              });
            },
          });
        },
      });
    },
<script>

4. A 程序获取返回值

官方文档和一些 ai 的回答中,都是说在 onShow 的 「options」 中可以获取到返回值,但实际测试发现,并没有获取到。

经过测试发现,还是得调用 my.getEnterOptionsSync api 来获取返回值。

1
2
3
4
5
6
7
8
9
10
<script setup>
onShow() {
    const options = my.getEnterOptionsSync();
      if (options?.referrerInfo?.extraData) {
      const { result } = options.referrerInfo.extraData;
      // 拿到 userId 进行相关业务处理
    }
}
<script>

总结

到此,同个主体间的小程序之间的跳转就完成了,比较简单,但是还会有些坑,主要是由信息差异造成的。比如说需要在联调设置中打开开关,获取返回参数需要手动调用 my.getEnterOptionsSync 方法。

后续

上面的流程是没有问题的,当然,是在 ios 系统下操作的。当在 android 系统下操作时,失败了,如【实现】—— 【1. 跳转到 B 程序】中失败的提示。通过社区、ai、官方文档等都没有找到一个合理解决方案,有一个稍微可靠的是「需发布为体验版」。

在将 A、B 小程序发布为体验版后, ios 系统依然可以正常跳转,但 android 系统仍然无法跳转。通过多次测试,有一种情况下是可以跳转的:

  • 启动 B 程序体验版,并在「联调设置」中打开开关。

  • 启动 A 程序,点击按钮,触发跳转到 B 程序的逻辑。结果为失败。

  • 启动 B 程序开发版,进行「真机预览」,并在「联调设置」中打开开关。

  • 启动 A 程序,点击按钮,触发跳转到 B 程序的逻辑。结果为失败。

  • 将 B 程序开发版的「联调设置」关闭,并清楚缓存。打开 B 程序体验版,并在「联调设置」中打开开关。

  • 启动 A 程序,点击按钮,触发跳转到 B 程序的逻辑。结果为成功。

通过这种方式才能进行挑战,但是方式是比较繁琐的,目前还是没找到原因。 我觉得其核心点就是得先进入 B 程序的开发版,然后清除缓存,然后再进入体验版。