Skip to content

Payment failed with message: Request must be in JSON format with content type application/json #91

Description

@Praveencodenex

Issue Description

When attempting to process a card payment through the PayTabs Flutter SDK, I'm receiving a content type error.

Environment

  • Flutter SDK : sdk: ^3.5.2
  • PayTabs SDK version: flutter_paytabs_bridge: 2.7.0
  • Platform: [iOS/Android]
  • Device: Tested multiple device (both android and ios)

Steps to Reproduce

  1. Initialized payment with method "card payment"
  2. Set amount to 400.0
  3. Set eventId to 25
  4. Set country to SAR (Saudi Arabia)
  5. Used dummy/test card with following details
    Card Number: 4000 0000 0000 0002
    Exp date: 03/27
    CVV:123
  6. Error getting : Payment failed with message: Request must be in JSON format with content type application/json

Code Snippet

`class PaymentService {
static Future initiatePayment({
required BuildContext context,
required double amount,
required int eventId,
String? cartDescription = "Event Payment",
String? packageId,
required String paymentMethod,
}) async {

print("Initiating payment with method: $paymentMethod, amount: $amount, eventId: $eventId");
final payTabsProvider = Provider.of<PayTabsProvider>(context, listen: false);
final completer = Completer<PaymentResult>();

try {
  switch (paymentMethod.toLowerCase()) {
    case 'apple pay':
      payTabsProvider.payWithApple(context, amount, eventId, (event) {
        print("Handling Apple Pay event: $event");
        _handlePaymentEvent(event, completer, eventId);
      });
      break;
    case 'card payment':
      payTabsProvider.payWithCards(context, amount, eventId, (event) {
        print("Handling Card payment event: $event");
        _handlePaymentEvent(event, completer, eventId);
      });
      break;
    case 'samsung pay':
      payTabsProvider.payWithSamsung(context, amount, eventId, (event) {
        print("Handling Samsung Pay event: $event");
        _handlePaymentEvent(event, completer, eventId);
      });
      break;
    default:
      print("Unsupported payment method: $paymentMethod");
      completer.complete(PaymentResult.failure('Unsupported payment method: $paymentMethod//'));
      break;
  }
} catch (e) {
  print("Error in initiatePayment: $e");
  completer.complete(PaymentResult.failure('Payment initiation failed: $e'));
}

return completer.future;

}

static void _handlePaymentEvent(Map<String, dynamic> event, Completer completer, int eventId) {
print("Processing payment event: $event");

var data = event['data'] ?? {};
String status = event['status']?.toString() ?? 'error';
bool isSuccess = status == 'success' && (data['isSuccess'] == true);
String transactionReference = data['transactionReference']?.toString() ?? 'Unknown';
String message = event['message']?.toString() ?? 'Unknown error';

if (isSuccess) {
  print("Payment successful with transaction reference: $transactionReference");
  completer.complete(PaymentResult.success(eventId, transactionReference));
} else {
  print("Payment failed with message: $message");
  completer.complete(PaymentResult.failure(message));
}

}
}`

`import 'package:flutter/material.dart';
import 'package:flutter_paytabs_bridge/BaseBillingShippingInfo.dart';
import 'package:flutter_paytabs_bridge/IOSThemeConfiguration.dart';
import 'package:flutter_paytabs_bridge/PaymentSdkApms.dart';
import 'package:flutter_paytabs_bridge/PaymentSdkConfigurationDetails.dart';
import 'package:flutter_paytabs_bridge/PaymentSdkLocale.dart';
import 'package:flutter_paytabs_bridge/PaymentSdkTokeniseType.dart';
import 'package:flutter_paytabs_bridge/flutter_paytabs_bridge.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';

class PayTabsProvider with ChangeNotifier {
PaymentSdkConfigurationDetails generateConfig(BuildContext context, double amount) {
var billingDetails = BillingDetails(
"Test User",
"test@example.com",
"+966123456789",
"123 Test Street",
"SA",
"Riyadh",
"Riyadh",
"12345",
);

var profileId = dotenv.env['PAYTABS_PROFILE_ID'] ?? '';
var serverKey = dotenv.env['PAYTABS_SERVER_KEY'] ?? '';
var clientKey = dotenv.env['PAYTABS_CLIENT_KEY'] ?? '';

if (profileId.isEmpty || serverKey.isEmpty || clientKey.isEmpty) {
  debugPrint("Error: Missing PayTabs credentials in .env file");
}

var configuration = PaymentSdkConfigurationDetails(
  profileId: profileId,
  serverKey: serverKey,
  clientKey: clientKey,
  cartId: "cart_${DateTime.now().millisecondsSinceEpoch}",
  currencyCode: "SAR",
  amount: amount,
  screentTitle: "Halawaghala Payment",
  showBillingInfo: true,
  forceShippingInfo: false,
  cartDescription: "Halawaghala Payment",
  merchantName: "Halawaghala",
  merchantApplePayIndentifier: "merchant.com.halawaghala.services",
  samsungPayToken: "your_samsung_pay_token",
  billingDetails: billingDetails,
  tokeniseType: PaymentSdkTokeniseType.USER_OPTIONAL,
  merchantCountryCode: "SA",
  simplifyApplePayValidation: true,
  alternativePaymentMethods: [PaymentSdkAPms.APPLE_PAY, PaymentSdkAPms.SAMSUNG_PAY],
  locale: Localizations.localeOf(context).languageCode == "ar" ? PaymentSdkLocale.AR : PaymentSdkLocale.EN,
);

final theme = IOSThemeConfigurations();
theme.secondaryColor = "02652A";
theme.buttonColor = "02652A";
// Remove logoImage if the asset is missing to avoid errors
configuration.iOSThemeConfigurations = theme;

return configuration;

}

void payWithCards(BuildContext context, double amount, int eventId, Function(Map<String, dynamic>) onPaymentCallback) async {
try {
FlutterPaytabsBridge.startCardPayment(generateConfig(context, amount), (event) {
// Cast event to Map<String, dynamic>
final eventMap = event.cast<String, dynamic>();
onPaymentCallback(eventMap);
});
} catch (e) {
onPaymentCallback({'status': 'error', 'message': 'Payment initiation failed: $e'});
}
}

void payWithSamsung(BuildContext context, double amount, int eventId, Function(Map<String, dynamic>) onPaymentCallback) async {
try {
FlutterPaytabsBridge.startSamsungPayPayment(generateConfig(context, amount), (event) {
final eventMap = event.cast<String, dynamic>();
onPaymentCallback(eventMap);
});
} catch (e) {
onPaymentCallback({'status': 'error', 'message': 'Payment initiation failed: $e'});
}
}

void payWithApple(BuildContext context, double amount, int eventId, Function(Map<String, dynamic>) onPaymentCallback) async {
try {
FlutterPaytabsBridge.startApplePayPayment(generateConfig(context, amount), (event) {
final eventMap = event.cast<String, dynamic>();
onPaymentCallback(eventMap);
});
} catch (e) {
onPaymentCallback({'status': 'error', 'message': 'Payment initiation failed: $e'});
}
}

void initializePayTabs() {
}
}`

`class PaymentResult {
final bool isSuccess;
final bool isCancelled;
final String message;
final int? eventId;
final String? details;

PaymentResult._({
required this.isSuccess,
required this.isCancelled,
required this.message,
this.eventId,
this.details,
});

factory PaymentResult.success(int eventId, String details) {
return PaymentResult._(
isSuccess: true,
isCancelled: false,
message: "Payment Successful!",
eventId: eventId,
details: details,
);
}

factory PaymentResult.failure(String message) {
return PaymentResult._(
isSuccess: false,
isCancelled: false,
message: message,
);
}

factory PaymentResult.cancelled(String message) {
return PaymentResult._(
isSuccess: false,
isCancelled: true,
message: message,
);
}
}`

`import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:hala_wa_ghala/screens/checkout/components/payment_result.dart';

import 'package:hala_wa_ghala/res/widgets/custom_snack_bar.dart';
import 'dart:io' show Platform;

import '../../../data/manager/payment_manager.dart';

class PaymentType {
final String title;
final String svgAsset;
final double iconSize;
final bool enabled;
final VoidCallback? onTap;

PaymentType({
required this.title,
required this.svgAsset,
this.iconSize = 24.0,
this.enabled = true,
this.onTap,
});

static List getPaymentTypes(BuildContext context, double amount, int eventId, Function(PaymentResult) onPaymentResult) {
bool isIOS = Platform.isIOS;
bool isAndroid = Platform.isAndroid;

return [
  PaymentType(
    title: AppLocalizations.of(context)!.payApple,
    svgAsset: 'assets/images/applepay.svg',
    iconSize: 30,
    enabled: isIOS,
    onTap: isIOS
        ? () {
      Navigator.pop(context);
      _handleApplePay(context, amount, eventId, onPaymentResult);
    }
        : null,
  ),
  PaymentType(
    title: AppLocalizations.of(context)!.cardPayment,
    svgAsset: 'assets/images/card.svg',
    onTap: () {
      Navigator.pop(context);
      _handleCardPayment(context, amount, eventId, onPaymentResult);
    },
  ),
  PaymentType(
    title: AppLocalizations.of(context)!.samsungPay,
    svgAsset: 'assets/images/samsung_pay.svg',
    iconSize: 25,
    enabled: isAndroid,
    onTap: isAndroid
        ? () {
      Navigator.pop(context);
      _handleSamsungPay(context, amount, eventId, onPaymentResult);
    }
        : null,
  ),
];

}

static void _handleApplePay(BuildContext context, double amount, int eventId, Function(PaymentResult) onPaymentResult) async {
try {
final result = await PaymentService.initiatePayment(
context: context,
amount: amount,
eventId: eventId,
paymentMethod: 'apple pay',
);
_handlePaymentResult( result, amount);
onPaymentResult(result);
} catch (e) {
final failureResult = PaymentResult.failure("Apple Pay failed: $e");
_handlePaymentResult( failureResult, amount);
onPaymentResult(failureResult);
}
}

static void _handleCardPayment(BuildContext context, double amount, int eventId, Function(PaymentResult) onPaymentResult) async {
try {
final result = await PaymentService.initiatePayment(
context: context,
amount: amount,
eventId: eventId,
paymentMethod: 'card payment',
);
_handlePaymentResult( result, amount);
onPaymentResult(result);
} catch (e) {
final failureResult = PaymentResult.failure("Card Payment failed: $e");
_handlePaymentResult( failureResult, amount);
onPaymentResult(failureResult);
}
}

static void _handleSamsungPay(BuildContext context, double amount, int eventId, Function(PaymentResult) onPaymentResult) async {
try {
final result = await PaymentService.initiatePayment(
context: context,
amount: amount,
eventId: eventId,
paymentMethod: 'samsung pay',
);
_handlePaymentResult( result, amount);
onPaymentResult(result);
} catch (e) {
final failureResult = PaymentResult.failure("Samsung Pay failed: $e");
_handlePaymentResult( failureResult, amount);
onPaymentResult(failureResult);
}
}

static void _handlePaymentResult( PaymentResult result, double amount) {
if (result.isSuccess) {
SnackBarUtils.showSuccess(result.message);

} else {
  SnackBarUtils.showError(result.message);
}

}
}`

Iam also tried your example code with same credentials getting same error with Saudi Arabia

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions