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 - 线上环境直接填写你的后端公网接口地址
- 本地开发阶段,需要用工具(如ngrok)将本地后端服务暴露到公网,例如执行
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
相关产品推荐
相关产品推荐

