├── api ├── apiDocs.py ├── bpjsInquiries.py ├── pdamInquiries.py ├── postpaidInquiries.py └── prepaidInquiries.py ├── image └── img.png ├── readme.md ├── requirements.txt ├── server.py ├── src ├── ScraperAPI.py ├── bpjsKesehatanInquiries.py ├── pdamInquiries.py ├── postpaidInquiries.py └── prepaidInquiries.py └── views └── index.html /api/apiDocs.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | from flask_restx import Api, Resource 3 | from src.pdamInquiries import pdamInquiries 4 | from src.prepaidInquiries import prepaidInquiries 5 | from src.postpaidInquiries import postpaidInquiries 6 | from src.bpjsKesehatanInquiries import bpjsKesehatanInquiries 7 | 8 | api_documentation = Api( 9 | version='1.0', 10 | title='API Cek 📑🗓', 11 | doc='/api/docs', 12 | description='API Cek 📑🗓 adalah Simple API untuk mengecek tagihan PDAM, listrik prabayar, listrik pascabayar, dan BPJS Kesehatan' 13 | ) 14 | 15 | index_doc = api_documentation.namespace( 16 | 'index', 17 | description='digunakan untuk mengecek status API', 18 | path='/api' 19 | ) 20 | pdam_doc = api_documentation.namespace( 21 | 'pdamInquiries', 22 | description='digunakan untuk mengecek tagihan PDAM', 23 | path='/api/pdamInquiries' 24 | ) 25 | prepaid_doc = api_documentation.namespace( 26 | 'prepaidInquiries', 27 | description='digunakan untuk mengecek tagihan listrik prabayar', 28 | path='/api/prepaidInquiries' 29 | ) 30 | bpjs_doc = api_documentation.namespace( 31 | 'bpjsKesehatanInquiries', 32 | description='digunakan untuk mengecek tagihan BPJS Kesehatan', 33 | path='/api/bpjsKesehatanInquiries' 34 | ) 35 | postpaid_doc = api_documentation.namespace( 36 | 'postpaidInquiries', 37 | description='digunakan untuk mengecek tagihan listrik pascabayar', 38 | path='/api/postpaidInquiries' 39 | ) 40 | 41 | 42 | @index_doc.route('/') 43 | class Index(Resource): 44 | def get(self): 45 | return { 46 | "status": True, 47 | "message": "API Cek 📑🗓 is running", 48 | "datetime": datetime.now().strftime("%Y-%m-%d %H:%M:%S") 49 | } 50 | 51 | 52 | @prepaid_doc.route('/') 53 | @postpaid_doc.response(400, 'Customer number cannot be empty') 54 | class PrepaidInquiries(Resource): 55 | def get(self): 56 | return { 57 | "status": False, 58 | "message": "Customer number cannot be empty", 59 | }, 400 60 | 61 | 62 | @prepaid_doc.route('/') 63 | class PrepaidInquiries(Resource): 64 | def get(self, customer_number): 65 | 66 | try: 67 | return prepaidInquiries(customer_number)._get_data() 68 | 69 | except Exception: 70 | 71 | return { 72 | "status": False, 73 | "message": "Server error" 74 | }, 500 75 | 76 | 77 | @postpaid_doc.route('/') 78 | @postpaid_doc.response(400, 'Customer number cannot be empty') 79 | class PostpaidInquiries(Resource): 80 | def get(self): 81 | return { 82 | "status": False, 83 | "message": "Customer number cannot be empty", 84 | }, 400 85 | 86 | 87 | @postpaid_doc.route('/') 88 | class PostpaidInquiries(Resource): 89 | def get(self, customer_number): 90 | 91 | try: 92 | return postpaidInquiries(customer_number)._get_data() 93 | 94 | except Exception: 95 | 96 | return { 97 | "status": False, 98 | "message": "Server error" 99 | }, 500 100 | 101 | 102 | @pdam_doc.route('/') 103 | @pdam_doc.response(400, 'Customer number cannot be empty') 104 | class PdamInquiries(Resource): 105 | def get(self): 106 | return { 107 | "status": False, 108 | "message": "Customer number cannot be empty", 109 | }, 400 110 | 111 | 112 | @pdam_doc.route('/') 113 | class PdamInquiries(Resource): 114 | 115 | def get(self, customer_number): 116 | 117 | try: 118 | return pdamInquiries(customer_number)._get_operators() 119 | 120 | except Exception: 121 | 122 | return { 123 | "status": False, 124 | "message": "Server error" 125 | }, 500 126 | 127 | 128 | @pdam_doc.route('//') 129 | class PdamInquiries(Resource): 130 | 131 | def get(self, customer_number, operator): 132 | 133 | try: 134 | return pdamInquiries(customer_number)._get_data(operator) 135 | 136 | except Exception: 137 | 138 | return { 139 | "status": False, 140 | "message": "Server error" 141 | }, 500 142 | 143 | 144 | @bpjs_doc.route('/') 145 | @bpjs_doc.response(400, 'Customer number cannot be empty') 146 | class BpjsKesehatanInquiries(Resource): 147 | def get(self): 148 | return { 149 | "status": False, 150 | "message": "Customer number cannot be empty", 151 | }, 400 152 | 153 | 154 | @bpjs_doc.route('/') 155 | class BpjsKesehatanInquiries(Resource): 156 | def get(self, customer_number): 157 | 158 | try: 159 | 160 | return bpjsKesehatanInquiries(customer_number)._get_data() 161 | 162 | except Exception: 163 | 164 | return { 165 | "status": False, 166 | "message": "Server error" 167 | }, 500 168 | -------------------------------------------------------------------------------- /api/bpjsInquiries.py: -------------------------------------------------------------------------------- 1 | from flask import blueprints 2 | from src.bpjsKesehatanInquiries import bpjsKesehatanInquiries 3 | 4 | bpjsKesehatanInquiriess = blueprints.Blueprint('bpjsKesehatanInquiriess', __name__) 5 | 6 | 7 | @bpjsKesehatanInquiriess.route('/api/bpjsKesehatanInquiries/', methods=['GET']) 8 | def index(): 9 | return { 10 | "status": False, 11 | "message": "Customer number cannot be empty", 12 | }, 404 13 | 14 | 15 | @bpjsKesehatanInquiriess.route('/api/bpjsKesehatanInquiries/', methods=['GET']) 16 | def get_data(customer_number): 17 | try: 18 | 19 | return bpjsKesehatanInquiries(customer_number)._get_data() 20 | 21 | except Exception: 22 | 23 | return { 24 | "status": False, 25 | "message": "Server error" 26 | }, 500 27 | -------------------------------------------------------------------------------- /api/pdamInquiries.py: -------------------------------------------------------------------------------- 1 | from flask import blueprints 2 | from src.pdamInquiries import pdamInquiries 3 | 4 | pdamInquiriess = blueprints.Blueprint('pdamInquiriess', __name__) 5 | 6 | 7 | @pdamInquiriess.route('/api/pdamInquiries/', methods=['GET']) 8 | def index(): 9 | return { 10 | "status": False, 11 | "message": "Customer number cannot be empty", 12 | }, 404 13 | 14 | 15 | @pdamInquiriess.route('/api/pdamInquiries//', methods=['GET']) 16 | def get_operators(customer_number): 17 | try: 18 | return pdamInquiries(customer_number)._get_operators() 19 | 20 | except Exception: 21 | 22 | return { 23 | "status": False, 24 | "message": "Server error" 25 | }, 500 26 | 27 | 28 | @pdamInquiriess.route('/api/pdamInquiries//', methods=['GET']) 29 | def get_data(customer_number, operator_id): 30 | try: 31 | return pdamInquiries(customer_number)._get_data(operator_id) 32 | 33 | except Exception: 34 | 35 | return { 36 | "status": False, 37 | "message": "Server error" 38 | }, 500 39 | -------------------------------------------------------------------------------- /api/postpaidInquiries.py: -------------------------------------------------------------------------------- 1 | from flask import blueprints 2 | from src.postpaidInquiries import postpaidInquiries 3 | 4 | postpaidInquiriess = blueprints.Blueprint('postpaidInquiriess', __name__) 5 | 6 | 7 | @postpaidInquiriess.route('/api/postpaidInquiries/', methods=['GET']) 8 | def index(): 9 | return { 10 | "status": False, 11 | "message": "Customer number cannot be empty", 12 | }, 404 13 | 14 | 15 | @postpaidInquiriess.route('/api/postpaidInquiries/', methods=['GET']) 16 | def get_data(customer_number): 17 | try: 18 | return postpaidInquiries(customer_number)._get_data() 19 | 20 | except Exception: 21 | 22 | return { 23 | "status": False, 24 | "message": "Server error" 25 | }, 500 26 | -------------------------------------------------------------------------------- /api/prepaidInquiries.py: -------------------------------------------------------------------------------- 1 | from flask import blueprints 2 | from src.prepaidInquiries import prepaidInquiries 3 | 4 | prepaidInquiriess = blueprints.Blueprint('prepaidInquiriess', __name__) 5 | 6 | 7 | @prepaidInquiriess.route('/api/prepaidInquiries/', methods=['GET']) 8 | def index(): 9 | return { 10 | "status": False, 11 | "message": "Customer number cannot be empty" 12 | }, 404 13 | 14 | 15 | @prepaidInquiriess.route('/api/prepaidInquiries/', methods=['GET']) 16 | def get_data(customer_number): 17 | try: 18 | return prepaidInquiries(customer_number)._get_data() 19 | 20 | except Exception: 21 | 22 | return { 23 | "status": False, 24 | "message": "Server error" 25 | }, 500 26 | -------------------------------------------------------------------------------- /image/img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandrocods/API-Cek/f23824757eb0613bc9b62622867609732d7bb61c/image/img.png -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # API Cek 📑🗓 2 | 3 | "Cek tagihan" adalah sebuah istilah yang merujuk pada proses memeriksa jumlah uang yang harus dibayarkan oleh seseorang 4 | atas layanan atau produk yang telah diberikan oleh pihak lain. Biasanya, tagihan ini berisi rincian mengenai jenis 5 | layanan atau produk yang digunakan, jumlah yang harus dibayar, dan tanggal jatuh tempo pembayaran. Dengan melakukan "cek 6 | tagihan", seseorang dapat memastikan bahwa tagihan yang diterima sesuai dengan layanan atau produk yang telah digunakan. 7 | Dibuat menggunakan bahasa pemrograman Python3 dan metode scraping. Scraping adalah teknik ekstraksi data yang dilakukan 8 | dengan cara mengambil informasi dari sebuah website bukalapak secara otomatis, menggunakan library atau framework 9 | tertentu 10 | 11 | Project ini dibuat untuk tujuan pengembangan dan pembelajaran 12 | 13 | ## 📚 Daftar Isi 14 | 15 | - [Library](#library) 16 | - [Fitur](#fitur) 17 | - [Cara Penggunaan](#cara-penggunaan) 18 | - [Refrensi](#refrensi) 19 | - [Prepaid Inquiries](#prepaid-inquiries) 20 | - [Postpaid Inquiries](#postpaid-inquiries) 21 | - [PDAM Inquiries](#pdam-inquiries) 22 | - [BPJS Kesehatan Inquiries](#bpjs-kesehatan-inquiries) 23 | 24 | - [Rest API](#rest-api) 25 | - [Deployment](#deployment) 26 | - [Web App](#web-app) 27 | 28 | ## Library 29 | 30 | - [Flask](https://pypi.org/project/Flask/) 31 | - [Requests](https://pypi.org/project/requests/) 32 | - [Flask-cors](https://pypi.org/project/Flask-Cors/) 33 | - [Flask-restx](https://pypi.org/project/flask-restx/) 34 | - [Beautifulsoup4](https://pypi.org/project/beautifulsoup4/) 35 | - [Fake_useragent](https://pypi.org/project/fake-useragent/) 36 | - [Requests-toolbelt](https://pypi.org/project/requests-toolbelt/) 37 | 38 | ## Fitur 39 | 40 | | Nama | Status | 41 | |-----------------------------------------|--------| 42 | | prepaidInquiries ( Token Listrik ) | ✅ | 43 | | postpaidInquiries ( Tagihan Listrik ) | ✅ | 44 | | pdamInquiries ( Tagihan PDAM ) | ✅ | 45 | | bpjsKesehatanInquiries ( Tagihan BPJS ) | ✅ | 46 | | Rest API | ✅ | 47 | | Rest API Documentation | ✅ | 48 | | Web App | ✅ | 49 | 50 | ## Cara Penggunaan 51 | 52 | library ini dapat digunakan secara langsung dengan mengimport file sesuai dengan fitur yang diinginkan 53 | yang terdapat pada folder [src](https://github.com/sandrocods/API-Cek/tree/master/src) 54 | 55 | ```python 56 | # Import library untuk mengecek tagihan listrik prabayar 57 | from src.prepaidInquiries import prepaidInquiries 58 | 59 | # panggil class prepaidInquiries dan method _get_data() 60 | # parameter pertama adalah customer_number (nomor pelanggan) 61 | 62 | print( 63 | prepaidInquiries( 64 | customer_number="xxxxxxxxxxx" 65 | )._get_data() 66 | ) 67 | 68 | # contoh output jika berhasil 69 | # { 70 | # "status": True, 71 | # "customer_number": "xxxxxx", 72 | # "customer_name": "x xxxx xxxxxx", 73 | # "segmentation": "R1", 74 | # "power": 2200 75 | # } 76 | 77 | # contoh output jika gagal 78 | # { 79 | # "status": False, 80 | # "customer_number": "xxxxxx" 81 | # } 82 | ``` 83 | 84 | ## Refrensi 85 | 86 | Berikut adalah contoh output dan parameter dari beberapa method yang terdapat pada library ini 87 | 88 | ### Prepaid Inquiries 89 | 90 | Prepaid Inquiries adalah sebuah class yang digunakan untuk mengecek tagihan listrik prabayar 91 | 92 | | Parameter | Tipe Data | Keterangan | 93 | |-----------------|-----------|-----------------| 94 | | customer_number | String | Nomor pelanggan | 95 | 96 | Contoh output jika berhasil 97 | 98 | ```json 99 | { 100 | "status": true, 101 | "customer_number": "xxxxxx", 102 | "customer_name": "x xxxx xxxxxx", 103 | "segmentation": "R1", 104 | "power": 2200 105 | } 106 | ``` 107 | 108 | Contoh output jika gagal 109 | 110 | ```json 111 | { 112 | "status": false, 113 | "customer_number": "xxxxxx" 114 | } 115 | ``` 116 | 117 | ### Postpaid Inquiries 118 | 119 | Postpaid Inquiries adalah sebuah class yang digunakan untuk mengecek tagihan listrik pascabayar 120 | 121 | | Parameter | Tipe Data | Keterangan | 122 | |-----------------|-----------|-----------------| 123 | | customer_number | String | Nomor pelanggan | 124 | 125 | Contoh output jika berhasil 126 | 127 | ```json 128 | { 129 | "status": true, 130 | "customer_number": "xxxxxx", 131 | "customer_name": "xxxxx xxxxxx", 132 | "segmentation": "R1", 133 | "power": 450, 134 | "period": [ 135 | "2023-03-01" 136 | ], 137 | "stand_meter": "00015338 - 00015445", 138 | "amount": 52230 139 | } 140 | ``` 141 | 142 | Contoh output jika gagal 143 | 144 | ```json 145 | { 146 | "status": false, 147 | "customer_number": "xxxxxx", 148 | "message": "Nomor tidak terdaftar" 149 | } 150 | ``` 151 | 152 | ### PDAM Inquiries 153 | 154 | PDAM Inquiries adalah sebuah class yang digunakan untuk mengecek tagihan PDAM 155 | 156 | | Parameter | Tipe Data | Keterangan | 157 | |-----------------|-----------|-----------------| 158 | | customer_number | String | Nomor pelanggan | 159 | | operator_id | String | ID operator | 160 | 161 | Contoh output jika berhasil 162 | 163 | ```json 164 | { 165 | "status": true, 166 | "customer_number": "xxxxxx", 167 | "customer_name": "xxxxx xxxxxx", 168 | "bills": [ 169 | { 170 | "usage": "0000013780", 171 | "start_meter": 486000, 172 | "end_meter": 499780, 173 | "address": "-", 174 | "admin_fee": 3000, 175 | "penalty_fee": 5000, 176 | "bill_period": "2023-02-01", 177 | "amount": 73156, 178 | "cubication": "486000-499780" 179 | } 180 | ] 181 | } 182 | ``` 183 | 184 | Contoh output jika gagal 185 | 186 | ```json 187 | { 188 | "status": false, 189 | "customer_number": "xxxxxx", 190 | "message": "Tagihan tidak ditemukan atau sudah dibayar" 191 | } 192 | ``` 193 | 194 | Mengambil ID operator 195 | 196 | Data telah di sort berdasarkan group 197 | 198 | ```python 199 | from src.pdamInquiries import pdamInquiries 200 | 201 | print( 202 | pdamInquiries("xxxx")._get_operators() 203 | ) 204 | 205 | # Output 206 | # { 207 | # "status": true, 208 | # "data": [ 209 | # { 210 | # "id": 471, 211 | # "name": "PDAM Kota Banda Aceh", 212 | # "group": "Aceh" 213 | # }, 214 | # { 215 | # "id": 486, 216 | # "name": "PDAM Kab. Aceh Barat", 217 | # "group": "Aceh" 218 | # }, 219 | # .. dan seterusnya 220 | # ] 221 | # } 222 | ``` 223 | 224 | ### BPJS Kesehatan Inquiries 225 | 226 | BPJS Kesehatan Inquiries adalah sebuah class yang digunakan untuk mengecek tagihan BPJS Kesehatan 227 | 228 | | Parameter | Tipe Data | Keterangan | 229 | |-----------------|-----------|-----------------| 230 | | customer_number | String | Nomor pelanggan | 231 | 232 | Contoh output jika berhasil 233 | 234 | ```json 235 | { 236 | "status": true, 237 | "customer_number": "xxxxxx", 238 | "customer_name": "xxxxx xxxxxx", 239 | "count_family_members": 4, 240 | "amount": 142500 241 | } 242 | ``` 243 | 244 | Contoh output jika gagal 245 | 246 | ```json 247 | { 248 | "status": false, 249 | "customer_number": "0000003137160351", 250 | "message": "Tagihan tidak ditemukan atau sudah dibayar" 251 | } 252 | ``` 253 | 254 | ## Rest api 255 | 256 | Jika anda ingin melakukan request secara langsung, anda dapat menggunakan rest api yang telah disediakan dengan 257 | menggunakan Swagger API Documentation berikut 258 | 259 | ##### [Swagger API Documentation](http://47.88.53.4:1111/api/docs) 260 | 261 | Untuk menggunakan rest api, anda harus menggunakan `BASE_URL` berikut ini 262 | 263 | ```text 264 | BASE_URL = http://47.88.53.4:1111/api/ 265 | ``` 266 | 267 | Berikut adalah refrensi rest api yang tersedia pada aplikasi ini 268 | 269 | ### [Prepaid Inquiries](http://47.88.53.4:1111/api/prepaidInquiries/xxxxxxxxxxx) 270 | 271 | ```http 272 | GET /prepaidInquiries/{customer_number} 273 | ``` 274 | 275 | | Parameter | Tipe Data | Keterangan | 276 | |-----------------|-----------|-----------------| 277 | | customer_number | String | Nomor pelanggan | 278 | 279 | ### [Postpaid Inquiries](http://47.88.53.4:1111/api/postpaidInquiries/xxxxxxxxxxx) 280 | 281 | ```http 282 | GET /postpaidInquiries/{customer_number} 283 | ``` 284 | 285 | | Parameter | Tipe Data | Keterangan | 286 | |-----------------|-----------|-----------------| 287 | | customer_number | String | Nomor pelanggan | 288 | 289 | ### [Pdam Inquiries](http://47.88.53.4:1111/api/pdamInquiries/xxxxxxxxxxx) 290 | 291 | ```http 292 | GET /pdamInquiries/{customer_number}/{operator_id} 293 | ``` 294 | 295 | | Parameter | Tipe Data | Keterangan | 296 | |-----------------|-----------|-----------------| 297 | | customer_number | String | Nomor pelanggan | 298 | | operator_id | String | ID operator | 299 | 300 | ### [BPJS Kesehatan Inquiries](http://47.88.53.4:1111/api/bpjsKesehatanInquiries/xxxxxxxxxxx) 301 | 302 | ```http 303 | GET /bpjsKesehatanInquiries/{customer_number} 304 | ``` 305 | 306 | | Parameter | Tipe Data | Keterangan | 307 | |-----------------|-----------|-----------------| 308 | | customer_number | String | Nomor pelanggan | 309 | 310 | ## Deployment 311 | 312 | Untuk melakukan deploy ke server production pada project ini menggunakan 313 | library [waitress](https://docs.pylonsproject.org/projects/waitress/en/stable/) 314 | 315 | langkah-langkahnya sebagai berikut : 316 | 317 | 1. Git clone repository ini 318 | 319 | ```bash 320 | git clone https://github.com/sandrocods/API-Cek 321 | ``` 322 | 323 | 2. Masuk ke folder API-Cek 324 | 325 | ```bash 326 | cd API-Cek 327 | ``` 328 | 329 | 3. Install requirements 330 | 331 | ```bash 332 | pip3 install -r requirements.txt 333 | ``` 334 | 335 | 4. install waitress 336 | 337 | ```bash 338 | pip3 install waitress 339 | ``` 340 | 341 | 5. Jalankan waitress dengan command berikut 342 | 343 | ```bash 344 | waitress-serve --host 127.0.0.1 --port 5000 server:app 345 | ``` 346 | 347 | Jika berhasil maka akan muncul output seperti berikut di terminal 348 | 349 | ```bash 350 | INFO:waitress:Serving on http://127.0.0.0:5000 351 | ``` 352 | 353 | ## Web App 354 | Untuk menggunakan web app yang telah didesain untuk mempermudah penggunaan API ini, anda dapat mengunjungi link berikut ini [Web App](http://47.88.53.4:1111/apps) 355 | 356 | ![img.png](image/img.png) 357 | 358 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | Flask 2 | requests 3 | beautifulsoup4 4 | fake_useragent 5 | flask-restx 6 | flask-cors -------------------------------------------------------------------------------- /server.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | from flask_cors import CORS 3 | from flask import Flask, render_template, request 4 | from api.apiDocs import api_documentation 5 | from api.pdamInquiries import pdamInquiriess 6 | from api.prepaidInquiries import prepaidInquiriess 7 | from api.postpaidInquiries import postpaidInquiriess 8 | from api.bpjsInquiries import bpjsKesehatanInquiriess 9 | 10 | app = Flask(__name__, template_folder='views') 11 | 12 | # Init CORS 13 | CORS(app, resources={r"/*": {"origins": "*"}}) 14 | 15 | # Init API Docs 16 | api_documentation.init_app(app) 17 | 18 | # Route Pdam Inquiries 19 | app.register_blueprint(pdamInquiriess) 20 | 21 | # Route Prepaid Inquiries 22 | app.register_blueprint(prepaidInquiriess) 23 | 24 | # Route Postpaid Inquiries 25 | app.register_blueprint(postpaidInquiriess) 26 | 27 | # Route BPJS Kesehatan Inquiries 28 | app.register_blueprint(bpjsKesehatanInquiriess) 29 | 30 | 31 | @app.route('/', methods=['GET']) 32 | @app.route('/api', methods=['GET']) 33 | @app.route('/api/', methods=['GET']) 34 | def index(): 35 | return { 36 | "status": True, 37 | "message": "API Cek 📑🗓 is running", 38 | "datetime": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") 39 | }, 200 40 | 41 | 42 | @app.route('/apps', methods=['GET']) 43 | def apps(): 44 | return render_template('index.html') 45 | 46 | 47 | @app.errorhandler(404) 48 | def not_found(e): 49 | if request.path == '/': 50 | return { 51 | "status": True, 52 | "message": "API Cek 📑🗓 is running", 53 | "datetime": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") 54 | }, 200 55 | else: 56 | return { 57 | "status": False, 58 | "message": "API Path Not Found" 59 | }, 404 60 | -------------------------------------------------------------------------------- /src/ScraperAPI.py: -------------------------------------------------------------------------------- 1 | import json 2 | import requests 3 | from bs4 import BeautifulSoup 4 | from fake_useragent import UserAgent 5 | 6 | 7 | class ScraperAPI: 8 | BASE_URL = "https://www.bukalapak.com/" 9 | API_URL = "https://api.bukalapak.com/" 10 | 11 | def __init__(self): 12 | self.access_token = None 13 | 14 | def _get_access_token(self, url): 15 | try: 16 | ua = UserAgent( 17 | browsers=['firefox', 'chrome', 'edge'] 18 | ) 19 | response = requests.get( 20 | url=self.BASE_URL + url, 21 | headers={ 22 | "User-Agent": ua.random 23 | } 24 | ) 25 | soup = BeautifulSoup(response.text, "html.parser") 26 | access_token = soup.findAll("script")[3].text. \ 27 | replace("localStorage.setItem('bl_token', '", "").replace("');", "") 28 | 29 | self.access_token = json.loads(access_token)['access_token'] 30 | return self.access_token 31 | 32 | except IndexError: 33 | return None 34 | 35 | except json.decoder.JSONDecodeError: 36 | return None 37 | 38 | except requests.exceptions.ConnectionError: 39 | return None 40 | -------------------------------------------------------------------------------- /src/bpjsKesehatanInquiries.py: -------------------------------------------------------------------------------- 1 | import json 2 | import requests 3 | from src.ScraperAPI import ScraperAPI 4 | from datetime import datetime 5 | 6 | 7 | class bpjsKesehatanInquiries(ScraperAPI): 8 | 9 | def __init__(self, customer_number): 10 | super().__init__() 11 | self.customer_number = customer_number 12 | if len(self.customer_number) < 16: 13 | raise Exception("Customer number must be 16 digits") 14 | elif self.customer_number is None: 15 | raise Exception("Customer number cannot be empty") 16 | 17 | self.access_token = ScraperAPI()._get_access_token("bpjs-kesehatan") 18 | if self.access_token is None: 19 | raise Exception("Failed to get access token") 20 | 21 | def _get_data(self): 22 | response = None 23 | try: 24 | response = requests.post( 25 | url=ScraperAPI.API_URL + "bpjs-kesehatan/inquiries", 26 | params={ 27 | "access_token": self.access_token, 28 | }, 29 | headers={ 30 | "Content-Type": "application/json", 31 | "Accept": "application/json", 32 | }, 33 | json={ 34 | "paid_until": { 35 | "month": int(datetime.now().strftime("%m")) + 1, 36 | "year": datetime.now().strftime("%Y"), 37 | }, 38 | "customer_number": self.customer_number, 39 | } 40 | ) 41 | 42 | return { 43 | "status": True, 44 | "customer_number": self.customer_number, 45 | "customer_name": response.json()['data']['customer_name'], 46 | "count_family_members": response.json()['data']['family_member_count'], 47 | "amount": response.json()['data']['amount'] 48 | } 49 | 50 | except KeyError: 51 | return { 52 | "status": False, 53 | "customer_number": self.customer_number, 54 | "message": response.json()['errors'][0]['message'], 55 | } 56 | 57 | except json.decoder.JSONDecodeError: 58 | return None 59 | 60 | except requests.exceptions.ConnectionError: 61 | return None 62 | 63 | except requests.exceptions.ReadTimeout: 64 | return None 65 | -------------------------------------------------------------------------------- /src/pdamInquiries.py: -------------------------------------------------------------------------------- 1 | import json 2 | import requests 3 | from src.ScraperAPI import ScraperAPI 4 | 5 | 6 | class pdamInquiries(ScraperAPI): 7 | 8 | def __init__(self, customer_number): 9 | super().__init__() 10 | self.customer_number = customer_number 11 | if self.customer_number is None: 12 | raise Exception("Customer number cannot be empty") 13 | 14 | self.access_token = ScraperAPI()._get_access_token("listrik-pln/tagihan-listrik") 15 | if self.access_token is None: 16 | raise Exception("Failed to get access token") 17 | 18 | def _get_operators(self): 19 | try: 20 | response = requests.get( 21 | url=ScraperAPI.API_URL + "pdam/operators", 22 | params={ 23 | "access_token": self.access_token, 24 | }, 25 | headers={ 26 | "Content-Type": "application/json", 27 | "Accept": "application/json", 28 | } 29 | ) 30 | 31 | if len(response.json()['data']) is not None: 32 | 33 | build_data = [] 34 | for data in response.json()['data']: 35 | build_data.append({ 36 | "id": data['id'], 37 | "name": data['name'], 38 | "group": data['group'], 39 | }) 40 | 41 | build_data = sorted(build_data, key=lambda k: k['group']) 42 | 43 | return { 44 | "status": True, 45 | "data": build_data, 46 | } 47 | 48 | except KeyError: 49 | return { 50 | "status": False, 51 | } 52 | 53 | except json.decoder.JSONDecodeError: 54 | return None 55 | 56 | def _get_data(self, operator_id): 57 | response = None 58 | if operator_id is None: 59 | raise Exception("Operator ID cannot be empty") 60 | try: 61 | response = requests.post( 62 | url=ScraperAPI.API_URL + "pdam/inquiries", 63 | params={ 64 | "access_token": self.access_token, 65 | }, 66 | headers={ 67 | "Content-Type": "application/json", 68 | "Accept": "application/json", 69 | }, 70 | json={ 71 | "operator_id": operator_id, 72 | "customer_number": self.customer_number, 73 | } 74 | ) 75 | 76 | return { 77 | "status": True, 78 | "customer_number": self.customer_number, 79 | "customer_name": response.json()['data']['customer_name'], 80 | "bills": response.json()['data']['bills'], 81 | 82 | } 83 | 84 | except KeyError: 85 | return { 86 | "status": False, 87 | "customer_number": self.customer_number, 88 | "message": response.json()['errors'][0]['message'], 89 | } 90 | 91 | except json.decoder.JSONDecodeError: 92 | return None 93 | 94 | except requests.exceptions.ConnectionError: 95 | return None 96 | 97 | except requests.exceptions.ReadTimeout: 98 | return None 99 | -------------------------------------------------------------------------------- /src/postpaidInquiries.py: -------------------------------------------------------------------------------- 1 | import json 2 | import requests 3 | from src.ScraperAPI import ScraperAPI 4 | 5 | 6 | class postpaidInquiries(ScraperAPI): 7 | 8 | def __init__(self, customer_number): 9 | super().__init__() 10 | self.customer_number = customer_number 11 | if len(self.customer_number) < 12 or len(self.customer_number) > 12: 12 | raise Exception("Customer number must be 12 digits") 13 | elif self.customer_number is None: 14 | raise Exception("Customer number cannot be empty") 15 | 16 | self.access_token = ScraperAPI()._get_access_token("listrik-pln/tagihan-listrik") 17 | if self.access_token is None: 18 | raise Exception("Failed to get access token") 19 | 20 | def _get_data(self): 21 | try: 22 | response = None 23 | response = requests.post( 24 | url=ScraperAPI.API_URL + "electricities/postpaid-inquiries", 25 | params={ 26 | "access_token": self.access_token, 27 | }, 28 | headers={ 29 | "Content-Type": "application/json", 30 | "Accept": "application/json", 31 | }, 32 | json={ 33 | "customer_number": self.customer_number, 34 | } 35 | ) 36 | 37 | return { 38 | "status": True, 39 | "customer_number": self.customer_number, 40 | "customer_name": response.json()['data']['customer_name'], 41 | "segmentation": response.json()['data']['segmentation'], 42 | "power": response.json()['data']['power'], 43 | "period": response.json()['data']['period'], 44 | "stand_meter": response.json()['data']['stand_meter'], 45 | "amount": response.json()['data']['amount'], 46 | } 47 | 48 | 49 | except KeyError: 50 | return { 51 | "status": False, 52 | "customer_number": self.customer_number, 53 | "message": response.json()['errors'][0]['message'], 54 | } 55 | 56 | except json.decoder.JSONDecodeError: 57 | return None 58 | 59 | except requests.exceptions.ConnectionError: 60 | return None 61 | 62 | except requests.exceptions.ReadTimeout: 63 | return None 64 | -------------------------------------------------------------------------------- /src/prepaidInquiries.py: -------------------------------------------------------------------------------- 1 | import json 2 | import requests 3 | from src.ScraperAPI import ScraperAPI 4 | 5 | 6 | class prepaidInquiries(ScraperAPI): 7 | 8 | def __init__(self, customer_number): 9 | super().__init__() 10 | self.customer_number = customer_number 11 | if self.customer_number is None: 12 | raise Exception("Customer number cannot be empty") 13 | 14 | self.access_token = ScraperAPI()._get_access_token("listrik-pln/token-listrik") 15 | if self.access_token is None: 16 | raise Exception("Failed to get access token") 17 | 18 | def _get_data(self): 19 | try: 20 | response = requests.post( 21 | url=ScraperAPI.API_URL + "electricities/prepaid-inquiries", 22 | params={ 23 | "access_token": self.access_token, 24 | }, 25 | headers={ 26 | "Content-Type": "application/json", 27 | "Accept": "application/json", 28 | }, 29 | json={ 30 | "customer_number": self.customer_number, 31 | "product_id": 0, 32 | } 33 | ) 34 | 35 | return { 36 | "status": True, 37 | "customer_number": self.customer_number, 38 | "customer_name": response.json()['data']['customer_name'], 39 | "segmentation": response.json()['data']['segmentation'], 40 | "power": response.json()['data']['power'], 41 | } 42 | except KeyError: 43 | return { 44 | "status": False, 45 | "customer_number": self.customer_number, 46 | } 47 | 48 | except json.decoder.JSONDecodeError: 49 | return None 50 | 51 | except requests.exceptions.ConnectionError: 52 | return None 53 | 54 | except requests.exceptions.ReadTimeout: 55 | return None 56 | -------------------------------------------------------------------------------- /views/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | API Cek 📑🗓 | Web Apps 7 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 |
17 |
18 |
19 |

API Cek 📑🗓

20 |
21 |
22 |
23 |
24 | 25 | 31 |
32 | 33 |
34 | 35 | 37 |
38 | 39 |
40 | 41 | 44 |
45 | 46 | 47 | 48 | 49 |
50 |
51 | 52 | 55 | 56 | 57 |
58 |
59 | 60 |
61 |
62 |
63 |

Detail Tagihan

64 | 77 |
78 |
79 |
80 | 81 |
82 |
83 | 86 |
87 |
88 | 89 | 90 |
91 |
92 | 93 | 96 | 97 | 256 | 257 | --------------------------------------------------------------------------------