xe_create_order_handler.dart 9.21 KB
import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:appframe/config/constant.dart';
import 'package:appframe/config/locator.dart';
import 'package:appframe/data/repositories/user_auth_repository.dart';
import 'package:appframe/services/dispatcher.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_localization/flutter_localization.dart';
import 'package:appframe/services/subscription_service_ios.dart';
import 'package:fluwx/fluwx.dart';

class XeCreateOrderHandler extends MessageHandler {
  late final Fluwx _fluwx;
  late final UserAuthRepository _userAuthRepository;
  late FluwxCancelable _fluwxCancelable;

  // 支付结果 Completer,用于将异步回调转为 await
  Completer<WeChatPaymentResponse>? _payCompleter;

  // 超时定时器
  Timer? _timeoutTimer;

  final SubscriptionService _subService = SubscriptionService();

  XeCreateOrderHandler() {
    _fluwx = getIt.get<Fluwx>();
    _userAuthRepository = getIt.get<UserAuthRepository>();
  }

  @override
  Future<dynamic> handleMessage(params) async {

    print("##############  handleMessage #############");
    // 从 params 中提取支付参数
    final String chargeCode = params['chargeCode'] as String? ?? '';
    final int durationType = params['durationType'] as int? ?? 0;
    final int duration = params['duration'] as int? ?? 0;
    final int totalFee = params['totalFee'] as int? ?? 0;
    final bool renew = params['renew'] as bool? ?? false;

    final String phone = params['phone'] as String? ?? '';
    final String userCode = params['userCode'] as String? ?? '';
    final String tbxStuId = params['tbxStuId'] as String? ?? '';
    final String stuId = params['stuId'] as String? ?? '';

    // ext 为 JSON 格式字符串
    final String ext = params['ext'] as String? ?? '{}';

    // 解析 ext
    final Map<String, dynamic> extMap = jsonDecode(ext);
    final useCoin = extMap['useCoin'] as bool? ?? false;

    debugPrint('PayHandler params: chargeCode=$chargeCode, durationType=$durationType, '
        'duration=$duration, totalFee=$totalFee, renew=$renew, '
        'phone=$phone, userCode=$userCode, tbxStuId=$tbxStuId, stuId=$stuId, '
        'ext=$ext');

    // 1. 请求后端获取预支付订单信息
    final deviceType = Platform.isIOS?"ios":"andorid";
    print("[debug]. handleMessage 1 "+deviceType);
    if (deviceType == 'andorid'){
       await _wx_pay_proc_(userCode, tbxStuId, chargeCode, deviceType, phone, stuId, ext, duration, durationType, totalFee, renew, useCoin);
    }else if (deviceType == 'ios'){
       // 暂时不支持使用学币扣减 
       await _ios_pay_proc_(userCode, tbxStuId, chargeCode, deviceType, phone, stuId, ext, duration, durationType, totalFee, renew, false);
    }

  }

  // 执行微信支付
  Future<dynamic> _wx_pay_proc_ (String userCode, tbxStuId, chargeCode,deviceType,phone,stuId,ext,int duration, durationType, totalFee,bool renew, useCoin) async{

    // 2. 检查微信是否安装
    if (!await _fluwx.isWeChatInstalled) {
      throw Exception('设备上未安装微信App,不支持微信支付');
    }

    var result = await _userAuthRepository.createOrder(userCode, tbxStuId, chargeCode, duration, durationType, totalFee,
        renew, phone, stuId, ext, useCoin ? 1 : 0, deviceType);
    if (result == null) {
      throw Exception('获取支付信息失败');
    }

    var data = result['data'] as Map<String, dynamic>?;
    if (data == null) {
      throw Exception('支付参数获取失败');
    }

    // 3. 从后端响应中提取预支付ID
    final prepayId = data['prepayId'] as String?;
    if (prepayId == null || prepayId.isEmpty) {
      throw Exception('预支付订单ID获取失败');
    }

    // 4. 从后端响应中提取支付参数(nonceStr、timestamp、paySign 由后端生成)
    final appId = Constant.wxAppId;
    final partnerId = Constant.wxPartnerId;
    final packageValue = 'Sign=WXPay';
    final nonceStr = data['nonceStr'] as String;
    final timestamp = data['timeStamp'] as int;
    final paySign = data['paySign'] as String;
    final wxTradeNo = data['wxTradeNo'] as String;

    debugPrint('_wx_pay_proc_ => prepayId: $prepayId');
    debugPrint('_wx_pay_proc_ => nonceStr: $nonceStr');
    debugPrint('_wx_pay_proc_ => timestamp: $timestamp');
    debugPrint('_wx_pay_proc_ => paySign: $paySign');
    debugPrint('_wx_pay_proc_ => appId: $appId');
    debugPrint('_wx_pay_proc_ => partnerId: $partnerId');
    debugPrint('_wx_pay_proc_ => packageValue: $packageValue');
    debugPrint('_wx_pay_proc_ => wxTradeNo: $wxTradeNo');

    if (nonceStr.isEmpty || paySign.isEmpty || wxTradeNo.isEmpty) {
      throw Exception('支付参数获取失败');
    }

    // 5. 注册支付结果监听器
    _payCompleter = Completer<WeChatPaymentResponse>();
    _fluwxCancelable = _fluwx.addSubscriber(_responseListener);

    // 6. 启动超时兜底(60秒 * 10)
    _timeoutTimer = Timer(const Duration(seconds: 600), () {
      if (_payCompleter != null && !_payCompleter!.isCompleted) {
        _payCompleter!.completeError(TimeoutException('支付超时'));
      }
    });

    // 7. 调用 fluwx.pay() 拉起微信支付
    final payResult = await _fluwx.pay(
      which: Payment(
        // 微信开放平台 AppID
        appId: appId,
        // 商户号(固定)
        partnerId: partnerId,
        // 预支付ID(后端返回)
        prepayId: prepayId,
        // 固定值 Sign=WXPay
        packageValue: packageValue,
        // 随机字符串(后端返回)
        nonceStr: nonceStr,
        // 时间戳(后端返回,秒级)
        timestamp: timestamp,
        // 签名(后端生成)
        sign: paySign,
      ),
    );

    if (!payResult) {
      _cleanup();
      throw Exception('拉起微信支付失败');
    }

    // 8. 等待支付结果回调
    try {
      final response = await _payCompleter!.future;

      if (response.isSuccessful) {
        debugPrint('wechat pay success: ${response.errStr}');
        return {"orderUnique": wxTradeNo, "orderState": 1};
      } else if (response.errCode == -2) {
        debugPrint('wechat pay cancel: ${response.errStr}');
        // 用户取消支付
        // throw Exception('已取消支付');
        return {"orderUnique": wxTradeNo, "orderState": 0};
      } else {
        debugPrint('wechat pay failed: ${response.errStr}');
        // 支付失败
        throw Exception('支付失败');
      }
    } catch (e) {
      debugPrint('wechat pay error: $e');
      throw Exception('支付异常:$e');
    } finally {
      _cleanup();
    }

  
  }

  /// Fluwx 响应监听器
  void _responseListener(WeChatResponse response) {
    if (response is WeChatPaymentResponse) {
      _timeoutTimer?.cancel();
      if (_payCompleter != null && !_payCompleter!.isCompleted) {
        _payCompleter!.complete(response);
      }
    }
  }

  /// 清理资源
  void _cleanup() {
    _fluwxCancelable.cancel();
    _timeoutTimer?.cancel();
    _timeoutTimer = null;
    _payCompleter = null;
  }


  // 执行ios的微信支付
  Future<dynamic> _ios_pay_proc_ (String userCode, tbxStuId, chargeCode,deviceType,phone,stuId,ext,int duration, durationType, totalFee,bool renew, useCoin) async{

    print("[debug]. _ios_pay_proc_ 11 ");

    // 暂时用固定的价格
    var result = await _userAuthRepository.createOrder(userCode, tbxStuId, chargeCode, duration, durationType, totalFee,
        renew, phone, stuId, ext, useCoin ? 1 : 0, deviceType);

    print("[debug]. _ios_pay_proc_ 12 ");
    print(result);
    // map[nonceStr:qNfHK6a95jjJkwzDkh0h3fhfUVuS0jZ9 paySign: timeStamp:1783497438 wxTradeNo:to1281644408384671744]
    var data = result['data'] as Map<String, dynamic>?;
    if (data == null) {
      throw Exception('订单生成失败');
    }

    print("[debug]. _ios_pay_proc_ 13 ");
    // 3. 从后端响应中提取预支付ID
    final wxTradeNo = data['wxTradeNo'] as String?;
    if (wxTradeNo == null || wxTradeNo.isEmpty) {
      throw Exception('订单生成失败');
    }

    // 4. 从后端响应中提取支付参数(nonceStr、timestamp、paySign 由后端生成)
    final timestamp = data['timeStamp'] as int;

     print("[debug]. _ios_pay_proc_ 3 ");
    debugPrint('_ios_pay_proc_ => timestamp: $timestamp');
    debugPrint('_ios_pay_proc_ => wxTradeNo: $wxTradeNo');

    if (wxTradeNo.isEmpty) {
      throw Exception('支付参数获取失败');
    }

    // 执行ios支付  
    await _subService.initialize();

    // 为了调试,先模拟
    var product;
    for (var p in _subService.products) {
        // 因为带了一个¥符号
        debugPrint('checking ==> 产品ID: ${p.id}, 标题: ${p.title}, 价格: ${p.price}');
        if (p.price.toString().indexOf(totalFee.toString().substring(0,2))==1){
          product = p;
          debugPrint('match =====> 产品ID: ${p.id}, 标题: ${p.title}, 价格: ${p.price}');
          break;
        }
    }
    if(product==null){
       throw Exception('订单生成失败'); 
    }
    print("match product is "+product.price);
    var isOk = _subService.buySubscription(product, userCode, tbxStuId,wxTradeNo);
    if (isOk==true){
      return {"orderUnique": wxTradeNo, "orderState": 1};
    }else{
      return {"orderUnique": wxTradeNo, "orderState": 0};
    }
    // throw Exception('已取消支付');
    
  
  }


}