I have this API interface

@FormUrlEncoded
@Headers("Accept: application/json;charset=UTF-8")
@POST("checkout/guest/netspay")
fun getNestPayCheckOut(
   @Field("outlet_id") outLetId: String,
   @Field("order_type") orderType:String,
   @Field("products") products:String,
   @Field("pickup_time") pickUpTime:String,
   @Field("total_price_tax") totalPrice:String,
   @Field("order_note") orderNote:String,
   @Field("name") name:String,
   @Field("email") email:String,
   @Field("phone") phone:String

):Observable<NetsPayCheckOut>

This is how I perform the API call

fun getNetsPayGuestCheckOut(
   outletId:String, orderType:String,
   products:String, pickUpTime:String,
   name:String,email:String,
   phone:String, totalPrice:String,
   note:String,
   mNetsCheckOut:MutableLiveData<NetsPayCheckOut>,
   mErrorLD: MutableLiveData<Error>
){
mTheApiNew.getNestPayCheckOut(
   outletId,orderType,
   products,pickUpTime,
   name,email,
   phone,totalPrice,
   note
)
   .subscribeOn(scheduler)
   .observeOn(Schedulers.computation())
   .observeOn(AndroidSchedulers.mainThread())
   .subscribe(object : Observer<NetsPayCheckOut> {
      override fun onComplete() { }

      override fun onSubscribe(d: Disposable) { }

      override fun onNext(response: NetsPayCheckOut) {
         if(response.status!!){
            mNetsCheckOut.value= response
         } else {
            mErrorLD.value= ServerError(response.message!!)
            Log.e("checkout","${response.status} and ${response.message}")
         }
      }

      override fun onError(e: Throwable) {
         mErrorLD.value= FailureError(e.message!!)
         Log.e("checkout","${e.message} and ${e.localizedMessage}")
      }

   })
}

Postman call

Postman header

NetsPayCheckOut & NetsPayData classes:

import com.google.gson.annotations.SerializedName

data class NetsPayCheckOut(
   val code: Int? = null,
   @SerializedName("data")
   val netsPayData: NetsPayData? = null,
   val message: String? = null,
   val status: Boolean? = null
)

data class NetsPayData(
   val secretKey: String? = null,
   val txnReq: String? = null,
   val keyId: String? = null
)

But I always receive this error

com.jakewharton.retrofit2.adapter.rxjava2.HttpException: HTTP 422 Unprocessable Entity

1 Answers

1
Julien Arzul On

The Exception tells you that your server responded with an HTTP error 422. Which means that your request reached your server correctly but it couldn't be processed correctly.

Based on the Postman screenshot and the Retrofit declaration, I can see that you declare your request @FormUrlEncoded but in Postman you send those fields not encoded (the equivalent of FormUrlEncoded in Postman is the "x-www-form-urlencoded" tab). Removing the @FormUrlEncoded annotation from your getNestPayCheckOut should help.

If not, one useful way of debugging such errors is by using a Proxy like https://www.charlesproxy.com/. It will allow you to see the HTTP requests made from your phone/application and compare it with what Postman is sending.

As a side-note, if @FormUrlEncoded is indeed what is causing the issue, I would recommend modifying your server so that it accepts only encoded fields: that way you won't get any issues if your fields contain special characters like "=" and "&"