You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter集成Chargily ePay API:支付确认(Webhook)实现求助

实现Chargily ePay支付确认(Webhook)方案

Chargily ePay的支付确认依赖Webhook机制,核心是后端接收Chargily推送的支付状态变更通知,再同步到Flutter客户端。以下是具体实现步骤:

1. 配置Webhook基础信息

  • 先在Chargily开发者后台设置你的Webhook URL:
    • 本地开发阶段,需要用工具(如ngrok)将本地后端服务暴露到公网,例如执行ngrok http 8080生成临时公网地址,格式类似https://xxxx.ngrok.io/chargily-webhook
    • 线上环境直接填写你的后端公网接口地址

2. 后端实现Webhook接收与验证

Flutter客户端无法直接作为Webhook接收端(无公网IP),必须搭建后端服务处理请求。以下是Dart后端(基于shelf框架)的示例:

import 'package:shelf/shelf.dart';
import 'package:shelf/shelf_io.dart' as shelf_io;
import 'package:shelf_router/shelf_router.dart';
import 'dart:convert';
import 'dart:crypto';

void main() async {
  final router = Router();
  final apiKey = '你的Chargily API密钥'; // 和发起支付时使用的密钥一致

  router.post('/chargily-webhook', (Request request) async {
    // 步骤1:验证请求签名,防止伪造
    final receivedSignature = request.headers['X-Signature'];
    final requestBody = await request.readAsString();

    // 计算签名:使用API密钥对请求体做HMAC SHA256加密,再转Base64
    final hmac = Hmac(sha256, utf8.encode(apiKey));
    final computedSignature = base64Encode(hmac.convert(utf8.encode(requestBody)).bytes);

    if (receivedSignature != computedSignature) {
      return Response.forbidden('无效签名');
    }

    // 步骤2:解析支付状态数据
    final invoiceData = jsonDecode(requestBody);
    final invoiceId = invoiceData['id'];
    final paymentStatus = invoiceData['status']; // 可选值:paid/failed/canceled
    final amount = invoiceData['amount'];

    // 步骤3:执行业务逻辑(更新本地订单状态等)
    // updateOrder(invoiceId, paymentStatus, amount);

    // 返回200状态码告知Chargily已接收
    return Response.ok('Webhook已处理');
  });

  final handler = Pipeline().addMiddleware(logRequests()).addHandler(router);
  await shelf_io.serve(handler, '0.0.0.0', 8080);
  print('后端服务运行于 http://localhost:8080');
}

3. Flutter客户端同步支付状态

客户端无法直接接收Webhook,可通过两种方式同步状态:

方式1:轮询查询发票状态

定期调用Chargily API查询指定发票的状态:

import 'package:dio/dio.dart';
import 'dart:developer';

Future<void> pollInvoiceStatus(String invoiceId) async {
  const pollInterval = Duration(seconds: 5);
  final dio = Dio();
  final apiKey = '你的Chargily API密钥';

  while (true) {
    try {
      final response = await dio.get(
        'http://epay.chargily.com.dz/api/invoice/$invoiceId',
        options: Options(headers: {
          'X-Authorization': apiKey,
          'Accept': 'application/json',
        }),
      );

      final status = response.data['status'];
      if (status == 'paid' || status == 'failed' || status == 'canceled') {
        // 更新UI或本地订单状态
        // updatePaymentUI(status);
        break; // 状态确定后停止轮询
      }
    } catch (e) {
      log('查询发票状态失败: $e');
    }
    await Future.delayed(pollInterval);
  }
}

方式2:后端主动推送

后端收到Webhook后,通过WebSocket或推送服务(如Firebase Cloud Messaging)通知Flutter客户端,这种方式更高效,适合实时性要求高的场景。

关键注意事项

  • 必须验证Webhook签名:这是确保请求来自Chargily的核心,避免恶意篡改或伪造请求
  • Webhook端点必须返回200状态码:若返回非200,Chargily会多次重试推送
  • 本地开发用ngrok时,注意每次启动ngrok会生成新地址,需要同步更新Chargily后台的Webhook配置

内容的提问来源于stack exchange,提问作者anikki00

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 20:15:33