PAYATHON 2026

能否通过不绑定用户银行账户的移动应用进行非接触式支付?

支付阿杰

结论

技术上可以实现,用户也不必绑定个人银行账户。不过,移动应用不能直接把公司银行账户模拟成银行卡。

要在普通商户的非接触式 POS 机上付款,必须接入银行卡收单体系。通常由持牌发卡机构或发卡服务商发行虚拟卡,资金来自公司的预存资金、授信额度或结算账户。移动应用用于管理用户的消费权限,实际付款则由手机钱包或受支持的 NFC 支付机制完成。

如果支付范围仅限自有设备、自有门店或指定商户,也可以搭建闭环支付系统,不接入 Visa、Mastercard、银联等卡组织。相应的限制是,这套系统不能在普通银行卡 POS 机上使用。

为什么应用不能直接”像银行卡一样”付款

普通非接触式 POS 机不会调用应用提供的自定义付款接口。它只识别符合 EMV Contactless 等规范的支付凭证,并通过收单机构、卡组织和发卡机构完成授权。

一笔典型交易大致经过以下链路:

手机钱包或支付设备
        ↓ NFC
商户 POS
        ↓
收单机构
        ↓
卡组织
        ↓
发卡机构或发卡处理平台
        ↓
企业额度与风控系统

公司银行账户不是 POS 可以识别的支付凭证。即使 Android 支持 Host Card Emulation(HCE),普通应用也不能自行生成一个可以在银行卡网络中结算的有效卡号。银行卡支付还涉及:

  • 发卡资质或持牌合作机构
  • 卡组织接入和 BIN
  • EMV 支付凭证
  • 动态密码和密钥管理
  • 网络令牌化
  • 交易授权、清算与结算
  • PCI DSS 等安全要求
  • KYC、AML、资金托管及当地支付监管

因此,NFC 通信只是其中一层,主要门槛在于支付网络接入和合规发行。

可选实现方案

方案一:企业虚拟卡或员工卡

这通常是最适合该场景的方案。

企业可以与发卡机构或发卡平台合作,为每位用户生成独立的虚拟卡或支付令牌。用户不需要绑定个人银行账户,消费由企业资金承担。应用中的权限系统可以控制:

  • 单笔和每日限额
  • 总预算
  • 有效时间
  • 商户类别,即 MCC
  • 国家或地区
  • 线上、线下及非接触式交易权限
  • 指定项目或成本中心
  • 卡片冻结和注销

如果发行方支持 Apple Pay、Google Wallet 或当地手机钱包,可以把虚拟卡配置到手机钱包中,用于非接触式支付。应用通常负责开卡、额度管理和交易查询,不直接保存或模拟完整的银行卡凭证。

这种结构与企业费用卡相似,只是实体卡被虚拟卡或钱包令牌取代。

方案二:闭环 NFC 或二维码支付

如果支付范围只包括公司食堂、园区、自有门店或合作商户,可以不接入银行卡网络。

应用向自有终端提供账户标识、一次性令牌或签名后的付款请求。后台验证用户额度后,再从企业内部余额中记账。

移动应用 → 自有终端 → 企业支付后台 → 额度检查 → 内部记账

这种方案实现起来更简单,也便于精确控制消费权限,但普通银行卡 POS 机无法接受。商户需要安装专用应用、SDK 或终端设备。

在不少场景中,动态二维码比自定义 NFC 协议更容易部署,因为它不需要处理不同手机系统对 NFC 卡模拟的限制。

方案三:预付账户或电子钱包

平台可以为用户维护由企业充值的预付余额,用户再通过平台提供的卡片、二维码或钱包功能付款。

能否自行运营这类账户,取决于所在国家或地区的监管要求。如果涉及代收代付、储值、资金沉淀或向多个商户付款,通常需要支付牌照,或与持牌支付机构合作。

推荐的落地步骤

1. 明确受理范围

先确定支付凭证需要在哪些地方使用:

  • 需要在普通银行卡 POS 机上通用:选择持牌发卡机构和卡组织方案。
  • 只在自有或指定商户使用:可以搭建闭环支付系统。
  • 两种场景都需要:开放网络使用企业卡,同时保留自己的额度和风控后台。

2. 选择资金结构

用户不绑定银行账户,并不意味着支付系统不需要资金来源。常见结构包括:

  • 企业预先向发卡机构充值
  • 企业提供保证金
  • 发卡机构向企业提供授信
  • 每日从企业结算账户划款
  • 平台持有合规的备付金或托管账户

具体采用哪种结构,要由发卡机构、银行和当地监管要求共同决定。

3. 为用户分配独立支付凭证

不应让所有员工共用同一个卡号。通常需要为每位用户或每种用途生成独立虚拟卡,以便控制额度、追踪交易和撤销凭证。

支付凭证与用户之间可以采用以下关系:

user_id → spending_policy_id → virtual_card_id → issuer_account

用户获得的是企业主账户下受限的消费权限,并不拥有资金账户。

4. 在授权阶段检查消费权限

只在应用界面显示”剩余额度”并不够。用户可能绕过应用,直接使用已经加入手机钱包的卡,因此所有限制都必须由后端在交易授权时执行。

下面是一个简化的授权示例:

interface AuthorizationRequest {
  cardId: string;
  amount: number;
  currency: string;
  merchantId: string;
  merchantCategoryCode: string;
  country: string;
  occurredAt: string;
}

interface SpendingPolicy {
  enabled: boolean;
  currency: string;
  remainingAmount: number;
  maxTransactionAmount: number;
  allowedMcc: string[];
  allowedCountries: string[];
  validFrom: string;
  validUntil: string;
}

function authorize(
  request: AuthorizationRequest,
  policy: SpendingPolicy
): { approved: boolean; reason: string } {
  const now = new Date(request.occurredAt);

  if (!policy.enabled) {
    return { approved: false, reason: "CARD_DISABLED" };
  }

  if (request.currency !== policy.currency) {
    return { approved: false, reason: "CURRENCY_NOT_ALLOWED" };
  }

  if (request.amount > policy.maxTransactionAmount) {
    return { approved: false, reason: "TRANSACTION_LIMIT_EXCEEDED" };
  }

  if (request.amount > policy.remainingAmount) {
    return { approved: false, reason: "INSUFFICIENT_BUDGET" };
  }

  if (!policy.allowedMcc.includes(request.merchantCategoryCode)) {
    return { approved: false, reason: "MCC_NOT_ALLOWED" };
  }

  if (!policy.allowedCountries.includes(request.country)) {
    return { approved: false, reason: "COUNTRY_NOT_ALLOWED" };
  }

  if (now < new Date(policy.validFrom) || now > new Date(policy.validUntil)) {
    return { approved: false, reason: "OUTSIDE_VALIDITY_PERIOD" };
  }

  return { approved: true, reason: "APPROVED" };
}

实际系统还要处理余额预占、撤销、退款、小费调整、离线交易、重复通知和并发扣款。更新额度时应使用数据库事务或原子操作,不能简单地先查询再扣减。

例如:

UPDATE spending_accounts
SET available_amount = available_amount - :amount
WHERE account_id = :account_id
  AND available_amount >= :amount;

只有受影响行数为 1,才能确认额度预占成功。

5. 接入手机钱包

使用开放式银行卡网络时,钱包配置或令牌化能力通常由发卡机构提供。配置过程可能包括用户身份验证、设备绑定和支付令牌下发。

实际可用能力取决于发卡机构、卡组织、手机平台、地区和钱包政策。自行发行的虚拟卡未必能加入 Apple Pay 或 Google Wallet,选型时需要服务商明确确认:

  • 支持的国家和地区
  • 支持的卡组织
  • 是否支持将虚拟卡配置到钱包
  • 是否提供应用内配置流程
  • 授权回调的时限和可配置规则
  • NFC 交易是否支持实时额度控制

Android HCE 能解决什么

Android HCE 可以让应用响应 NFC 读卡器发送的 APDU,适用于门禁、会员卡或自建闭环协议。例如:

class CompanyPaymentService : HostApduService() {
    override fun processCommandApdu(
        commandApdu: ByteArray,
        extras: Bundle?
    ): ByteArray {
        val token = createShortLivedToken()
        return token.toByteArray(Charsets.UTF_8) +
            byteArrayOf(0x90.toByte(), 0x00.toByte())
    }

    override fun onDeactivated(reason: Int) {
        // 清理本次会话状态
    }

    private fun createShortLivedToken(): String {
        return "example-token"
    }
}

这段代码只能说明应用可以与兼容的自有 NFC 终端通信。它不会让普通银行卡 POS 接受该应用,也不能构成完整、安全的支付实现。生产系统还需要使用随机挑战、短期令牌、数字签名、防重放机制和安全的密钥存储。

iPhone 对后台 NFC、卡模拟和支付凭证的开放程度,还会受到系统能力、地区及 Apple 政策的限制,不能直接套用 Android HCE 的实现方式。产品落地前,需要根据目标地区和当时的平台文档单独确认相关能力。

关键注意事项

不要在应用中保存真实卡片密钥

支付密钥应由发卡机构、令牌服务提供商或经过认证的安全组件管理。应用和业务后台应尽量只接触支付令牌、内部卡片标识和脱敏信息。

应用额度与发卡侧额度必须一致

如果限制只保存在应用数据库中,而发卡机构在授权时不检查这些限制,用户仍可能通过手机钱包完成超额消费。额度规则必须进入实时授权链路,或同步为发卡平台原生的卡片控制规则。

并非所有交易都能实时联网

部分交通、小额、离线或延迟上送交易,可能无法在交易发生前调用业务后台。如果业务要求”绝对不能超额”,需要确认发行方能否禁用离线授权,并了解这样做会如何影响受理率。

预授权金额可能发生变化

酒店、租车、加油站和餐饮场景可能先预占一笔金额,之后再完成或调整。额度系统不能把所有授权请求都视为最终扣款,需要分别处理:

  • Authorization
  • Incremental authorization
  • Reversal
  • Clearing
  • Refund
  • Chargeback

尽早处理合规问题

只要系统涉及替用户持有资金、发行支付工具或向外部商户付款,就可能受到支付、反洗钱、数据保护和消费者权益法规的约束。通常更可行的方式是接入已有资质的银行或发卡服务商,并由合作方明确各方责任,而不是自行成为发卡机构。

最合适的架构

如果目标是”员工用手机在普通商户 POS 上付款,公司承担费用,并由应用控制额度”,建议采用以下架构:

企业资金账户
    ↓
持牌发卡机构或发卡平台
    ↓
每位用户的虚拟企业卡
    ↓
Apple Pay、Google Wallet 或当地手机钱包
    ↓
普通非接触式 POS

交易授权请求
    ↓
企业额度与风控后台
    ↓
批准或拒绝

这种方案不要求用户绑定个人银行账户,也能兼顾普通 POS 的受理范围和企业消费控制。如果只在封闭场景中使用,二维码或自定义 NFC 闭环系统的成本更低,控制起来也更直接。

备注:内容仅供参考。