Richie P.
Richie P.

Reputation: 354

API always error 408 - Invalid Data Type Sent

I really don't know what happen with this error (I mean by, is this related to the Flutter or Dart or the package that I used or the API that I used). In a nutshell, it always giving me back error code 408 - Invalid data type sent from my flutter App, while I COMPLETELY could done it in Postman and been tried it with PHP.

I just wanna call a normal POST request to my payment gateway API (I use Midtrans).


Here is my result:

From Postman

From Postman

From my app in Flutter within VS Code From my app in Flutter within VS Code


What am I doing wrong? I am completely has no clue about this. I will give the detail below for anyone who want to try a simple call to this API so you can reproduce this.

Endpoint

https://api.sandbox.midtrans.com/v2/charge

Body

    "payment_type": "bank_transfer",
    "bank_transfer": {
        "bank": "permata",
        "va_number": "1234567890"
    },
    "transaction_details": {
        "order_id": "order-101b-{{2020-11-0222rrd324dzz}}",
        "gross_amount": 44000
    },
    "customer_details": {
        "email": "[email protected]",
        "first_name": "Richie",
        "last_name": "Permana",
        "phone": "+6281 1234 1234"
    },
    "item_details": [
        {
            "id": "item01",
            "price": 21000,
            "quantity": 1,
            "name": "Schema Programmer"
        },
        {
            "id": "item02",
            "price": 23000,
            "quantity": 1,
            "name": "Ayam Xoxoxo"
        }
    ]
}

This is the header

{
  'content-type': 'application/json',
  'accept': 'application/json',
  'authorization':
      'Basic U0ItTWlkLXNlcnZlci1kNnJNbGp5ZDBKSDgyOEhBT28tSWkxM0E=',
  'cache-control': 'no-cache'
}

My Dart Function Snippet

Future _makePayment() async {
    String url = "https://api.sandbox.midtrans.com/v2/charge";

    final Map<String, String> header = {
      'content-type': 'application/json',
      'accept': 'application/json',
      'authorization':
          'Basic U0ItTWlkLXNlcnZlci1kNnJNbGp5ZDBKSDgyOEhBT28tSWkxM0E=',
      'cache-control': 'no-cache'
    };

    var json = jsonEncode({
      "payment_type": "bank_transfer",
      "bank_transfer": {"bank": "permata", "va_number": "1234567890"},
      "transaction_details": {
        "order_id": "order-101b-{{2020-11-0222rrddzz557}}",
        "gross_amount": 44000
      },
      "customer_details": {
        "email": "[email protected]",
        "first_name": "Richie",
        "last_name": "Permana",
        "phone": "+6281 1234 1234"
      },
      "item_details": [
        {
          "id": "item01",
          "price": 21000,
          "quantity": 1,
          "name": "Schema Programmer"
        },
        {"id": "item02", "price": 23000, "quantity": 1, "name": "Ayam Xoxoxo"}
      ]
    });

    Response response = await post(
      url,
      headers: header,
      body: json,
    );


    var res = jsonDecode(response.body);
    print(
        "payloadddded =>> ${json.runtimeType}\n");
    if (res['status_code'] == 201) {
      print("ngeheeeee berhasil MIDTRAANSS =>> ${res['status_code']}");
    } else {
      print("res full =>> ${response.body}");
      print("ape kaden => ${res['status_code']} || terosz => $res");
    }
  }

Note:

For the body, you may be need put more attention on the order_id because it will return some error if you not change the order_id (yes, think it like any other primary key id).

API Docs: https://api-docs.midtrans.com/


I really appreciate any helps or workaround given. Thank you very much.

Upvotes: 0

Views: 1016

Answers (1)

Richard Heap
Richard Heap

Reputation: 51750

Dart's package:http manipulates the content-type header under the hood. If it does the encoding from string to bytes for you (i.e. if body is a string) then it adds a charset=xxx suffix to the content type - it becomes, for example application/json; charset=utf-8.

Apparently your server is allergic to this. (It shouldn't be, but whatever...). You can prove this using the dart:io http client.

  var client = HttpClient();
  var request = await client.postUrl(Uri.parse(url));
  request.headers.set('content-type', 'application/json; charset=utf-8');
  request.headers.add(
    'authorization',
    'Basic U0ItTWlkLXNlcnZlci1kNnJNbGp5ZDBKSDgyOEhBT28tSWkxM0E=',
  );
  request.add(utf8.encode(json));
  var response2 = await request.close();
  var reply = await response2.transform(utf8.decoder).join();
  print(reply);
  client.close();

This gives the same 408 error but does not if the charset suffix is removed.

There's a simple solution. Don't allow http to do the encoding for you - do it yourself.

  var response = await http.post(
    url,
    headers: headers,
    body: utf8.encode(json),
  );

(Your json apparently needs work, because this now complains that the json is invalid, but that's easy to compare with your working postman.)

Upvotes: 2

Related Questions