Flutter 中如何从 EGHL 支付响应获取 TxnMessage
支付阿杰
结论
makePayment() 返回 JSON 字符串。先用 Dart 的 jsonDecode() 将其转换为 Map,再通过键名 TxnMessage 读取结果:
final Map<String, dynamic> response =
jsonDecode(result) as Map<String, dynamic>;
final String txnMessage =
response['TxnMessage']?.toString() ?? 'Unknown transaction result';
对于示例响应,txnMessage 的值为:
Transaction Failed
在现有代码中处理
将获取结果后的代码改为:
String result = await Eghlpluginunofficial.makePayment(
merchantReturnUrl: 'SDK',
serviceId: 'SIT',
password: 'sit12345',
merchantName: 'GHL ePayment Testing',
amount: 1.00,
paymentDescription: 'eGHL Payment testing',
customerName: 'Somebody',
customerEmail: 'somebody@somesite.com',
customerPhone: '60123456789',
paymentId: paymentId,
orderNumber: paymentId,
currencyCode: 'MYR',
languageCode: 'EN',
pageTimeout: const Duration(
minutes: 12,
seconds: 30,
),
transactionType: 'SALE',
paymentMethod: 'ANY',
useDebugPaymentUrl: true,
);
final Map<String, dynamic> response =
jsonDecode(result) as Map<String, dynamic>;
final String txnMessage =
response['TxnMessage']?.toString() ?? 'Unknown transaction result';
if (!mounted) return;
setState(() {
_result = txnMessage;
});
print(txnMessage);
之后,页面中的 Text(_result) 会显示 Transaction Failed。
为什么需要 jsonDecode
返回内容虽然看起来像 Dart 对象,但 result 的声明类型是 String,因此不能直接这样访问:
result['TxnMessage']
必须先把 JSON 字符串解析成键值结构:
final decoded = jsonDecode(result);
解析完成后,才能通过键名访问字段:
decoded['TxnMessage']
代码中已经导入所需的库:
import 'dart:convert';
更稳妥的完整写法
支付插件返回的内容可能为空、格式异常,或者不是预期的 JSON 对象。可以增加类型和字段检查:
Future<void> pay() async {
try {
final String paymentId =
await Eghlpluginunofficial.generateId('Test');
final String result = await Eghlpluginunofficial.makePayment(
merchantReturnUrl: 'SDK',
serviceId: 'SIT',
password: 'sit12345',
merchantName: 'GHL ePayment Testing',
amount: 1.00,
paymentDescription: 'eGHL Payment testing',
customerName: 'Somebody',
customerEmail: 'somebody@somesite.com',
customerPhone: '60123456789',
paymentId: paymentId,
orderNumber: paymentId,
currencyCode: 'MYR',
languageCode: 'EN',
pageTimeout: const Duration(
minutes: 12,
seconds: 30,
),
transactionType: 'SALE',
paymentMethod: 'ANY',
useDebugPaymentUrl: true,
);
final dynamic decoded = jsonDecode(result);
if (decoded is! Map<String, dynamic>) {
throw const FormatException(
'Payment response is not a JSON object',
);
}
final String txnMessage =
decoded['TxnMessage']?.toString().trim() ?? '';
if (!mounted) return;
setState(() {
_result = txnMessage.isNotEmpty
? txnMessage
: 'No transaction message returned';
});
} on FormatException catch (err) {
if (!mounted) return;
setState(() {
_result = 'Invalid payment response: $err';
});
} on PlatformException catch (err) {
if (!mounted) return;
setState(() {
_result = 'PlatformException: ${err.message ?? err.toString()}';
});
} catch (err) {
if (!mounted) return;
setState(() {
_result = 'Error: $err';
});
}
}
判断支付是否成功
TxnMessage 可以用于页面展示,但不适合单独作为交易状态的判断依据,因为提示文字可能发生变化。判断结果时,应优先读取 EGHL 返回的状态字段,例如 TxnStatus,并按照当前插件或支付接口文档定义的状态值处理。
如果已经确认该接口中 "0" 代表成功,其他值代表失败,可以这样写:
final String status = decoded['TxnStatus']?.toString() ?? '';
final String message =
decoded['TxnMessage']?.toString() ?? 'Unknown transaction result';
if (status == '0') {
// 支付成功
} else {
// 支付失败或状态异常
}
setState(() {
_result = message;
});
TxnStatus 各个取值的具体含义,应以当前使用的 EGHL 接口或插件版本文档为准,不能根据一条示例响应推断所有状态码。
注意返回字符串的格式
传给 jsonDecode() 的内容必须是合法 JSON。实际返回值应类似:
{
"TxnMessage": "Transaction Failed",
"TxnStatus": "1"
}
问题中代码块外层的反引号只是 Markdown 格式标记。如果插件返回的原始字符串也包含反引号或其他额外字符,应先检查插件的原始输出。不要在正常情况下随意删除字符,否则可能掩盖真正的返回格式问题。
备注:内容仅供参考。
