Uber API integration 中的乘车付款流程如何实现?
结论
通常情况下,第三方应用不能先代收乘车费,再自行与 Uber 结算。
在标准的 Uber API integration 中,第三方应用主要提供叫车入口,处理用户授权,展示车型和价格信息,并同步订单状态。实际乘车费用仍由 Uber 按照其支付规则,直接从乘客绑定的支付方式中收取。第三方应用既拿不到乘客的银行卡信息,也不能仅通过公开 API 把自己设为行程收款方。
如果企业希望统一付费、赞助用户行程或采用月结,可以申请 Uber for Business、Vouchers、Guest Rides 等企业产品,同时向 Uber 确认所在国家或地区是否支持。这些产品用于解决企业付款问题,不等于允许第三方先代收乘车费,再转给 Uber。
标准付款流程
一般的付款流程如下:
- 用户在第三方应用中选择叫车。
- 应用通过 Uber 提供的授权方式取得用户许可,或者跳转到 Uber 应用,让用户继续操作。
- 应用获取可用车型、预计到达时间和预估价格。
- 用户确认行程,并选择 Uber 账户中可用的付款方式。
- Uber 创建行程,负责匹配司机、计价和履约。
- 行程结束后,Uber 根据最终里程、时长、附加费、取消费等计算实际费用。
- Uber 从乘客在 Uber 体系内选择的支付方式中扣款。
- 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 通常无法单独实现这种模式。
备注:内容仅供参考。
