createOrder method

Future<bool> createOrder({
  1. required num amountVal,
  2. num? coinsVal,
  3. String? coinPlanId,
  4. String? orderId,
  5. String? subject,
  6. String? appId,
  7. String? merchantNo,
  8. String? apiUrl,
  9. String? privateKeyBase64,
  10. String? frontCallbackUrl,
  11. String? notifyUrl,
  12. String? upiId,
  13. String currencyCode = "USD",
  14. String countryCode = "US",
  15. String userId = "USER_01",
  16. String paymentGatewayName = "PayerMax",
  17. bool testMode = false,
  18. bool openHostedCashierDirectly = true,
  19. dynamic onSuccess()?,
  20. dynamic onFailure()?,
  21. dynamic onToast()?,
})

Setup and initialize order creation with PayerMax

Implementation

Future<bool> createOrder({
  required num amountVal,
  num? coinsVal,
  String? coinPlanId,
  String? orderId,
  String? subject,
  String? appId,
  String? merchantNo,
  String? apiUrl,
  String? privateKeyBase64,
  String? frontCallbackUrl,
  String? notifyUrl,
  String? upiId,
  String currencyCode = "USD",
  String countryCode = "US",
  String userId = "USER_01",
  String paymentGatewayName = "PayerMax",
  bool testMode = false,
  bool openHostedCashierDirectly = true,
  Function()? onSuccess,
  Function()? onFailure,
  Function()? onToast,
}) async {
  this.paymentGatewayName = paymentGatewayName;
  this.testMode = testMode;
  this.openHostedCashierDirectly = openHostedCashierDirectly;
  amount.value = amountVal.toDouble();
  coins.value = (coinsVal ?? amountVal).toInt();
  planId.value = coinPlanId ?? orderId ?? "";
  currency.value = currencyCode;
  onPaymentSuccess = onSuccess;
  onPaymentFailure = onFailure;
  onShowToast = onToast;
  statusRx.value = PayerMaxStatusModel.waiting();
  isLoading.value = true;

  try {
    final nowUtc = DateTime.now().toUtc();
    final requestTime = _formatRfc3339(nowUtc);

    final currentOutTradeNo =
        orderId ?? "ORDER_${nowUtc.millisecondsSinceEpoch}";
    outTradeNo.value = currentOutTradeNo;

    targetAppId = appId ?? PayerMaxConfig.defaultAppId;
    targetMerchantNo = merchantNo ?? PayerMaxConfig.defaultMerchantNo;
    targetApiUrl = apiUrl ??
        (testMode
            ? PayerMaxConfig.sandboxApiUrl
            : PayerMaxConfig.productionApiUrl);
    targetPrivateKey =
        privateKeyBase64 ?? PayerMaxConfig.defaultPrivateKeyBase64;
    frontCallback = frontCallbackUrl ?? "storybox://open";
    notifyUrlStr = notifyUrl;
    orderSubjectStr = subject ??
        (coinPlanId != null
            ? "Coin Recharge Plan $coinPlanId"
            : "Order $currentOutTradeNo");

    final requestBodyMap = {
      "version": "1.4",
      "keyVersion": "1",
      "requestTime": requestTime,
      "appId": targetAppId,
      "merchantNo": targetMerchantNo,
      "data": {
        "outTradeNo": currentOutTradeNo,
        "subject": orderSubjectStr,
        "totalAmount": amountVal.toStringAsFixed(2),
        "currency": currencyCode,
        "country": countryCode,
        "userId": userId,
        "frontCallbackUrl": frontCallback,
        if (notifyUrlStr != null && notifyUrlStr!.isNotEmpty)
          "notifyUrl": notifyUrlStr,
      }
    };

    final jsonBodyString = jsonEncode(requestBodyMap);

    // Sign with RSA Private Key
    final privateKey = _parsePkcs8PrivateKey(base64Decode(targetPrivateKey));
    final signature =
        _signSha256WithRsa(utf8.encode(jsonBodyString), privateKey);

    final response = await http.post(
      Uri.parse(targetApiUrl),
      headers: {
        "Content-Type": "application/json;charset=utf-8",
        "Accept": "application/json",
        "sign": signature,
      },
      body: jsonBodyString,
    );

    final resData = jsonDecode(response.body) as Map<String, dynamic>;
    final code = resData["code"] ?? "";
    final msg = resData["msg"] ?? "";

    rawResponseMsg.value = msg.isNotEmpty ? msg : code;

    if (code == "APPLY_SUCCESS" || code == "SUCCESS") {
      final data = resData["data"] ?? {};
      redirectUrl.value = data["redirectUrl"] ?? "";
      tradeNo.value = data["payerMaxTradeNo"] ?? currentOutTradeNo;
    } else {
      tradeNo.value = currentOutTradeNo;
    }

    final payeeUpi = upiId ?? "";
    upiUri.value =
        "upi://pay?pa=$payeeUpi&pn=PayerMax&am=${amountVal.toStringAsFixed(2)}&cu=$currencyCode&tr=$currentOutTradeNo";

    isLoading.value = false;
    return true;
  } catch (e) {
    isLoading.value = false;
    debugPrint("PayerMaxController Exception => $e");
    final failureResponse = IncodesPaymentResponse(
      "Connection Error: $e",
      false,
      outTradeNo.value,
    );
    _handleFailure(failureResponse);
    return false;
  }
}