Beberapa waktu yang lalu, sempat terjadi kenaikan harga bawang yang cukup signifikan karena petani bawang di Brebes mengalami gagal panen akibat bencana banjir. Akibat kejadian itu, saya iseng-iseng mencari situs yang menyediakan informasi harga bahan pokok. Akhirnya ketemu salah satu situs yang menyediakan informasi harga bahan pokok, yaitu situs PIHPS Nasiona. Ternyata situs tersebut juga menyediakan aplikasi untuk perangkat mobile yang bisa diunduh di situs google play bagi pengguna Android, dan di App Store bagi pengguna produk Apple.

Dari sana, akhirnya saya mengunduh aplikasi untuk Android menggunakan situs apk-dl. Versi aplikasi yang diunduh pada tutorial ini adalah v3.0.4.

Setelah aplikasi tersebut berhasil diunduh, selanjutnya adalah mengekstraknya menggunakan aplikasi zip (pada tutorial ini digunakan p7zip) dengan perintah seperti ini:

% 7z x -oekstrak harga_pangan_3.0.4.apk

7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,64 bits,4 CPUs Intel(R) Core(TM) i3-2330M CPU @ 2.20GHz (206A7),ASM)

Scanning the drive for archives:
1 file, 24327735 bytes (24 MiB)

Extracting archive: harga_pangan_3.0.4.apk
--
Path = harga_pangan_3.0.4.apk
Type = zip
Physical Size = 24327735

Everything is Ok

Files: 3021
Size:       47267540
Compressed: 24327735

Perintah di atas akan mengekstrak aplikasi harga pangan ke sub direktori ekstrak. Selanjutnya, kita akan pindah ke sub direktori ekstrak tersebut dan mengubah file classes.dex menjadi classes.jar menggunakan Dex2Jar.

% cd ekstrak
% dex2jar classes.dex

Setelah proses konversi dari dex ke jar selesai. Kita dapat menggunakan aplikasi Java Decompiler untuk melakukan dekompilasi. Pada panel sebelah kiri aplikasi JD-Gui, pilih com -> pihps.hargapangan -> domain -> repository -> api -> ConfigUrl.class , maka akan muncul seperti pada gambar di bawah ini:

JD-Gui

Berikut ini adalah hasil dekompilasi class tersebut:

package com.pihps.hargapangan.domain.repository.api;

public class ConfigUrl {
  public static String allCommodity() {
    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder.append(getService());
    stringBuilder.append("getjson?option=com_gtpihps&task=json.commodities");
    return stringBuilder.toString();
  }

  public static String allReferences() {
    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder.append(getService());
    stringBuilder.append("getjson?option=com_gtpihps&task=json.references&all=1");
    return stringBuilder.toString();
  }

  public static String checkAppUpdate(String paramString) {
    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder.append(getService());
    stringBuilder.append("getjson?option=com_gtpihps&task=json.checkVersion&version=");
    stringBuilder.append(paramString);
    return stringBuilder.toString();
  }

  public static String cometchatLogin() {
    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder.append(getService());
    stringBuilder.append("plugins/cometchat");
    return stringBuilder.toString();
  }

  public static String commodityImages() {
    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder.append(getService());
    stringBuilder.append("getjson?task=json.commodityImages");
    return stringBuilder.toString();
  }

  public static String compareProvinceCommodity(int paramInt1, String paramString, int paramInt2) {
    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder.append(getService());
    stringBuilder.append("getjson?task=json.statNationalByCommodity&commodity_id=");
    stringBuilder.append(paramInt1);
    stringBuilder.append("&date=");
    stringBuilder.append(paramString);
    stringBuilder.append("&price_type_id=");
    stringBuilder.append(paramInt2);
    return stringBuilder.toString();
  }

  public static String compareRegencyCommodity(int paramInt1, String paramString, int paramInt2) {
    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder.append(getService());
    stringBuilder.append("?option=com_gtpihps&task=json.statRegencyByCommodity&commodity_id=");
    stringBuilder.append(paramInt1);
    stringBuilder.append("&date=");
    stringBuilder.append(paramString);
    stringBuilder.append("&price_type_id=");
    stringBuilder.append(paramInt2);
    return stringBuilder.toString();
  }

  public static String dashboardCommodity(String paramString1, String paramString2, int paramInt) {
    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder.append(getService());
    stringBuilder.append("getjson?option=com_gtpihps&task=json.statFluctuationByCommodity&commodity_id=");
    stringBuilder.append(paramString1);
    stringBuilder.append("&date=");
    stringBuilder.append(paramString2);
    stringBuilder.append("&&price_type_id=");
    stringBuilder.append(paramInt);
    return stringBuilder.toString();
  }

  public static String dashboardProvince(String paramString1, String paramString2, int paramInt) {
    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder.append(getService());
    stringBuilder.append("getjson?option=com_gtpihps&task=json.statFluctuationByProvince&province_id=");
    stringBuilder.append(paramString1);
    stringBuilder.append("&date=");
    stringBuilder.append(paramString2);
    stringBuilder.append("&&price_type_id=");
    stringBuilder.append(paramInt);
    return stringBuilder.toString();
  }

  public static String getDataProvByReg(String paramString1, String paramString2, String paramString3) {
    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder.append(getService());
    stringBuilder.append("getjson?task=json.statProvinceByRegency&regency_id=");
    stringBuilder.append(paramString1);
    stringBuilder.append("&market_id=");
    stringBuilder.append(paramString2);
    stringBuilder.append("&date=");
    stringBuilder.append(paramString3);
    return stringBuilder.toString();
  }

  public static String getLatestDate() {
    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder.append(getService());
    stringBuilder.append("getjson?option=com_gtpihps&task=json.latestDate");
    return stringBuilder.toString();
  }

  public static String getService() {
    return "http://hargapangan.id/";
  }

  public static String imageCommodityReference() {
    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder.append(getService());
    stringBuilder.append("getjson?task=json.commodityImages");
    return stringBuilder.toString();
  }

  public static String marketComodity(String paramString1, String paramString2, String paramString3, String paramString4) {
    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder.append(getService());
    stringBuilder.append("getjson?task=json.statProvinceByRegency&regency_id=");
    stringBuilder.append(paramString2);
    stringBuilder.append("&market_id=");
    stringBuilder.append(paramString3);
    stringBuilder.append("&date=");
    stringBuilder.append(paramString4);
    return stringBuilder.toString();
  }

  public static String priceHistory(String paramString1, String paramString2, String paramString3, int paramInt1, String paramString4, int paramInt2, String paramString5) {
    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder.append(getService());
    stringBuilder.append("getjson?task=json.statProvinceByCommodity&regency_id=");
    stringBuilder.append(paramString2);
    stringBuilder.append("&market_id=");
    stringBuilder.append(paramString3);
    stringBuilder.append("&commodity_id=");
    stringBuilder.append(paramInt1);
    stringBuilder.append("&date=");
    stringBuilder.append(paramString4);
    stringBuilder.append("&type=");
    stringBuilder.append(paramString5);
    stringBuilder.append("&province_id=");
    stringBuilder.append(paramString1);
    stringBuilder.append("&price_type_id=");
    stringBuilder.append(paramInt2);
    return stringBuilder.toString();
  }

  public static String provinceComodity(String paramString1, String paramString2, int paramInt) {
    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder.append(getService());
    stringBuilder.append("?option=com_gtpihps&task=json.statProvinceByRegency&date=");
    stringBuilder.append(paramString2);
    stringBuilder.append("&province_id=");
    stringBuilder.append(paramString1);
    stringBuilder.append("&price_type_id=");
    stringBuilder.append(paramInt);
    return stringBuilder.toString();
  }

  public static String regencyComodity(String paramString1, String paramString2, String paramString3, int paramInt) {
    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder.append(getService());
    stringBuilder.append("?option=com_gtpihps&task=json.statProvinceByRegency&date=");
    stringBuilder.append(paramString3);
    stringBuilder.append("&regency_id=");
    stringBuilder.append(paramString2);
    stringBuilder.append("&price_type_id=");
    stringBuilder.append(paramInt);
    return stringBuilder.toString();
  }
}

Dari hasil dekompilasi di atas, bisa terlihat bahwa terdapat beberapa endpoint pada domain hargapangan.id yang dapat digunakan untuk memperoleh data yang diinginkan. Untuk memperoleh informasi province_id, regency_id dan market_id, kita dapat mengirimkan permintaan/request ke:

http://hargapangan.id/getjson?option=com_gtpihps&task=json.references&all=1

Hasilnya berupa format JSON berisi informasi province_id, regency_id, market_id, name yang selanjutnya dapat digunakan untuk memperoleh harga pada pasar di kota pada provinsi yang diinginkan. Misalnya, untuk memperoleh harga di Pasar Modern Kab. Manokwari Papua Barat, kita dapat mengirimkan request pada tautan berikut ini:

http://hargapangan.id/getjson?task=json.statProvinceByRegency&regency_id=91&market_id=309

Hasilnya berupa data dengan tipe JSON seperti ini:

{
  "result": {
    "province_id": "34",
    "regency_id": "91",
    "market_id": "309",
    "name": "Ps. Modern Kab. Manokwari",
    "date": "2020-06-23",
    "notification": "",
    "prices": [
      {
        "id": "",
        "name": "Beras",
        "denom": "kg",
        "type": "category",
        "level": 0,
        "price": "13.350",
        "diff": "0",
        "trend": "still"
      },
      {
        "id": 1,
        "name": "Beras Kualitas Bawah I",
        "denom": "kg",
        "type": "commodity",
        "level": 1,
        "price": "12.350",
        "diff": "0",
        "trend": "still"
      },
      {
        "id": 2,
        "name": "Beras Kualitas Bawah II",
        "denom": "kg",
        "type": "commodity",
        "level": 1,
        "price": "-",
        "diff": "-",
        "trend": "unknown"
      },
      {
        "id": 3,
        "name": "Beras Kualitas Medium I",
        "denom": "kg",
        "type": "commodity",
        "level": 1,
        "price": "13.800",
        "diff": "0",
        "trend": "still"
      },
      {
        "id": 4,
        "name": "Beras Kualitas Medium II",
        "denom": "kg",
        "type": "commodity",
        "level": 1,
        "price": "12.750",
        "diff": "0",
        "trend": "still"
      },
      {
        "id": 5,
        "name": "Beras Kualitas Super I",
        "denom": "kg",
        "type": "commodity",
        "level": 1,
        "price": "14.300",
        "diff": "0",
        "trend": "still"
      },
      {
        "id": 6,
        "name": "Beras Kualitas Super II",
        "denom": "kg",
        "type": "commodity",
        "level": 1,
        "price": "13.600",
        "diff": "0",
        "trend": "still"
      },
      {
        "id": "",
        "name": "Daging Ayam",
        "denom": "kg",
        "type": "category",
        "level": 0,
        "price": "-",
        "diff": "-",
        "trend": "unknown"
      },
      {
        "id": 7,
        "name": "Daging Ayam Ras Segar",
        "denom": "kg",
        "type": "commodity",
        "level": 1,
        "price": "41.000",
        "diff": "0",
        "trend": "still"
      },
      {
        "id": "",
        "name": "Daging Sapi",
        "denom": "kg",
        "type": "category",
        "level": 0,
        "price": "-",
        "diff": "-",
        "trend": "unknown"
      },
      {
        "id": 8,
        "name": "Daging Sapi Kualitas 1",
        "denom": "kg",
        "type": "commodity",
        "level": 1,
        "price": "134.000",
        "diff": "0",
        "trend": "still"
      },
      {
        "id": 9,
        "name": "Daging Sapi Kualitas 2",
        "denom": "kg",
        "type": "commodity",
        "level": 1,
        "price": "130.000",
        "diff": "0",
        "trend": "still"
      },
      {
        "id": "",
        "name": "Telur Ayam",
        "denom": "kg",
        "type": "category",
        "level": 0,
        "price": "-",
        "diff": "-",
        "trend": "unknown"
      },
      {
        "id": 10,
        "name": "Telur Ayam Ras Segar\r\n",
        "denom": "kg",
        "type": "commodity",
        "level": 1,
        "price": "45.600",
        "diff": "0",
        "trend": "still"
      },
      {
        "id": "",
        "name": "Bawang Merah",
        "denom": "kg",
        "type": "category",
        "level": 0,
        "price": "-",
        "diff": "-",
        "trend": "unknown"
      },
      {
        "id": 11,
        "name": "Bawang Merah Ukuran Sedang",
        "denom": "kg",
        "type": "commodity",
        "level": 1,
        "price": "84.000",
        "diff": "0",
        "trend": "still"
      },
      {
        "id": "",
        "name": "Bawang Putih",
        "denom": "kg",
        "type": "category",
        "level": 0,
        "price": "-",
        "diff": "-",
        "trend": "unknown"
      },
      {
        "id": 12,
        "name": "Bawang Putih Ukuran Sedang",
        "denom": "kg",
        "type": "commodity",
        "level": 1,
        "price": "63.250",
        "diff": "0",
        "trend": "still"
      },
      {
        "id": "",
        "name": "Cabai Merah",
        "denom": "kg",
        "type": "category",
        "level": 0,
        "price": "-",
        "diff": "-",
        "trend": "unknown"
      },
      {
        "id": 13,
        "name": "Cabai Merah Besar",
        "denom": "kg",
        "type": "commodity",
        "level": 1,
        "price": "57.500",
        "diff": "0",
        "trend": "still"
      },
      {
        "id": 14,
        "name": "Cabai Merah Keriting ",
        "denom": "kg",
        "type": "commodity",
        "level": 1,
        "price": "36.000",
        "diff": "0",
        "trend": "still"
      },
      {
        "id": "",
        "name": "Cabai Rawit",
        "denom": "kg",
        "type": "category",
        "level": 0,
        "price": "-",
        "diff": "-",
        "trend": "unknown"
      },
      {
        "id": 15,
        "name": "Cabai Rawit Hijau",
        "denom": "kg",
        "type": "commodity",
        "level": 1,
        "price": "-",
        "diff": "-",
        "trend": "unknown"
      },
      {
        "id": 16,
        "name": "Cabai Rawit Merah",
        "denom": "kg",
        "type": "commodity",
        "level": 1,
        "price": "78.500",
        "diff": "0",
        "trend": "still"
      },
      {
        "id": "",
        "name": "Minyak Goreng",
        "denom": "kg",
        "type": "category",
        "level": 0,
        "price": "-",
        "diff": "-",
        "trend": "unknown"
      },
      {
        "id": 17,
        "name": "Minyak Goreng Curah",
        "denom": "kg",
        "type": "commodity",
        "level": 1,
        "price": "-",
        "diff": "-",
        "trend": "unknown"
      },
      {
        "id": 18,
        "name": "Minyak Goreng Kemasan Bermerk 1",
        "denom": "kg",
        "type": "commodity",
        "level": 1,
        "price": "17.750",
        "diff": "0",
        "trend": "still"
      },
      {
        "id": 19,
        "name": "Minyak Goreng Kemasan Bermerk 2",
        "denom": "kg",
        "type": "commodity",
        "level": 1,
        "price": "12.750",
        "diff": "0",
        "trend": "still"
      },
      {
        "id": "",
        "name": "Gula Pasir",
        "denom": "kg",
        "type": "category",
        "level": 0,
        "price": "-",
        "diff": "-",
        "trend": "unknown"
      },
      {
        "id": 20,
        "name": "Gula Pasir Kualitas Premium",
        "denom": "kg",
        "type": "commodity",
        "level": 1,
        "price": "21.000",
        "diff": "0",
        "trend": "still"
      },
      {
        "id": 21,
        "name": "Gula Pasir Lokal",
        "denom": "kg",
        "type": "commodity",
        "level": 1,
        "price": "13.500",
        "diff": "0",
        "trend": "still"
      }
    ]
  },
  "message": "",
  "status": ""
}

Dari sini, kita dapat membuat script yang melakukan request untuk memperoleh data yang kita inginkan dan mengolah data tersebut. Sekian jurnal singkat kali ini, semoga bermanfaat. Terima kasih kepada Allah SWT, dan Anda yang telah membaca jurnal ini.