PAYATHON 2026

Uber API integration 中的乘车付款流程如何实现?

支付小周

结论

通常情况下,第三方应用不能先代收乘车费,再自行与 Uber 结算。

在标准的 Uber API integration 中,第三方应用主要提供叫车入口,处理用户授权,展示车型和价格信息,并同步订单状态。实际乘车费用仍由 Uber 按照其支付规则,直接从乘客绑定的支付方式中收取。第三方应用既拿不到乘客的银行卡信息,也不能仅通过公开 API 把自己设为行程收款方。

如果企业希望统一付费、赞助用户行程或采用月结,可以申请 Uber for Business、Vouchers、Guest Rides 等企业产品,同时向 Uber 确认所在国家或地区是否支持。这些产品用于解决企业付款问题,不等于允许第三方先代收乘车费,再转给 Uber。

标准付款流程

一般的付款流程如下:

  1. 用户在第三方应用中选择叫车。
  2. 应用通过 Uber 提供的授权方式取得用户许可,或者跳转到 Uber 应用,让用户继续操作。
  3. 应用获取可用车型、预计到达时间和预估价格。
  4. 用户确认行程,并选择 Uber 账户中可用的付款方式。
  5. Uber 创建行程,负责匹配司机、计价和履约。
  6. 行程结束后,Uber 根据最终里程、时长、附加费、取消费等计算实际费用。
  7. Uber 从乘客在 Uber 体系内选择的支付方式中扣款。
  8. Uber 向乘客提供收据。第三方应用只能在授权范围内读取行程状态或费用结果。

预估价格不属于支付授权,也不表示第三方应用可以按这个金额扣款。路线、等待时间、通行费、动态定价或取消规则都可能影响最终费用。

第三方应用应该如何接入

不同地区、合作级别和产品类型所开放的能力并不一致。部分开发者只能使用深度链接或跳转方式。完整的应用内叫车能力通常还需要额外审核或商业合作。

可以按以下顺序设计接入方案:

1. 确定可用的接入模式

如果没有取得完整的行程创建权限,可以使用 Uber 官方支持的 deep link 或 universal link,把上车点、目的地等信息传给 Uber 应用。订单和付款方式仍由用户在 Uber 界面中确认。

示意代码如下:

const pickup = {
  latitude: 31.2304,
  longitude: 121.4737,
  nickname: "人民广场"
};

const dropoff = {
  latitude: 31.2153,
  longitude: 121.4543,
  nickname: "目的地"
};

const params = new URLSearchParams({
  action: "setPickup",
  "pickup[latitude]": String(pickup.latitude),
  "pickup[longitude]": String(pickup.longitude),
  "pickup[nickname]": pickup.nickname,
  "dropoff[latitude]": String(dropoff.latitude),
  "dropoff[longitude]": String(dropoff.longitude),
  "dropoff[nickname]": dropoff.nickname
});

const uberUrl = `https://m.uber.com/ul/?${params.toString()}`;
window.location.href = uberUrl;

链接参数和支持范围可能发生调整。生产环境应以接入时的 Uber 官方文档为准。

2. 将敏感操作放在服务端

如果已经取得受限的行程 API 权限,应在服务端保存客户端凭据、刷新访问令牌并调用 Uber API。不要将 client_secret 或服务端访问令牌放在网页、桌面端或移动应用中。

下面是一个不绑定具体 API 版本的服务端结构示例:

app.post("/api/rides", requireLogin, async (req, res) => {
  const { pickup, dropoff, productId, paymentMethodId } = req.body;

  const accessToken = await getValidUberAccessToken(req.user.id);

  const ride = await uberClient.createRide({
    accessToken,
    pickup,
    dropoff,
    productId,
    paymentMethodId
  });

  res.json({
    rideId: ride.id,
    status: ride.status
  });
});

这里的 uberClient.createRide 只是根据实际获批产品封装调用的示例,并非可以直接使用的官方固定方法。真实的 endpoint、字段名称、OAuth scope 和付款字段必须以当前获批的 API 文档为准,不能从旧版示例中直接推断。

3. 通过 webhook 同步状态

订单创建后,如果开放能力允许,第三方应用可以接收司机已接受、司机到达、行程开始、行程结束或订单取消等状态变化。

app.post("/webhooks/uber", verifyWebhookSignature, async (req, res) => {
  const event = req.body;

  await updateRideStatus({
    externalRideId: event.resource_id,
    status: event.event_type,
    payload: event
  });

  res.sendStatus(200);
});

实际开发时,需要验证 webhook 签名,并根据事件 ID 做幂等处理,以免重复通知造成状态重复更新。

为什么不适合自行代收乘车费

如果第三方先收款,再把钱转给 Uber,会带来一系列额外问题:

  • 第三方可能会成为支付交易中的商户或资金处理方。
  • 第三方需要处理支付牌照、反洗钱、退款、拒付、税务和发票责任。
  • 预估车费和最终车费可能不同,不能简单按照下单金额结算。
  • Uber 未必向普通开发者提供订单应付账款或分账接口。
  • 用户的 Uber 账户中可能已有优惠券、企业付款方式或地区特定支付方式,第三方收款可能与这些方式冲突。
  • 如果第三方已经扣款,但叫车失败,还要负责退款和对账。
  • 自行保存或处理银行卡信息还会带来 PCI DSS 合规要求。

除非已经与 Uber 签订明确的商业协议,并取得相应的接口权限,否则不要将乘车费接入自己的支付网关,也不要通过抓取或模拟客户端请求等方式绕过 Uber 的付款流程。

可行的替代方案

企业赞助或统一结算

如果需求是由用户叫车、企业承担费用,可以评估 Uber for Business、Vouchers 或 Guest Rides。产品是否可用、由谁付款、如何控制额度以及采用什么结算方式,取决于当地支持情况和企业账户资格,需要向 Uber 商务团队确认。

在这种模式下,通常由企业直接与 Uber 结算,而不是第三方应用先向乘客收款,再把钱转给 Uber。

单独收取平台服务费

第三方可以为自身提供的独立服务收取服务费,但需要满足以下条件:

  • 服务费必须对应第三方实际提供的独立服务。
  • 页面应明确区分“第三方服务费”和“Uber 乘车费”。
  • 不能把预估车费包装成由第三方销售的乘车产品。
  • 应提前确认 Uber 开发者协议、当地消费者保护规则和支付法规是否允许这种收费方式。
  • 第三方服务应单独提供订单、退款说明和发票或收据。

即使第三方可以收取独立服务费,也不代表它可以代收 Uber 车费。

预充值或钱包模式

如果计划让用户先向应用钱包充值,再用余额支付 Uber 行程,需要格外谨慎。储值余额、代付和资金转移在许多地区可能受到金融监管,而且标准 Uber API 通常不提供从第三方钱包直接结算乘车费的通道。在没有 Uber 书面合作方案和合规评估的情况下,不应采用这种设计。

实施时的注意事项

  • 先确认开发者账户实际取得了哪些 API、OAuth scope 和地区权限。
  • 能够展示报价,不代表能够创建订单或处理付款。
  • 不要在客户端保存 client_secret、长期访问令牌或 webhook 密钥。
  • 对 webhook 进行签名验证、重放防护和幂等处理。
  • 明确标注预估价格,不要承诺最终扣款金额。
  • 为叫车失败、司机取消、乘客取消和行程费用调整设计相应界面。
  • 不要直接照搬多年前的 Ride Requests API 示例。接口开放范围和商业要求可能已经变化。
  • 上线前,应向 Uber 确认品牌展示、用户授权、数据保存和支付说明是否符合其平台政策。

普通第三方接入通常只承担叫车入口和行程信息界面的功能,不应成为乘车费的收款方。企业需要代付或统一结算时,应申请 Uber 对应的企业产品。如果确实需要由第三方代收并分账,则必须取得专门的商业合作和合规支持,公开 API 通常无法单独实现这种模式。

备注:内容仅供参考。