В настоящее время я разрабатываю платежный модуль во Flutter и использую B2C API M-Pesa. Это код функции будущего вызова B2C:
Future b2cPayment({
required String phoneNumber,
required String amount,
required String remarks,
}) async {
try {
String originatorConversationID = 'B2C_${DateTime.now()}_${Random().nextInt(1000000).toString().padLeft(6, '0')}';
// Validate amount for B2C
final amountValue = int.tryParse(amount);
if (amountValue == null || amountValue < 10) {
throw Exception('Minimum withdrawal amount is 10 KES');
}
if (amountValue > 150000) {
throw Exception('Maximum withdrawal amount is 150,000 KES');
}
final token = await _getAccessToken(false);
// Format phone number
String formattedPhone = phoneNumber.trim();
if (formattedPhone.startsWith('0')) {
formattedPhone = '254${formattedPhone.substring(1)}';
} else if (formattedPhone.startsWith('+254')) {
formattedPhone = formattedPhone.substring(1);
}
final requestData = {
'OriginatorCoversationID': originatorConversationID,
'InitiatorName': Mpesa_Withdraw_Config.initiatorName,
'SecurityCredential': Mpesa_Withdraw_Config.securityCredential,
'CommandID':
'BusinessPayment', // Use 'BusinessPayment' not 'PromotionPayment'
'Amount': amount,
'PartyA': Mpesa_Withdraw_Config.businessShortCode,
'PartyB': formattedPhone,
'Remarks': remarks,
'QueueTimeOutURL': Mpesa_Withdraw_Config.timeoutUrl,
'ResultURL': Mpesa_Withdraw_Config.b2cCallbackUrl,
'Occasion': 'Withdrawal',
};
final response = await http
.post(
Uri.parse(
'${Mpesa_Withdraw_Config.baseUrl}/mpesa/b2c/v3/paymentrequest'),
headers: {
'Authorization': 'Bearer $token',
'Content-Type': 'application/json',
},
body: jsonEncode(requestData),
)
.timeout(
const Duration(seconds: 30),
onTimeout: () {
throw Exception('Request timed out. Please try again.');
},
);
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
// Check for errors in response
if (data['errorCode'] != null) {
throw Exception('M-Pesa B2C Error: ${data['errorMessage']}');
}
return data;
} else {
final errorBody = jsonDecode(response.body);
throw Exception(
'${response.statusCode}: B2C payment failed: ${errorBody['errorMessage'] ?? response.body}');
print('${errorBody['errorMessage']}');
}
} catch (e) {
if (e.toString().contains('SocketException')) {
throw Exception('No internet connection.');
}
rethrow;
}
}
Но я продолжаю получать эту ошибку:
Ошибка: Исключение 400: платеж B2C не выполнен: неверный запрос — неверный OriginatorConversationID
Я также пытался создать функцию генератора() для генерации случайного строкового значения для originatorConversationId, но все равно получил то же самое ошибка
String generator(){
const originatorConversationID = `B2C_${Date.now()}_${Math.random().toString(36).substring(7)}`;
}
Подробнее здесь: https://stackoverflow.com/questions/797 ... call-error