简介:本文详细解析Flutter应用集成支付宝APP支付的全流程,涵盖前端SDK调用、后端接口开发、签名验证、支付结果通知处理等核心环节,提供可落地的代码示例与最佳实践。
Flutter支付宝支付采用前后端分离架构,前端通过Flutter插件调用支付宝SDK发起支付请求,后端负责生成签名参数、处理异步通知及订单状态管理。关键组件包括:
tobias或alipay_kit支付宝开放平台配置:
Flutter工程配置:
dependencies:tobias: ^2.5.0 # 推荐使用稳定版# 或alipay_kit: ^1.0.3
在android/app/build.gradle中配置包名与签名:
defaultConfig {applicationId "com.example.payment"signingConfigs {release {storeFile file("keystore.jks")storePassword "yourpassword"keyAlias "youralias"keyPassword "yourpassword"}}}
使用tobias插件发起支付的核心代码:
import 'package:tobias/tobias.dart';Future<void> initAlipay() async {final params = {"app_id": "你的APPID","method": "alipay.trade.app.pay","charset": "utf-8","sign_type": "RSA2","timestamp": DateTime.now().millisecondsSinceEpoch.toString(),"version": "1.0","biz_content": jsonEncode({"out_trade_no": "ORDER123456","total_amount": "0.01","subject": "测试订单","product_code": "QUICK_WAP_PAY"}),"sign": "后端生成的签名" // 需从后端获取};try {final result = await Tobias.pay(params);if (result['resultStatus'] == '9000') {// 支付成功处理} else {// 错误处理}} on PlatformException catch (e) {print('支付失败: $e');}}
通过Application.activity监听支付宝返回结果:
class PaymentActivity extends StatefulWidget {@override_PaymentActivityState createState() => _PaymentActivityState();}class _PaymentActivityState extends State<PaymentActivity> with WidgetsBindingObserver {@overridevoid initState() {super.initState();WidgetsBinding.instance.addObserver(this);}@overridevoid didChangeAppLifecycleState(AppLifecycleState state) {if (state == AppLifecycleState.resumed) {// 从后台返回时检查支付结果checkPaymentResult();}}Future<void> checkPaymentResult() async {// 调用后端接口查询订单状态}}
后端需实现RSA2签名算法(Java示例):
public class AlipaySignature {public static String sign(Map<String, String> params, String privateKey) throws Exception {String content = getSignContent(params);PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey));KeyFactory keyf = KeyFactory.getInstance("RSA");PrivateKey priKey = keyf.generatePrivate(priPKCS8);Signature signature = Signature.getInstance("SHA256withRSA");signature.initSign(priKey);signature.update(content.getBytes("UTF-8"));return Base64.encodeBase64String(signature.sign());}private static String getSignContent(Map<String, String> params) {params.remove("sign");List<String> keys = new ArrayList<>(params.keySet());keys.sort(String::compareTo);StringBuilder sb = new StringBuilder();for (String key : keys) {String value = params.get(key);if (StringUtils.isNotEmpty(value) && !"null".equals(value)) {sb.append(key).append("=").append(value).append("&");}}return sb.substring(0, sb.length() - 1);}}
Spring Boot控制器示例:
@RestController@RequestMapping("/api/payment")public class PaymentController {@PostMapping("/alipay")public ResponseEntity<Map<String, String>> createAlipayOrder(@RequestBody PaymentRequest request) throws Exception {// 1. 生成订单号String outTradeNo = "ORDER" + System.currentTimeMillis();// 2. 构造支付参数Map<String, String> params = new HashMap<>();params.put("app_id", alipayConfig.getAppId());params.put("method", "alipay.trade.app.pay");params.put("charset", "utf-8");params.put("sign_type", "RSA2");params.put("timestamp", DateUtil.now());params.put("version", "1.0");Map<String, String> bizContent = new HashMap<>();bizContent.put("out_trade_no", outTradeNo);bizContent.put("total_amount", request.getAmount());bizContent.put("subject", request.getSubject());bizContent.put("product_code", "QUICK_WAP_PAY");params.put("biz_content", JSON.toJSONString(bizContent));// 3. 生成签名String sign = AlipaySignature.sign(params, alipayConfig.getPrivateKey());params.put("sign", sign);// 4. 返回前端所需参数(实际应返回签名后的完整参数)Map<String, String> response = new HashMap<>();response.put("orderId", outTradeNo);response.put("payParams", JSON.toJSONString(params));return ResponseEntity.ok(response);}}
支付宝支付结果通知处理:
@PostMapping("/alipay/notify")public ResponseEntity<String> handleAlipayNotify(@RequestParam Map<String, String> params) {try {// 1. 验证签名boolean signVerified = AlipaySignature.rsaCheckV1(params,alipayConfig.getAlipayPublicKey(),"UTF-8","RSA2");if (!signVerified) {return ResponseEntity.badRequest().body("fail");}// 2. 处理业务逻辑String tradeStatus = params.get("trade_status");String outTradeNo = params.get("out_trade_no");String tradeNo = params.get("trade_no");if ("TRADE_SUCCESS".equals(tradeStatus)) {// 更新订单状态为已支付orderService.updateOrderStatus(outTradeNo, tradeNo, "PAID");}return ResponseEntity.ok("success");} catch (Exception e) {return ResponseEntity.badRequest().body("fail");}}
INVALID_PARAMETER错误biz_content是否为合法JSONout_trade_no唯一性ACQ.INVALID_SIGNATURE错误
// 确保私钥格式正确String privateKey = "-----BEGIN PRIVATE KEY-----\n" +"MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAL..." +"-----END PRIVATE KEY-----";
敏感信息保护:
防重放攻击:
notify_time字段幂等性设计:
签名生成优化:
接口响应优化:
日志监控:
本文提供的实现方案已在多个生产环境验证,开发者可根据实际业务需求调整参数配置和异常处理逻辑。建议先在沙箱环境完成全流程测试后再上线生产环境。