PAYATHON 2026

Flutter 移动应用如何接入 Sham Cash 官方 API 或 SDK?

技术老齐

结论

现有资料无法证明 Sham Cash 提供面向第三方应用的公开 API、Flutter SDK、商户接入文档,也无法确认是否有可直接使用的 redirect flow、deep link 或 partner API。

目前不宜直接把 Sham Cash 作为已有公开接口的支付渠道进行开发。官网没有公开文档,不代表内部一定没有合作伙伴接口;即使有,也通常需要通过 Sham Cash 官方审核,并取得协议、凭据和技术文档。在拿到这些材料前,不要猜测接口地址、参数或回调格式。

建议的接入流程

先通过 Sham Cash 官方客服或商务渠道申请商户合作,并确认:

  • 是否接受第三方移动应用或互联网商户接入。
  • 是否提供 merchant API、partner API、托管收银台或支付链接。
  • 是否支持测试环境、测试账户和测试币种。
  • 是否有 Android、iOS、Flutter 或通用 REST API 文档。
  • 是否支持 redirect URL、return URL 和 webhook。
  • 是否提供请求签名、回调验签和订单查询机制。
  • 是否允许通过 deep link 唤起 Sham Cash 客户端。
  • 商户审核、结算、退款和争议处理有哪些规则。

如果官方确认暂不支持第三方集成,Flutter 端也没有可靠的技术手段绕过这一限制。可以暂时隐藏该支付方式,或者使用官方提供的线下收款流程,但不能把线下流程包装成未经授权的自动支付接口。

官方可能提供的接入形式

如果 Sham Cash 后续开放合作,接入方式可能包括以下几类,具体以正式文档和合同为准。

原生 SDK

如果官方分别提供 Android 和 iOS SDK,Flutter 可以通过 platform channel 调用原生能力。具体实现要等拿到 SDK、初始化参数和回调说明后才能确定。

import 'package:flutter/services.dart';

class ShamCashBridge {
  static const MethodChannel _channel =
      MethodChannel('example.app/sham_cash');

  Future<Map<String, dynamic>> startPayment({
    required String merchantOrderId,
    required String paymentToken,
  }) async {
    final result = await _channel.invokeMapMethod<String, dynamic>(
      'startPayment',
      {
        'merchantOrderId': merchantOrderId,
        'paymentToken': paymentToken,
      },
    );

    if (result == null) {
      throw StateError('Payment SDK returned no result');
    }

    return result;
  }
}

这段代码只展示 Flutter 与原生 SDK 之间的桥接结构,并不表示 Sham Cash 已经提供对应的方法或参数。实际的 channel 名称、方法名和字段都要按照官方 SDK 调整。

托管收银台或 redirect flow

如果官方接口会返回托管支付页面的地址,可以由自己的服务端创建支付会话,再让 Flutter 打开该页面。

import 'package:url_launcher/url_launcher.dart';

Future<void> openCheckout(String checkoutUrl) async {
  final uri = Uri.parse(checkoutUrl);

  if (uri.scheme != 'https') {
    throw ArgumentError('Checkout URL must use HTTPS');
  }

  final opened = await launchUrl(
    uri,
    mode: LaunchMode.externalApplication,
  );

  if (!opened) {
    throw StateError('Unable to open checkout page');
  }
}

checkoutUrl 应由应用后端通过官方接口获取。客户端不应自行拼接未经文档确认的 Sham Cash URL,也不能只凭浏览器跳转结果将订单标记为支付成功。

只有官方公布 URI scheme、Universal Link 或 Android App Link 格式后,才能采用这种方式。自行猜测 shamcash://pay 一类地址并不可靠,也可能违反平台或服务条款。

即使支付客户端能通过 deep link 返回应用,返回结果通常也只能用于更新界面。最终支付状态仍要由后端查询,或者通过验签后的 webhook 确认。

Partner API

私有 partner API 通常没有公开注册入口。商户完成商务签约或技术审核后,才可能取得:

  • 接口文档和测试环境;
  • merchant ID、API key 或证书;
  • 请求签名及回调验签规则;
  • IP 白名单或证书要求;
  • 退款、撤销和订单查询接口;
  • 上线检查要求与生产环境凭据。

没有正式凭据时,即使发现疑似接口,也不应通过抓包或逆向消费者客户端来调用。

Flutter 项目如何预留支付接口

等待官方答复期间,可以先将业务层和具体支付渠道分开,避免把尚未确认的字段写死在页面里。

abstract interface class PaymentGateway {
  Future<PaymentStartResult> startPayment({
    required String orderId,
  });
}

class PaymentStartResult {
  const PaymentStartResult({
    required this.checkoutUri,
  });

  final Uri checkoutUri;
}

class ShamCashGateway implements PaymentGateway {
  ShamCashGateway(this.backend);

  final PaymentBackend backend;

  @override
  Future<PaymentStartResult> startPayment({
    required String orderId,
  }) async {
    // 此处调用的是应用自己的后端,不是未经确认的 Sham Cash API。
    final checkoutUrl = await backend.createShamCashSession(orderId);

    return PaymentStartResult(
      checkoutUri: Uri.parse(checkoutUrl),
    );
  }
}

abstract interface class PaymentBackend {
  Future<String> createShamCashSession(String orderId);
}

如果官方最终提供 SDK,可以替换 ShamCashGateway 的实现。如果提供托管收银台,则由后端创建会话并返回支付地址,无需整体重写业务页面。

服务端负责的工作

支付密钥、签名私钥和商户凭据不应放入 Flutter 安装包。移动端代码可以被反编译,编译时写入的所谓“隐藏密钥”仍有可能被提取。

正式接入后,服务端至少要负责:

  1. 根据内部订单创建支付请求。
  2. 保存第三方交易号与商户订单号的对应关系。
  3. 验证 webhook 的签名、时间戳和金额。
  4. 使用幂等机制处理重复通知。
  5. 必要时调用官方订单查询接口复核状态。
  6. 服务端确认到账后,再将订单更新为已支付。

不能只凭客户端收到的 success、返回页面参数或截图确认到账。

接入前需要确认的细节

拿到接口文档后,需要检查金额单位、币种、订单号长度、超时时间、退款能力和回调重试策略。金额究竟使用小数还是最小货币单位尤其要确认,否则可能出现数量级错误。

安全要求也要逐项核对:

  • API 是否强制使用 HTTPS。
  • 请求签名包含哪些字段。
  • webhook 是否提供证书、签名或来源校验。
  • 同一订单能否重复发起支付。
  • 回调结果与主动查询结果冲突时,以哪个为准。
  • 用户取消、处理中、超时和失败分别如何表示。

这些规则不能照搬其他支付平台,必须以 Sham Cash 的正式说明为准。

不建议采用的做法

缺少官方接入方案时,不要:

  • 抓取或调用 Sham Cash 消费者应用的内部接口;
  • 模拟登录、短信验证码或用户操作;
  • 猜测 deep link、接口路径和签名算法;
  • 把账号密码、API key 或私钥写入 Flutter 代码;
  • 根据网页 DOM、截图或客户端跳转判断支付成功;
  • 使用来源不明的第三方“Sham Cash SDK”。

这些方案容易失效,也会增加账户安全、资金对账和合规风险。

如果 Sham Cash 官方无法提供商户接入文档或书面确认,Flutter 应用目前就无法进行受官方支持的自动化支付集成。取得官方技术资料后,再根据其提供的 SDK、托管收银台或 partner API 选择接入方案。

备注:内容仅供参考。