Search code examples
androidretrofitx-www-form-urlencoded

How to send post request with content-type x-www-form-urlencoded android retrofit


I am facing problem sending post request with content-type as x-www-form-urlencoded in android retrofit. Not sure about the error I am making while sending post request. When same request is send via postman, I can receive expected correct response. Moreover, I tried sending same response via html form and received successful response

public class RequestManager {

    private static Retrofit retrofit;

    private static final String BASE_URL = "https://ipguat.apps.net.pk/Ecommerce/api/Transaction/";
    private OkHttpClient okhttpClient;

    static Gson gson = new GsonBuilder()
            .setLenient()
            .create();

    public static Retrofit getRetrofitInstance() {
        if (retrofit == null) {
            retrofit = new retrofit2.Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create(gson))
                    .build();
        }
        return retrofit;
    }

}

//MainActivity from where I am sending post request

 private void sendPayment(String token) {
        Date c = Calendar.getInstance().getTime();

        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        String formattedDate = df.format(c);
        Call<ResponseBody> call = service.sendPayment("102", "Arfeen Test", token, "00", "5", "03451234567", "arfeen@arfeen.me", "POSTMAN-TEST-ARF", "01", "Test Purchase", "www.facebook.com", "www.google.com", "TEST-01", formattedDate, "www.youtube.com");
        call.enqueue(new Callback<ResponseBody>() {
                         @Override
                         public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                             if (response.isSuccessful()) {
                                 try {
                                     renderPage(response.body().string());
                                 } catch (IOException e) {
                                     e.printStackTrace();
                                 }
                             }
                         }

                         @Override
                         public void onFailure(Call<ResponseBody> call, Throwable t) {
                             Toast.makeText(MainActivity.this, "Something went wrong...Please try later!", Toast.LENGTH_SHORT).show();
                         }
                     }
        );


    }

// Interface where endpoint for API is mentioned

public interface TokenService {

    @FormUrlEncoded
    @POST("PostTransaction/")
    Call<ResponseBody> sendPayment(@Field("MERCHANT_ID") String id,
                                   @Field("MERCHANT_NAME") String merchantName,
                                   @Field("TOKEN") String token,
                                   @Field("PROCCODE") String proccode,
                                   @Field("TXNAMT") String transaction,
                                   @Field("CUSTOMER_MOBILE_NO") String mobile,
                                   @Field("CUSTOMER_EMAIL_ADDRESS") String email,
                                   @Field("SIGNATURE") String signature,
                                   @Field("VERSION") String version,
                                   @Field("TXNDESC") String productDescription,
                                   @Field("SUCCESS_URL") String successUrl,
                                   @Field("FAILURE_URL") String failureUrl,
                                   @Field("BASKET_ID") String basketID,
                                   @Field("ORDER_DATE") String orderDate,
                                   @Field("CHECKOUT_URL") String checoutUrl);

}

Solution

  • Use @Headers annotation.

    public interface TokenService {
    
        @FormUrlEncoded
        @Headers("Content-Type:application/x-www-form-urlencoded")
        @POST("PostTransaction/")
        Call<ResponseBody> sendPayment(@Field("MERCHANT_ID") String id,
                                       @Field("MERCHANT_NAME") String merchantName,
                                       @Field("TOKEN") String token,
                                       @Field("PROCCODE") String proccode,
                                       @Field("TXNAMT") String transaction,
                                       @Field("CUSTOMER_MOBILE_NO") String mobile,
                                       @Field("CUSTOMER_EMAIL_ADDRESS") String email,
                                       @Field("SIGNATURE") String signature,
                                       @Field("VERSION") String version,
                                       @Field("TXNDESC") String productDescription,
                                       @Field("SUCCESS_URL") String successUrl,
                                       @Field("FAILURE_URL") String failureUrl,
                                       @Field("BASKET_ID") String basketID,
                                       @Field("ORDER_DATE") String orderDate,
                                       @Field("CHECKOUT_URL") String checoutUrl);
    
    }
    

    Try set up OkhttpClient,

    OkhttpManager.java

    import android.content.Context;
    import android.util.Log;
    import android.webkit.CookieManager;
    
    import java.security.cert.CertificateException;
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    import java.util.concurrent.TimeUnit;
    
    import javax.net.ssl.TrustManager;
    import javax.net.ssl.X509TrustManager;
    
    import okhttp3.Cookie;
    import okhttp3.CookieJar;
    import okhttp3.HttpUrl;
    import okhttp3.OkHttpClient;
    import okhttp3.Request;
    import okhttp3.Response;
    import okhttp3.logging.HttpLoggingInterceptor;
    
    public class OkHttpManager {
        private final String TAG = "OkHttpManager";
        private final int TIME_OUT_SECONDS = 60;
        private static OkHttpManager instance = null;
        private WebViewCookieHandler mWebViewCookieHandler = null;
    
        public static OkHttpManager getInstance() {
            if (instance == null) {
                instance = new OkHttpManager();
            }
            return instance;
        }
    
        private OkHttpManager() {
            if (mWebViewCookieHandler == null)
                mWebViewCookieHandler = new WebViewCookieHandler();
        }
    
        private static ArrayList<String> sCurCookies = new ArrayList<>();
    
        OkHttpClient getOkHttpClientDefault(Context context) {
            // init okhttp 3 logger
            HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
            interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
            try {
                final TrustManager[] trustAllCerts = new TrustManager[]{
                        new X509TrustManager() {
                            @Override
                            public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
                            }
    
                            @Override
                            public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
                            }
    
                            @Override
                            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                                return new java.security.cert.X509Certificate[]{};
                            }
                        }
                };
    
                return new OkHttpClient()
                        .newBuilder()
                        .cookieJar(mWebViewCookieHandler)
                        .hostnameVerifier((s, sslSession) -> true)
                        .connectTimeout(TIME_OUT_SECONDS, TimeUnit.SECONDS)
                        .readTimeout(TIME_OUT_SECONDS, TimeUnit.SECONDS)
                        .writeTimeout(TIME_OUT_SECONDS, TimeUnit.SECONDS)
                        .addInterceptor(interceptor)
                        .addInterceptor(chain -> {
                            Request.Builder builder = chain.request().newBuilder();
                            return chain.proceed(builder.build());
                        })
                        .addInterceptor(chain -> {
                            Response response = chain.proceed(chain.request());
    
                            if (!response.headers("Set-Cookie").isEmpty()) {
                                Log.d(TAG, "getCookie header added");
                                sCurCookies.addAll(response.headers("Set-Cookie"));
                            }
                            response.body();
                            return response;
                        })
                        .build();
            } catch (Exception e) {
                Log.e(TAG, e.toString());
            }
            return null;
        }
    
        private class WebViewCookieHandler implements CookieJar {
            private CookieManager webviewCookieManager = CookieManager.getInstance();
    
            @Override
            public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
                String urlString = url.toString();
    
                for (Cookie cookie : cookies) {
                    webviewCookieManager.setCookie(urlString, cookie.toString());
                }
            }
    
            @Override
            public List<Cookie> loadForRequest(HttpUrl url) {
                String urlString = url.toString();
                String cookiesString = webviewCookieManager.getCookie(urlString);
                if (cookiesString != null && !cookiesString.isEmpty()) {
                    //We can split on the ';' char as the cookie manager only returns cookies
                    //that match the url and haven't expired, so the cookie attributes aren't included
                    String[] cookieHeaders = cookiesString.split(";");
                    List<Cookie> cookies = new ArrayList<>(cookieHeaders.length);
    
                    for (String header : cookieHeaders) {
                        cookies.add(Cookie.parse(url, header));
                    }
                    return cookies;
                }
                return Collections.emptyList();
            }
        }
    }
    

    RequestManager.java

    public class RequestManager {
    
        private static Retrofit retrofit;
    
        private static final String BASE_URL = "https://ipguat.apps.net.pk/Ecommerce/api/Transaction/";
        private OkHttpClient okhttpClient;
    
        static Gson gson = new GsonBuilder()
                .setLenient()
                .create();
    
        public static Retrofit getRetrofitInstance(Activity activity) {
            if (retrofit == null) {
                retrofit = new retrofit2.Retrofit.Builder()
                        .baseUrl(BASE_URL)
                        .client(OkHttpManager.getInstance().getOkHttpClientDefault(activity))
                        .addConverterFactory(GsonConverterFactory.create(gson))
                        .build();
            }
            return retrofit;
        }
    
    }