PAYATHON 2026

支付宝小程序是否支持航班飞行模式下的离线购物与支付?

支付小周

结论

支付宝小程序可以通过定制开发实现这样的流程:起飞前联网进入商城,飞行期间离线浏览商品并暂存订单。但在完全断网的情况下,无法完成支付宝支付。

可行的流程是:

  • 起飞前联网加载小程序、商品数据和必要图片。
  • 飞行期间从本地缓存读取商品信息。
  • 由乘务员协助创建离线订单草稿。
  • 网络恢复后重新校验价格、库存和商品状态,再提交正式订单并发起支付。

如果要求旅客在飞行模式下直接完成扣款,并立即得到支付宝支付成功的结果,仅靠支付宝小程序无法实现。支付过程需要连接支付宝服务端和商户服务端。离线时无法创建、确认或查询有效的支付交易。

原因说明

小程序资源不等于业务数据自动离线

旅客联网打开小程序后,设备可能已经下载了部分小程序代码和静态资源,但商品列表、库存、价格、优惠资格和图片通常仍来自服务端。

因此,打开过小程序不代表商城断网后就能使用。开发方需要主动做好以下工作:

  • 提前下载允许离线销售的商品快照。
  • 将必要数据写入本地缓存。
  • 确保关键图片等资源在断网前已经加载,或者直接打包进小程序资源包。
  • 为离线页面单独设计数据读取和异常处理逻辑。

如果商城通过 web-view 加载 H5 页面,离线表现更难控制,不适合依赖浏览器缓存开展正式业务。

支付必须联网完成

支付宝支付涉及交易创建、身份验证、风控、扣款和支付结果确认。调用支付能力前,需要先取得服务端创建的交易信息,并连接支付宝服务。

以下调用只能在网络可用,并且已经取得有效 tradeNO 时执行:

my.tradePay({
  tradeNO,
  success(result) {
    console.log('支付调用完成', result);
  },
  fail(error) {
    console.error('支付失败', error);
  }
});

离线时不能在本地预先生成一个”支付成功”结果,也不能把离线订单草稿当作已付款订单。商户服务端还需要确认最终支付结果,不能只依赖客户端回调。

推荐实现流程

1. 起飞前同步离线商品快照

联网时,从服务端获取本航班允许销售的商品、展示价格、图片地址和快照版本,并保存到本地。

function downloadOfflineCatalog(flightId) {
  return new Promise((resolve, reject) => {
    my.request({
      url: 'https://example.com/api/offline-catalog',
      method: 'GET',
      data: { flightId },
      success(res) {
        const catalog = {
          flightId,
          version: res.data.version,
          expiresAt: res.data.expiresAt,
          products: res.data.products
        };

        my.setStorageSync({
          key: `offline_catalog_${flightId}`,
          data: catalog
        });

        resolve(catalog);
      },
      fail: reject
    });
  });
}

接口地址、字段和鉴权方式需要由业务系统自行定义。商品快照中不应保存支付凭证、密钥等敏感信息。

2. 飞行期间读取本地商品

断网后读取已经缓存的商品数据,并在页面上清楚显示数据更新时间和离线状态。

function getOfflineCatalog(flightId) {
  const result = my.getStorageSync({
    key: `offline_catalog_${flightId}`
  });

  const catalog = result && result.data;

  if (!catalog || catalog.flightId !== flightId) {
    throw new Error('未找到当前航班的离线商品数据');
  }

  if (catalog.expiresAt && Date.now() > catalog.expiresAt) {
    throw new Error('离线商品数据已过期');
  }

  return catalog;
}

不能假设所有商品图片在离线时仍能显示。关键图片应提前下载或随小程序资源一起发布,同时还要评估小程序包体和本地存储限制。

3. 离线保存订单草稿

飞行期间只能创建状态为”待同步”的本地订单。订单中应包含客户端生成的幂等标识,以免恢复网络后重复提交。

function createOfflineOrderDraft({ flightId, items, operatorId }) {
  const draft = {
    clientOrderId: `${flightId}_${Date.now()}_${Math.random()
      .toString(16)
      .slice(2)}`,
    flightId,
    items,
    operatorId,
    createdAt: Date.now(),
    status: 'PENDING_SYNC'
  };

  const result = my.getStorageSync({
    key: 'offline_order_drafts'
  });

  const drafts = Array.isArray(result.data) ? result.data : [];
  drafts.push(draft);

  my.setStorageSync({
    key: 'offline_order_drafts',
    data: drafts
  });

  return draft;
}

Math.random() 在示例中仅用于拼接客户端标识,不适合生成安全令牌或支付凭证。生产环境应使用可靠的唯一标识方案,并由服务端通过幂等机制防止重复下单。

4. 联网后同步并重新确认

网络恢复后,将订单草稿提交给服务端。服务端必须重新检查:

  • 商品是否仍然可售。
  • 实际库存是否充足。
  • 商品价格是否发生变化。
  • 优惠和会员权益是否仍然有效。
  • 同一个 clientOrderId 是否已经处理。
  • 订单是否属于对应的航班和操作人员。
function submitDraft(draft) {
  return new Promise((resolve, reject) => {
    my.request({
      url: 'https://example.com/api/orders/sync',
      method: 'POST',
      data: draft,
      success(res) {
        if (!res.data || !res.data.tradeNO) {
          reject(new Error('订单已同步,但暂时无法发起支付'));
          return;
        }

        resolve(res.data);
      },
      fail: reject
    });
  });
}

订单同步成功后,再使用服务端返回的有效 tradeNO 调用 my.tradePay。如果价格或库存有变化,应先让旅客重新确认,不能直接按照离线快照扣款。

可选的业务方案

如果航空公司需要在飞行期间交付商品,可以采用”离线记账、联网后支付”的流程,但这不等于离线支付宝支付。是否允许先交付商品,需要航空公司自行评估坏账、退款、旅客身份核验和争议处理风险。

也可以在机上提供能够访问互联网的 Wi-Fi。只要旅客设备可以正常连接商户服务端和支付宝服务,支付就能按在线交易处理。如果只能连接机舱局域网,无法访问互联网,通常仍然不能完成支付宝支付。

注意事项

  • “离线商城”是商户自行设计的离线业务能力,不能理解为支付宝提供了离线支付接口。
  • 首次进入小程序、登录授权和更新小程序版本通常需要联网,必须在起飞前完成。
  • 本地缓存可能被系统清理,不能作为唯一的订单存储方式。乘务员终端可以增加独立的订单留存和人工核对机制。
  • 离线期间无法实时锁定中心库存,可能发生超卖,需要设置航班配额或机上独立库存。
  • 订单草稿页面应明确标注”未提交”和”未支付”,避免旅客误以为已经付款。
  • 支付状态、金额和库存结果不能由客户端自行判定,最终状态应以服务端校验结果为准。
  • 存储旅客身份、手机号和订单信息时,应限制本地存储范围,并设计过期清理、加密和终端遗失处理方案。
  • my.getStorageSync、my.setStorageSync、my.request 和 my.tradePay 的具体可用条件,应以目标支付宝小程序运行环境及当前官方文档为准,并在真机飞行模式下完成测试。

备注:内容仅供参考。