如何让已经开发好的微信小程序运行在自有APP中

简介: 其实现在很多团队都有自己的小程序,但这些小程序大部分都是运行在微信上的,今天分享一个新的技术解决方案:借助小程序容器的技术将这些小程序运行在自己的APP里。 特别是商城、预约、会员中心、业务查询,这些服务可能已经在微信里跑了几年,页面和接口都比较成熟,业务人员也已经习惯了小程序的开发和发布方式。

其实现在很多团队都有自己的小程序,但这些小程序大部分都是运行在微信上的,今天分享一个新的技术解决方案:借助小程序容器的技术将这些小程序运行在自己的APP里。

特别是商城、预约、会员中心、业务查询,这些服务可能已经在微信里跑了几年,页面和接口都比较成熟,业务人员也已经习惯了小程序的开发和发布方式。

但等企业开始运营自己的APP,就需要看看,如何低成本的把这些服务搬迁到自有的APP中。

一种方案是:直接重写成原生页面,Android和iOS都要投入人力,测试、发版和后续维护也会多出两套工作。换成H5能少写一些界面,但原有小程序的组件、路由、分包和生命周期很难原样搬过来。更麻烦的是,微信小程序还要继续维护。一个需求改动,可能要同时照顾微信、APP原生和H5,业务越多,重复建设越明显。

那还有一个技术方案:在自己的APP里接入小程序容器,让APP先具备运行小程序的能力,再把已有微信小程序迁进来。原来的页面和业务逻辑能复用的继续复用,需要调整的地方集中处理,版本则交给小程序管理平台统一发布。

例如FinClip的小程序管理平台,宿主APP集成小程序运行时SDK,已有小程序代码上传到管理平台,APP通过小程序ID打开对应服务,它并不会把微信客户端搬进企业APP,而是在APP内部提供一套兼容小程序语法的运行环境。

cover_16_9.png

已有小程序为什么不能直接放进APP

微信小程序工程里的WXML、WXSS、JavaScript和JSON,只是一套业务代码。它能够在微信中运行,是因为微信客户端在背后完成了代码包加载、页面渲染、路由管理、脚本执行和生命周期调度,还把定位、相机、文件等接口接到了手机系统。

离开微信之后,这套运行环境也就没有了。把小程序目录复制到Android或iOS工程里,客户端并不知道该怎么解释这些文件,更不会自动处理页面跳转和小程序API。

小程序容器补的正是这一层。FinClip SDK集成到宿主APP后,负责下载和缓存小程序代码包,创建页面运行环境,处理前后台切换,并把小程序侧发起的能力调用交给端上。原有小程序依然以代码包运行,不需要先改造成原生页面。

但只有端上的运行时还不够。APP打开哪个小程序、使用哪个版本、哪些宿主可以访问,都要有后台管理。FinClip小程序管理平台保存小程序资产和代码版本,处理体验、审核、发布、灰度、回退与下架,并维护小程序和宿主应用之间的关联关系。

这样一来,端上负责把小程序跑起来,平台负责管理代码包和版本。两边合在一起,才是一套能够长期维护的接入方式。

APP、小程序和管理平台各自负责什么

接入小程序容器后,宿主APP原有的职责不会消失。账号体系、首页入口、原生导航、系统权限、支付、消息以及设备能力,仍然由APP掌握。小程序负责商城、预约、查询、活动等独立业务页面,继续访问原有业务后台。

用户从APP首页点击入口时,宿主先检查登录状态和业务参数,再把小程序ID、目标页面和启动参数交给FinClip SDK。运行时从本地缓存或管理平台取得代码包,创建小程序页面,并将页面展示在APP内。用户退出小程序后,仍然回到宿主原有的导航和页面栈中。

登录、支付、定位一类能力会多走一步。小程序发起调用后,运行时把请求交给宿主APP,由宿主判断当前小程序是否有权限,再调用原生能力或企业服务。小程序不需要知道Android和iOS分别用了什么实现,宿主也不用接管小程序内部的页面开发。

管理平台处在这条链路的另一端。平台中先创建宿主应用,配置Android Application ID或iOS Bundle ID,再生成SDK初始化所需的SDK Key、SDK Secret和服务器配置。小程序上传并发布后,还要和指定宿主应用建立关联。SDK初始化成功只代表运行环境可用,没有完成应用关联的小程序依然不能随意打开。

现有微信小程序能复用多少

如果项目使用标准微信小程序语法开发,可以直接从现有源码开始迁移。WXML页面、WXSS样式、JavaScript逻辑、JSON配置、自定义组件、页面路由、表单校验以及普通网络请求,通常都能保留。FinClip已经兼容的wx.*接口,也不用为了换一个运行环境全部改写成另一套前缀。

使用Taro、uni-app、kbone等框架的项目,可以先按照原来的构建流程输出微信小程序代码,再进行兼容检查和真机测试。对业务团队来说,代码仓库和日常开发方式不一定要推倒重来,迁移工作更多集中在平台差异和宿主能力的衔接上。

页面能打开,只能说明入口已经接通。迁移时还要继续检查云开发、微信插件市场插件、多线程Worker、微信服务端API、WXWebAssembly等能力。它们和微信环境结合得更深,可能需要替换、补充适配,或者暂时保留在微信端。具体支持范围也会受到SDK与基础库版本影响,项目要按实际使用版本核对能力清单。

微信登录、微信支付、订阅消息、客服、广告等能力也要单独看。这些能力连接的是微信账号或微信侧服务,进入自有APP后,通常要接到APP自己的账号、支付、推送和客服体系。小程序页面可以继续用,渠道相关的部分需要重新接线。

所以,代码复用比例很少由页面数量决定,更多取决于项目用了多少微信专属能力。业务页面越独立、接口越标准,迁移工作越集中;如果登录、支付和服务端能力都深度依赖微信,评估阶段就要把这些改造项列出来。

inline_01_architecture.png

把小程序运行时接进宿主APP

Android应用通常在Application中初始化SDK。FinClip SDK以多进程方式运行小程序时,小程序进程不应重复执行宿主初始化逻辑,因此要先判断当前进程:

@Override
public void onCreate() {
   
    super.onCreate();

    if (FinAppClient.INSTANCE.isFinAppProcess(this)) {
   
        return;
    }

    FinAppConfig config = new FinAppConfig.Builder()
            .setFinStoreConfigs(storeConfigs)
            .build();

    FinAppClient.INSTANCE.init(this, config, new FinCallback<Object>() {
   
        @Override
        public void onSuccess(Object result) {
   
            Log.i("FinClip", "SDK initialized");
        }

        @Override
        public void onError(int code, String error) {
   
            Log.e("FinClip", "SDK init failed: " + code + ", " + error);
        }

        @Override
        public void onProgress(int status, String info) {
   
        }
    });
}

初始化完成后,APP可以按照小程序ID打开线上版本,并把目标页面和业务参数一起传入:

Map<String, String> params = new HashMap<>();
params.put("path", "/pages/order/detail");
params.put("query", "orderId=20260806001&from=app");

FinAppClient.INSTANCE.getAppletApiManager().startApplet(
        this,
        IFinAppletRequest.Companion.fromAppId(apiServer, appId)
                .setStartParams(params),
        new FinSimpleCallback<String>() {
   
            @Override
            public void onSuccess(String result) {
   
                Log.i("FinClip", "Applet started");
            }

            @Override
            public void onError(int code, String error) {
   
                Log.e("FinClip", "Applet start failed: " + code + ", " + error);
            }
        }
);

path对应小程序页面路径,query可以携带订单号、来源渠道等参数。线上接入时,APP要先校验登录状态、参数格式和目标页面,不能把外部传入的内容原样交给小程序。SDK初始化失败、代码包下载失败或小程序未上架时,也要给用户留出明确的提示和返回入口。

iOS侧通过FATClient完成初始化。下面同样使用FinClip SDK文档中的真实调用方式:

FATStoreConfig *storeConfig = [[FATStoreConfig alloc] init];
storeConfig.sdkKey = @"SDK Key";
storeConfig.sdkSecret = @"SDK Secret";
storeConfig.apiServer = @"服务器地址";

FATConfig *config = [FATConfig configWithStoreConfigs:@[storeConfig]];
NSError *initError = nil;
BOOL initialized = [[FATClient sharedClient] initWithConfig:config
                                                      error:&initError];
if (!initialized) {
   
    NSLog(@"FinClip SDK初始化失败:%@", initError);
}

打开小程序时,通过FATAppletRequest设置小程序ID、服务器地址和启动参数:

FATAppletRequest *request = [[FATAppletRequest alloc] init];
request.appletId = @"小程序id";
request.apiServer = @"服务器地址";
request.startParams = @{
   
    @"path": @"/pages/order/detail",
    @"query": @"orderId=20260806001&from=app"
};

[[FATClient sharedClient]
    startAppletWithRequest:request
    InParentViewController:self
    completion:^(BOOL result, FATError *error) {
   
        NSLog(@"打开小程序:%@", error);
    }
    closeCompletion:^{
   
        NSLog(@"关闭小程序");
    }];

这些代码完成的是运行时初始化和小程序启动。账号怎样传递、支付由哪一侧执行、哪个小程序可以使用定位或相册,仍要由项目自己制定规则。SDK把调用链打通了,业务边界和权限边界不会自动生成。

小程序能打开之后,版本从哪里来

如果只停留在演示阶段,团队很容易把注意力都放在“页面能不能打开”上。等业务开始持续更新,版本从哪里上传、怎样审核、出现问题怎么退回,就会变成绕不开的工作。缺少管理平台时,小程序每改一个页面都可能牵动宿主APP发版,Android和iOS还要分别走应用商店审核。

实际接入中,已有工程可以通过FinClip Studio进行检查和上传,再在管理平台中形成体验版、审核版和线上版。小程序发布后与宿主应用关联,APP端使用小程序ID启动。运行时会结合本地缓存和平台上的版本信息加载代码包,有新版本时再按项目策略更新。

这样处理后,普通页面、组件和业务逻辑的调整可以通过小程序版本发布,宿主APP不用跟着每次变化重新提交应用商店。出现问题时,平台侧还可以回退版本或下架小程序,减少有问题代码继续分发的时间。

这条边界也不能说得过头。新增原生SDK、系统权限、隐私声明或宿主接口,依然需要修改APP并正常发版。小程序独立更新覆盖的是小程序代码包,无法代替宿主工程升级。上线验收时还应检查代码包完整性校验、缓存异常后的重新下载、旧版本兼容以及更新失败时的可用版本回退。

inline_02_workflow.pnginline_02_workflow.png

登录、支付和权限需要重新接好

页面迁移通常推进得比较快,登录更容易拖慢项目。原来的微信小程序可能使用OpenID或UnionID识别用户,自有APP使用的则是手机号、会员号或企业统一身份。微信里的会话不能直接带到企业APP里,需要建立账号映射,或者由宿主APP提供短时登录凭据,再由业务后台换取小程序会话。

这里建议只传短时、限用途的凭据,不要把APP的长期登录令牌直接暴露给小程序。业务后台还要校验这个凭据来自哪个宿主、准备访问哪个业务,并为失效、重复交换和账号不一致预留处理方式。

支付也要按APP现有体系重新接通。商品、订单确认和结果页面可以继续由小程序承载,支付动作交给宿主APP或企业支付服务执行。小程序收到端上回调后,还应向服务端查询订单状态。用户中途切后台、关闭页面或遇到回调延迟时,页面结果才不会和真实订单状态对不上。

定位、相机、相册、麦克风和文件访问,同时受操作系统权限、APP隐私声明和小程序授权策略约束。宿主APP需要知道是哪一个小程序发起调用,判断它是否有权使用该能力,并处理允许、拒绝和设备不支持等结果。以后如果还要接入第三方小程序,这层权限控制会比单个页面能否运行更值得提前设计。

先用一个业务把整条链路跑通

项目里没必要一开始就迁移全部小程序。挑一个页面数量适中、交易风险较低、微信专属能力较少的业务,通常更容易把问题暴露完整。先做兼容性检查,核对API、组件、插件和分包,再上传体验版本进行真机测试。

页面打开以后,不要马上把“能运行”当成接入完成。登录续期、网络异常、路由返回、前后台切换、文件上传、权限拒绝、弱网恢复和APP版本兼容,都需要实际走一遍。APP团队还要验证宿主应用标识、SDK初始化、小程序关联和启动参数,确保线上配置与测试环境没有混用。

正式发布前,至少演练一次版本回退和小程序下架。确认问题版本停止分发后,已经缓存过代码包的设备会怎样处理;小程序启动失败时,用户能否回到APP;业务入口是否需要临时关闭。这些情况在测试阶段处理,成本远低于上线后临时补救。

第一个业务稳定后,再把登录凭据、启动路由、错误页、权限申请和日志字段整理成宿主公共能力。迁入第二个小程序时,团队只处理新业务的差异,运行时和管理平台的基础链路可以继续沿用。

如果现有小程序以标准页面、组件和业务接口为主,希望同时保留微信入口与自有APP入口,小程序容器通常比重写一套原生页面更容易控制投入。若项目深度依赖微信云开发、插件、账号和渠道能力,就要先完成兼容评估,再决定迁移范围。能不能运行只是起点,已有代码能保留多少、宿主愿意开放哪些能力、版本由谁管理,才是这类项目做选型时需要回答的问题。

相关文章
|
3月前
|
存储 小程序 安全
如何为APP构建一个安全可控的沙箱运行环境,让第三方合作伙伴的小程序能够安全可控的运行在自己的APP里
如何为自己的APP引入一个安全可控的沙箱运行环境,沙箱为每个小程序创建一个独立的运行环境,实现第三方服务商通过小程序接入宿主APP,代码在自己可控的沙箱内运行,宿主APP通过管控后台掌握最终的决定权。
276 2
如何为APP构建一个安全可控的沙箱运行环境,让第三方合作伙伴的小程序能够安全可控的运行在自己的APP里
|
3月前
|
人工智能 移动开发 小程序
AI Coding如何落地APP开发——从个人玩具到公司级降本增效
AI Coding 提升了代码生产的效率,但代码生成之后谁来管、怎么跑、出了问题怎么修,如何应用到存量APP的生产环境中去,才是企业真正要面对的问题。作为APP运营团队,如何将AI能力应用到日常APP的更新迭代中去,分享一下基于“AI Coding + 小程序容器”的APP开发路径~
375 4
|
云栖大会 开发者
【用户权益中心】社区用户权益领取说明
【用户权益中心】社区用户权益领取说明
3665 4
|
2月前
|
人工智能 API 开发者
阿里云发布为Agent而生的全新AI产品官网“千问云”,模型服务全面Skill、CLI化
5月20日,阿里云发布“千问云”(www.qianwenai.com)——专为Agent时代打造的AI模型服务平台,集成150+主流模型API,首创Skills与CLI工具链,支持模型选型、调用、用量管理等全链路自动化,助力开发者与Agent高效构建AI应用。
2121 32
|
4月前
|
人工智能 监控 Kubernetes
LoongCollector + ACS Agent Sandbox:构建 AI Agent 生产级运行平台
文章介绍了阿里云ACSAgentSandbox与LoongCollector协同构建的AIAgent生产级运行平台,通过沙箱隔离保障运行时安全,并以高性能、全链路可观测能力解决Agent行为不可预测和执行风险难题。
2023 72
|
机器学习/深度学习 人工智能 API
大模型推理服务全景图
国内大模型推理需求激增,性能提升的主战场将从训练转移到推理。
3722 142
|
4月前
|
人工智能 安全 API
深度解析 Claude Code 在 Prompt / Context / Harness 的设计与实践
文章内容基于作者个人技术实践与独立思考,旨在分享经验,仅代表个人观点。
3898 75
深度解析 Claude Code 在 Prompt / Context / Harness 的设计与实践