add flutter
This commit is contained in:
Regular → Executable
@@ -0,0 +1,83 @@
|
||||
# Backend panel files modified (from ordering workflow & fixes)
|
||||
|
||||
All paths below are relative to **backendpanel/**.
|
||||
|
||||
---
|
||||
|
||||
## 1. `application/controllers/api/Notification.php`
|
||||
|
||||
**Change:** Load FCM v1 helper before calling the notification model so `send_generic` works.
|
||||
|
||||
- Added: `$this->load->helper('fcm_v1_helper');` at the start of `send_generic_post()`, before reading `$decoded`.
|
||||
|
||||
**Reason:** User and Driver apps send FCM via `POST api/notification/send_generic`. The controller calls `send_generic_to_token` / `send_generic_to_topic`, which use `fcm_v1_send()` from the helper.
|
||||
|
||||
---
|
||||
|
||||
## 2. `application/models/Notification_model.php`
|
||||
|
||||
**Change:** Implemented generic FCM send methods used by the API.
|
||||
|
||||
- Added: **`send_generic_to_token($target, $data, $options)`**
|
||||
Flattens `$data` (string values for FCM), loads `fcm_v1_helper` if needed, calls `fcm_v1_send($target, $flat, false, $options)`. Returns `true`/`false`.
|
||||
|
||||
- Added: **`send_generic_to_topic($target, $data, $options)`**
|
||||
Same as above but calls `fcm_v1_send(..., true, $options)` for topic.
|
||||
|
||||
**Reason:** The API was calling these methods but they did not exist. Without them, ordering FCM from User/Driver apps would fail.
|
||||
|
||||
---
|
||||
|
||||
## 3. `application/config/config.php`
|
||||
|
||||
**Change:** Documented the test backend URL.
|
||||
|
||||
- Added comment in the base_url block:
|
||||
`| Test backend API: apitest.semestaterpadu.my.id`
|
||||
- No change to the actual `$config['base_url']` value (already `https://apitest.semestaterpadu.my.id/`).
|
||||
|
||||
**Reason:** Clarify that the test backend endpoint is `apitest.semestaterpadu.my.id`.
|
||||
|
||||
---
|
||||
|
||||
## 4. `application/models/Pelanggan_model.php`
|
||||
|
||||
**Changes:**
|
||||
|
||||
- **get_driver_ride($lat, $lng, $fitur)**
|
||||
- **Logic:** Replaced
|
||||
`HAVING distance <= f.jarak_minimum`
|
||||
with
|
||||
`HAVING distance <= GREATEST(COALESCE(f.jarak_minimum, 10), 10)`
|
||||
so the search radius is at least 10 km (still uses real GPS from `config_driver` and user lat/lng; no region).
|
||||
- **Docblock:** Added comment that matching is purely by GPS, no region/wilayah; radius = `jarak_minimum` with minimum 10 km.
|
||||
|
||||
- **get_driver_car($lat, $lng, $fitur)**
|
||||
- **Docblock only:** Added comment that matching is purely by GPS, no region; radius 10 km.
|
||||
- Query unchanged (already used a fixed 10 km radius).
|
||||
|
||||
- **merchantnearby($long, $lat)**
|
||||
- **Docblock only:** Added comment that matching is purely by GPS (merchant lat/long vs user), no region; distance <= `fitur.jarak_minimum`.
|
||||
|
||||
- **merchantpromo($long, $lat)**
|
||||
- **Docblock only:** “Merchant promo nearby: purely GPS, no region.”
|
||||
|
||||
- **allmerchantnearby($long, $lat, $fitur)**
|
||||
- **Docblock only:** “All merchant nearby by fitur: purely GPS (merchant lat/long vs user), no region.”
|
||||
|
||||
**Reason:**
|
||||
- Minimum 10 km radius for ride so “tidak ada pengemudi” is less likely when drivers are close.
|
||||
- Explicit documentation that driver and merchant nearby use only real GPS and `jarak_minimum`, with no region involvement.
|
||||
|
||||
---
|
||||
|
||||
## Summary table
|
||||
|
||||
| File | Type of change |
|
||||
|------|----------------|
|
||||
| `application/controllers/api/Notification.php` | Load `fcm_v1_helper` in `send_generic_post()` |
|
||||
| `application/models/Notification_model.php` | New `send_generic_to_token`, `send_generic_to_topic` |
|
||||
| `application/config/config.php` | Comment: test backend API = apitest.semestaterpadu.my.id |
|
||||
| `application/models/Pelanggan_model.php` | Min radius 10 km in `get_driver_ride`; docblocks (purely GPS, no region) on driver & merchant nearby functions |
|
||||
|
||||
No other files under **backendpanel** were modified for these modifications (no views, no other controllers, no other models).
|
||||
Regular → Executable
Regular → Executable
Regular → Executable
+13
-6
@@ -22,6 +22,8 @@ defined('BASEPATH') or exit('No direct script access allowed');
|
||||
| If you need to allow multiple domains, remember that this file is still
|
||||
| a PHP script and you can easily do that on your own.
|
||||
|
|
||||
|
|
||||
| Test backend API: apitest.semestaterpadu.my.id
|
||||
*/
|
||||
$config['base_url'] = 'https://apitest.semestaterpadu.my.id/';
|
||||
|
||||
@@ -30,11 +32,16 @@ $config['base_url'] = 'https://apitest.semestaterpadu.my.id/';
|
||||
| API keys & external services (edit values here)
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
$config['google_maps_api_key'] = '';
|
||||
$config['firebase_db_url'] = 'https://project-on-time-apps-default-rtdb.firebaseio.com/';
|
||||
$config['fcm_project_id'] = '';
|
||||
$config['google_maps_api_key'] = 'AIzaSyB-g7AdE_hmuDjv7GMMPbrfT0N36yR3N7o';
|
||||
$config['firebase_db_url'] = 'https://ngojol-trial-default-rtdb.firebaseio.com/';
|
||||
// Firebase / FCM HTTP v1 service account configuration.
|
||||
// Project id from ngojol-trial-firebase-adminsdk JSON.
|
||||
$config['fcm_project_id'] = 'ngojol-trial';
|
||||
// Prefer using a credentials file path rather than inlining JSON here.
|
||||
// The JSON file is stored at backendpanel/ngojol-trial-firebase-adminsdk-lc81n-00c9e935db.json
|
||||
// and will be read by fcm_v1_helper via FCM_CREDENTIALS_PATH.
|
||||
$config['fcm_credentials_json'] = '';
|
||||
$config['fcm_credentials_path'] = '';
|
||||
$config['fcm_credentials_path'] = FCPATH . 'ngojol-trial-firebase-adminsdk-lc81n-00c9e935db.json';
|
||||
$config['fcm_limit_per_hour'] = 100;
|
||||
$config['fcm_limit_per_day'] = 500;
|
||||
$config['maps_limit_per_hour'] = 1000;
|
||||
@@ -182,7 +189,7 @@ $config['composer_autoload'] = FALSE;
|
||||
| Leave blank to allow all characters -- but only if you are insane.
|
||||
|
|
||||
| The configured value is actually a regular expression character group
|
||||
| and it will be executed as: ! preg_match('/^[<permitted_uri_chars>]+$/i
|
||||
| and it will be executed as: ! preg_match('/^[permitted_uri_chars]+$/i
|
||||
|
|
||||
| DO NOT CHANGE THIS UNLESS YOU FULLY UNDERSTAND THE REPERCUSSIONS!!
|
||||
|
|
||||
@@ -252,7 +259,7 @@ $config['allow_get_array'] = TRUE;
|
||||
| your log files will fill up very fast.
|
||||
|
|
||||
*/
|
||||
$config['log_threshold'] = 0;
|
||||
$config['log_threshold'] = 2;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
||||
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
+14
-2
@@ -24,13 +24,25 @@ class appnotification extends CI_Controller
|
||||
|
||||
public function send()
|
||||
{
|
||||
$this->load->helper('fcm_v1_helper');
|
||||
|
||||
// Validate Firebase token before kirim. If no token, relogin (retry) is done in helper.
|
||||
if (!fcm_v1_validate_token()) {
|
||||
$this->session->set_flashdata('error', 'Firebase token tidak valid. Pastikan file ngojol-trial-firebase-adminsdk JSON ada dan dapat dibaca. Silakan coba lagi.');
|
||||
redirect('appnotification/index');
|
||||
return;
|
||||
}
|
||||
|
||||
$topic = $this->input->post('topic');
|
||||
$title = $this->input->post('title');
|
||||
$message = $this->input->post('message');
|
||||
$this->notif->send_notif($title, $message, $topic);
|
||||
$this->session->set_flashdata('send', 'Notifikasi berhasil dikirim');
|
||||
|
||||
$ok = $this->notif->send_notif($title, $message, $topic);
|
||||
if ($ok) {
|
||||
$this->session->set_flashdata('send', 'Notifikasi berhasil dikirim');
|
||||
} else {
|
||||
$this->session->set_flashdata('error', 'Gagal mengirim notifikasi. Firebase token mungkin kedaluwarsa. Silakan coba lagi.');
|
||||
}
|
||||
redirect('appnotification/index');
|
||||
}
|
||||
}
|
||||
|
||||
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
+3
-1
@@ -59,6 +59,7 @@ class Driver extends CI_Controller
|
||||
$this->form_validation->set_rules('tgl_lahir', 'tgl_lahir', 'trim|prep_for_form');
|
||||
$this->form_validation->set_rules('gender', 'gender', 'trim|prep_for_form');
|
||||
$this->form_validation->set_rules('alamat_driver', 'alamat_driver', 'trim|prep_for_form');
|
||||
$this->form_validation->set_rules('reg_id', 'reg_id', 'trim|prep_for_form');
|
||||
|
||||
|
||||
if ($this->form_validation->run() == TRUE) {
|
||||
@@ -76,7 +77,8 @@ class Driver extends CI_Controller
|
||||
'tempat_lahir' => html_escape($this->input->post('tempat_lahir', TRUE)),
|
||||
'tgl_lahir' => html_escape($this->input->post('tgl_lahir', TRUE)),
|
||||
'gender' => html_escape($this->input->post('gender', TRUE)),
|
||||
'alamat_driver' => html_escape($this->input->post('alamat_driver', TRUE))
|
||||
'alamat_driver' => html_escape($this->input->post('alamat_driver', TRUE)),
|
||||
'reg_id' => html_escape($this->input->post('reg_id', TRUE))
|
||||
];
|
||||
|
||||
|
||||
|
||||
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
+45
-10
@@ -10,6 +10,7 @@ class Driver extends REST_Controller
|
||||
parent::__construct();
|
||||
|
||||
$this->load->helper("url");
|
||||
$this->load->helper('fcm_v1_helper');
|
||||
$this->load->database();
|
||||
$this->load->model('Driver_model');
|
||||
$this->load->model('Pelanggan_model');
|
||||
@@ -75,16 +76,28 @@ class Driver extends REST_Controller
|
||||
|
||||
$data = file_get_contents("php://input");
|
||||
$decoded_data = json_decode($data);
|
||||
$reg_id = array(
|
||||
'reg_id' => $decoded_data->token
|
||||
);
|
||||
// Only save reg_id (FCM token) when valid. Invalid/placeholder tokens are updated by relogin.
|
||||
$token_from_regid = isset($decoded_data->reg_id) ? trim((string) $decoded_data->reg_id) : '';
|
||||
$token_from_token = isset($decoded_data->token) ? trim((string) $decoded_data->token) : '';
|
||||
$token = $token_from_regid !== '' ? $token_from_regid : $token_from_token;
|
||||
$reg_id = array();
|
||||
if ($token !== '' && function_exists('fcm_v1_is_valid_device_token') && fcm_v1_is_valid_device_token($token)) {
|
||||
$reg_id['reg_id'] = $token;
|
||||
}
|
||||
|
||||
$condition = array(
|
||||
'password' => sha1($decoded_data->password),
|
||||
'no_telepon' => $decoded_data->no_telepon,
|
||||
//'token' => $decoded_data->token
|
||||
'password' => sha1($decoded_data->password)
|
||||
);
|
||||
$check_banned = $this->Driver_model->check_banned($decoded_data->no_telepon);
|
||||
$login_by_phone = isset($decoded_data->no_telepon) && $decoded_data->no_telepon !== '';
|
||||
if ($login_by_phone) {
|
||||
$condition['no_telepon'] = $decoded_data->no_telepon;
|
||||
} else {
|
||||
$condition['email'] = $decoded_data->email;
|
||||
}
|
||||
|
||||
$check_banned = $login_by_phone
|
||||
? $this->Driver_model->check_banned($decoded_data->no_telepon)
|
||||
: $this->Driver_model->check_banned_by_email($decoded_data->email);
|
||||
if ($check_banned) {
|
||||
$message = array(
|
||||
'message' => 'banned',
|
||||
@@ -96,9 +109,12 @@ class Driver extends REST_Controller
|
||||
$message = array();
|
||||
|
||||
if ($cek_login->num_rows() > 0) {
|
||||
$upd_regid = $this->Driver_model->edit_profile($reg_id, $decoded_data->no_telepon);
|
||||
$no_telepon = $cek_login->row()->no_telepon;
|
||||
if (!empty($reg_id)) {
|
||||
$this->Driver_model->edit_profile($reg_id, $no_telepon);
|
||||
}
|
||||
$get_pelanggan = $this->Driver_model->get_data_pelanggan($condition);
|
||||
$this->Driver_model->edit_status_login($decoded_data->no_telepon);
|
||||
$this->Driver_model->edit_status_login($no_telepon);
|
||||
$message = array(
|
||||
'code' => '200',
|
||||
'message' => 'found',
|
||||
@@ -133,6 +149,12 @@ class Driver extends REST_Controller
|
||||
);
|
||||
$ins = $this->Driver_model->my_location($data);
|
||||
|
||||
// When driver sends valid FCM token (reg_id) with location, update so they receive order requests. Invalid/placeholder tokens are updated by relogin.
|
||||
$reg_id = isset($decoded_data->reg_id) ? trim((string) $decoded_data->reg_id) : '';
|
||||
if ($reg_id !== '' && isset($decoded_data->id_driver) && function_exists('fcm_v1_is_valid_device_token') && fcm_v1_is_valid_device_token($reg_id)) {
|
||||
$this->Driver_model->update_driver_reg_id($decoded_data->id_driver, $reg_id);
|
||||
}
|
||||
|
||||
if ($ins) {
|
||||
$message = array(
|
||||
'message' => 'location updated',
|
||||
@@ -360,6 +382,7 @@ class Driver extends REST_Controller
|
||||
|
||||
$data = file_get_contents("php://input");
|
||||
$dec_data = json_decode($data);
|
||||
log_message('debug', 'accept_post: payload=' . $data);
|
||||
|
||||
$data_req = array(
|
||||
'id_driver' => $dec_data->id,
|
||||
@@ -372,9 +395,11 @@ class Driver extends REST_Controller
|
||||
);
|
||||
|
||||
$cek_login = $this->Driver_model->get_status_driver($condition);
|
||||
log_message('debug', 'accept_post: get_status_driver rows=' . $cek_login->num_rows());
|
||||
if ($cek_login->num_rows() > 0) {
|
||||
|
||||
$acc_req = $this->Driver_model->accept_request($data_req);
|
||||
log_message('debug', 'accept_post: accept_request result=' . json_encode($acc_req));
|
||||
if ($acc_req['status']) {
|
||||
$message = array(
|
||||
'message' => 'berhasil',
|
||||
@@ -415,6 +440,7 @@ class Driver extends REST_Controller
|
||||
|
||||
$data = file_get_contents("php://input");
|
||||
$dec_data = json_decode($data);
|
||||
log_message('debug', 'start_post: payload=' . $data);
|
||||
|
||||
$data_req = array(
|
||||
'id_driver' => $dec_data->id,
|
||||
@@ -422,6 +448,7 @@ class Driver extends REST_Controller
|
||||
);
|
||||
|
||||
$acc_req = $this->Driver_model->start_request($data_req);
|
||||
log_message('debug', 'start_post: start_request result=' . json_encode($acc_req));
|
||||
if ($acc_req['status']) {
|
||||
$message = array(
|
||||
'message' => 'berhasil',
|
||||
@@ -455,6 +482,7 @@ class Driver extends REST_Controller
|
||||
|
||||
$data = file_get_contents("php://input");
|
||||
$dec_data = json_decode($data);
|
||||
log_message('debug', 'finish_post: payload=' . $data);
|
||||
|
||||
$data_req = array(
|
||||
'id_driver' => $dec_data->id,
|
||||
@@ -467,6 +495,7 @@ class Driver extends REST_Controller
|
||||
);
|
||||
|
||||
$finish_transaksi = $this->Driver_model->finish_request($data_req, $data_tr);
|
||||
log_message('debug', 'finish_post: finish_request result=' . json_encode($finish_transaksi));
|
||||
if ($finish_transaksi['status']) {
|
||||
$message = array(
|
||||
'message' => 'berhasil',
|
||||
@@ -863,6 +892,12 @@ class Driver extends REST_Controller
|
||||
$namafoto = time() . '-' . rand(0, 99999) . ".jpg";
|
||||
$path = "images/fotodriver/" . $namafoto;
|
||||
file_put_contents($path, base64_decode($image));
|
||||
|
||||
// New driver registrations from older apps do not send an FCM token yet.
|
||||
// Generate a deterministic placeholder based on email so reg_id is never empty.
|
||||
// This stays unusable for FCM v1 because fcm_v1_is_valid_device_token() will reject it.
|
||||
$regIdPlaceholder = 'R' . sprintf('%u', crc32(strtolower(trim((string) $dec_data->email))));
|
||||
|
||||
$data_signup = array(
|
||||
'id' => 'D' . time(),
|
||||
'nama_driver' => $dec_data->nama_driver,
|
||||
@@ -878,7 +913,7 @@ class Driver extends REST_Controller
|
||||
'countrycode' => $dec_data->countrycode,
|
||||
'gender' => $dec_data->gender,
|
||||
'alamat_driver' => $dec_data->alamat_driver,
|
||||
'reg_id' => 12345,
|
||||
'reg_id' => $regIdPlaceholder,
|
||||
'status' => 0
|
||||
);
|
||||
|
||||
|
||||
Regular → Executable
Regular → Executable
+17
-5
@@ -10,6 +10,7 @@ class Merchant extends REST_Controller
|
||||
parent::__construct();
|
||||
|
||||
$this->load->helper("url");
|
||||
$this->load->helper('fcm_v1_helper');
|
||||
$this->load->database();
|
||||
$this->load->model('Merchantapi_model');
|
||||
$this->load->model('wallet_model', 'wallet');
|
||||
@@ -64,9 +65,13 @@ class Merchant extends REST_Controller
|
||||
|
||||
$data = file_get_contents("php://input");
|
||||
$decoded_data = json_decode($data);
|
||||
$reg_id = array(
|
||||
'token_merchant' => $decoded_data->token
|
||||
);
|
||||
// Only save FCM token when valid (relogin overwrites invalid/placeholder tokens).
|
||||
$token = isset($decoded_data->token) ? trim((string) $decoded_data->token) : '';
|
||||
$token = (isset($decoded_data->reg_id) && trim((string) $decoded_data->reg_id) !== '') ? trim((string) $decoded_data->reg_id) : $token;
|
||||
$reg_id = array();
|
||||
if ($token !== '' && function_exists('fcm_v1_is_valid_device_token') && fcm_v1_is_valid_device_token($token)) {
|
||||
$reg_id['token_merchant'] = $token;
|
||||
}
|
||||
|
||||
$condition = array(
|
||||
'password' => sha1($decoded_data->password),
|
||||
@@ -84,7 +89,9 @@ class Merchant extends REST_Controller
|
||||
$cek_login = $this->Merchantapi_model->get_data_merchant($condition);
|
||||
$message = array();
|
||||
if ($cek_login->num_rows() > 0) {
|
||||
$this->Merchantapi_model->edit_profile_token($reg_id, $decoded_data->no_telepon);
|
||||
if (!empty($reg_id)) {
|
||||
$this->Merchantapi_model->edit_profile_token($reg_id, $decoded_data->no_telepon);
|
||||
}
|
||||
$get_pelanggan = $this->Merchantapi_model->get_data_merchant($condition);
|
||||
$message = array(
|
||||
'code' => '200',
|
||||
@@ -183,6 +190,11 @@ class Merchant extends REST_Controller
|
||||
$path = "images/merchant/" . $namafoto;
|
||||
file_put_contents($path, base64_decode($image));
|
||||
|
||||
// Merchant apps prior to FCM v1 do not send a Firebase token on register.
|
||||
// Generate a deterministic placeholder from email so token_merchant is never empty.
|
||||
// This value is NOT a real FCM token; Notification_model will ignore it for push.
|
||||
$tokenPlaceholder = 'R' . sprintf('%u', crc32(strtolower(trim((string) $dec_data->email))));
|
||||
|
||||
$data_merchant = array(
|
||||
'id_fitur' => $dec_data->id_fitur,
|
||||
'nama_merchant' => $dec_data->nama_merchant,
|
||||
@@ -197,7 +209,7 @@ class Merchant extends REST_Controller
|
||||
'phone_merchant' => $dec_data->phone,
|
||||
'country_code_merchant' => $dec_data->countrycode,
|
||||
'status_merchant' => '0',
|
||||
'token_merchant' => time()
|
||||
'token_merchant' => $tokenPlaceholder
|
||||
);
|
||||
|
||||
$imagektp = $dec_data->foto_ktp;
|
||||
|
||||
Regular → Executable
Regular → Executable
+11
@@ -48,6 +48,17 @@ class Notification extends REST_Controller
|
||||
return;
|
||||
}
|
||||
|
||||
$this->load->helper('fcm_v1_helper');
|
||||
|
||||
// Always verify FCM token is ready before using Firebase service (as in test / panel send).
|
||||
if (!fcm_v1_validate_token()) {
|
||||
$this->response(array(
|
||||
'code' => '503',
|
||||
'message' => 'fcm_token_not_ready',
|
||||
), 200);
|
||||
return;
|
||||
}
|
||||
|
||||
$target = isset($decoded['target']) ? trim($decoded['target']) : '';
|
||||
$is_topic = !empty($decoded['is_topic']);
|
||||
$data = isset($decoded['data']) && is_array($decoded['data']) ? $decoded['data'] : array();
|
||||
|
||||
Regular → Executable
+103
-25
@@ -10,6 +10,7 @@ class Pelanggan extends REST_Controller
|
||||
parent::__construct();
|
||||
|
||||
$this->load->helper("url");
|
||||
$this->load->helper('fcm_v1_helper');
|
||||
$this->load->database();
|
||||
$this->load->model('Pelanggan_model');
|
||||
$this->load->model('wallet_model', 'wallet');
|
||||
@@ -115,16 +116,37 @@ class Pelanggan extends REST_Controller
|
||||
|
||||
$data = file_get_contents("php://input");
|
||||
$decoded_data = json_decode($data);
|
||||
$reg_id = array(
|
||||
'token' => $decoded_data->token
|
||||
);
|
||||
if (!$decoded_data || !isset($decoded_data->password)) {
|
||||
$this->response(array('code' => '400', 'message' => 'Invalid request', 'data' => []), 200);
|
||||
return;
|
||||
}
|
||||
// Only save FCM token when valid (relogin overwrites invalid/placeholder tokens).
|
||||
$token = isset($decoded_data->token) ? trim((string) $decoded_data->token) : '';
|
||||
$token = (isset($decoded_data->reg_id) && trim((string) $decoded_data->reg_id) !== '') ? trim((string) $decoded_data->reg_id) : $token;
|
||||
$reg_id = array();
|
||||
if ($token !== '' && function_exists('fcm_v1_is_valid_device_token') && fcm_v1_is_valid_device_token($token)) {
|
||||
$reg_id['token'] = $token;
|
||||
}
|
||||
|
||||
$condition = array(
|
||||
'password' => sha1($decoded_data->password),
|
||||
'no_telepon' => $decoded_data->no_telepon,
|
||||
//'token' => $decoded_data->token
|
||||
'password' => sha1($decoded_data->password)
|
||||
);
|
||||
$check_banned = $this->Pelanggan_model->check_banned($decoded_data->no_telepon);
|
||||
$no_telepon_val = isset($decoded_data->no_telepon) ? trim($decoded_data->no_telepon) : '';
|
||||
$email_val = isset($decoded_data->email) ? trim($decoded_data->email) : '';
|
||||
$login_by_phone = $no_telepon_val !== '';
|
||||
if ($login_by_phone) {
|
||||
$condition['no_telepon'] = $no_telepon_val;
|
||||
} else {
|
||||
if ($email_val === '') {
|
||||
$this->response(array('code' => '404', 'message' => 'no hp atau password salah!', 'data' => []), 200);
|
||||
return;
|
||||
}
|
||||
$condition['email'] = $email_val;
|
||||
}
|
||||
|
||||
$check_banned = $login_by_phone
|
||||
? $this->Pelanggan_model->check_banned($no_telepon_val)
|
||||
: $this->Pelanggan_model->check_banned_user($email_val);
|
||||
if ($check_banned) {
|
||||
$message = array(
|
||||
'message' => 'banned',
|
||||
@@ -136,7 +158,10 @@ class Pelanggan extends REST_Controller
|
||||
$message = array();
|
||||
|
||||
if ($cek_login->num_rows() > 0) {
|
||||
$upd_regid = $this->Pelanggan_model->edit_profile($reg_id, $decoded_data->no_telepon);
|
||||
$no_telepon = $cek_login->row()->no_telepon;
|
||||
if (!empty($reg_id)) {
|
||||
$this->Pelanggan_model->edit_profile($reg_id, $no_telepon);
|
||||
}
|
||||
$get_pelanggan = $this->Pelanggan_model->get_data_pelanggan($condition);
|
||||
|
||||
$message = array(
|
||||
@@ -206,6 +231,21 @@ class Pelanggan extends REST_Controller
|
||||
$namafoto = time() . '-' . rand(0, 99999) . ".jpg";
|
||||
$path = "images/pelanggan/" . $namafoto;
|
||||
file_put_contents($path, base64_decode($image));
|
||||
|
||||
// New users may register from older apps that do not send an FCM token.
|
||||
// Generate a deterministic placeholder based on email so the column is never empty.
|
||||
// This placeholder is intentionally SHORT / starting with "R" + digits so
|
||||
// fcm_v1_is_valid_device_token() will treat it as invalid for push.
|
||||
$incomingToken = isset($dec_data->token) ? trim((string) $dec_data->token) : '';
|
||||
if ($incomingToken === '') {
|
||||
$emailForToken = isset($dec_data->email) ? strtolower(trim((string) $dec_data->email)) : '';
|
||||
if ($emailForToken !== '') {
|
||||
$incomingToken = 'R' . sprintf('%u', crc32($emailForToken));
|
||||
} else {
|
||||
$incomingToken = 'R' . sprintf('%u', crc32('guest-' . time()));
|
||||
}
|
||||
}
|
||||
|
||||
$data_signup = array(
|
||||
'id' => 'P' . time(),
|
||||
'fullnama' => $dec_data->fullnama,
|
||||
@@ -216,7 +256,7 @@ class Pelanggan extends REST_Controller
|
||||
'tgl_lahir' => $dec_data->tgl_lahir,
|
||||
'countrycode' => $dec_data->countrycode,
|
||||
'fotopelanggan' => $namafoto,
|
||||
'token' => $dec_data->token,
|
||||
'token' => $incomingToken,
|
||||
);
|
||||
$signup = $this->Pelanggan_model->signup($data_signup);
|
||||
if ($signup) {
|
||||
@@ -831,24 +871,24 @@ class Pelanggan extends REST_Controller
|
||||
$token = $this->wallet->gettoken($iduser);
|
||||
$regid = $this->wallet->getregid($iduser);
|
||||
$tokenmerchant = $this->wallet->gettokenmerchant($iduser);
|
||||
|
||||
if ($token == NULL and $tokenmerchant == NULL and $regid != NULL) {
|
||||
|
||||
$topic = null;
|
||||
if ($token == NULL and $tokenmerchant == NULL and $regid != NULL && !empty(trim((string) $regid['reg_id']))) {
|
||||
$topic = $regid['reg_id'];
|
||||
} else if ($regid == NULL and $tokenmerchant == NULL and $token != NULL) {
|
||||
} else if ($regid == NULL and $tokenmerchant == NULL and $token != NULL && !empty(trim((string) $token['token']))) {
|
||||
$topic = $token['token'];
|
||||
} else if ($regid == NULL and $token == NULL and $tokenmerchant != NULL) {
|
||||
} else if ($regid == NULL and $token == NULL and $tokenmerchant != NULL && !empty(trim((string) $tokenmerchant['token_merchant']))) {
|
||||
$topic = $tokenmerchant['token_merchant'];
|
||||
}
|
||||
|
||||
|
||||
$title = 'Sukses';
|
||||
$message = 'Permintaan berhasil dikirim';
|
||||
$saldo = $this->wallet->getsaldo($iduser);
|
||||
|
||||
|
||||
|
||||
|
||||
$this->wallet->ubahsaldo($iduser, $amount, $saldo);
|
||||
//$this->wallet->ubahstatuswithdrawbyid($id);
|
||||
$this->wallet->send_notif($title, $message, $topic);
|
||||
if ($topic !== null) {
|
||||
$this->wallet->send_notif($title, $message, $topic);
|
||||
}
|
||||
|
||||
/* END EDIT */
|
||||
$message = array(
|
||||
@@ -877,12 +917,26 @@ class Pelanggan extends REST_Controller
|
||||
}
|
||||
|
||||
$data = file_get_contents("php://input");
|
||||
$dec_data = json_decode($data);
|
||||
log_message('debug', 'list_ride_post REQUEST: ' . $data);
|
||||
|
||||
$near = $this->Pelanggan_model->get_driver_ride($dec_data->latitude, $dec_data->longitude, $dec_data->fitur);
|
||||
$dec_data = json_decode($data);
|
||||
if (!$dec_data || !isset($dec_data->latitude, $dec_data->longitude, $dec_data->fitur)) {
|
||||
log_message('error', 'list_ride_post: invalid request, missing latitude/longitude/fitur');
|
||||
$message = array('data' => [], 'error' => 'Invalid request: latitude, longitude, fitur required');
|
||||
$this->response($message, 200);
|
||||
return;
|
||||
}
|
||||
|
||||
$radius_km = null;
|
||||
if (isset($dec_data->radius_km) && is_numeric($dec_data->radius_km)) {
|
||||
$radius_km = max(1, min(100, (float) $dec_data->radius_km));
|
||||
}
|
||||
$near = $this->Pelanggan_model->get_driver_ride($dec_data->latitude, $dec_data->longitude, $dec_data->fitur, $radius_km);
|
||||
$drivers = $near->result();
|
||||
$message = array(
|
||||
'data' => $near->result()
|
||||
'data' => $drivers
|
||||
);
|
||||
log_message('debug', 'list_ride_post RESPONSE: fitur=' . $dec_data->fitur . ' lat=' . $dec_data->latitude . ' lng=' . $dec_data->longitude . ' radius_km=' . ($radius_km !== null ? $radius_km : 'default') . ' drivers_found=' . count($drivers));
|
||||
$this->response($message, 200);
|
||||
}
|
||||
|
||||
@@ -910,12 +964,26 @@ class Pelanggan extends REST_Controller
|
||||
}
|
||||
|
||||
$data = file_get_contents("php://input");
|
||||
$dec_data = json_decode($data);
|
||||
log_message('debug', 'list_car_post REQUEST: ' . $data);
|
||||
|
||||
$near = $this->Pelanggan_model->get_driver_car($dec_data->latitude, $dec_data->longitude, $dec_data->fitur);
|
||||
$dec_data = json_decode($data);
|
||||
if (!$dec_data || !isset($dec_data->latitude, $dec_data->longitude, $dec_data->fitur)) {
|
||||
log_message('error', 'list_car_post: invalid request, missing latitude/longitude/fitur');
|
||||
$message = array('data' => [], 'error' => 'Invalid request: latitude, longitude, fitur required');
|
||||
$this->response($message, 200);
|
||||
return;
|
||||
}
|
||||
|
||||
$radius_km = null;
|
||||
if (isset($dec_data->radius_km) && is_numeric($dec_data->radius_km)) {
|
||||
$radius_km = max(1, min(100, (float) $dec_data->radius_km));
|
||||
}
|
||||
$near = $this->Pelanggan_model->get_driver_car($dec_data->latitude, $dec_data->longitude, $dec_data->fitur, $radius_km);
|
||||
$drivers = $near->result();
|
||||
$message = array(
|
||||
'data' => $near->result()
|
||||
'data' => $drivers
|
||||
);
|
||||
log_message('debug', 'list_car_post RESPONSE: fitur=' . $dec_data->fitur . ' lat=' . $dec_data->latitude . ' lng=' . $dec_data->longitude . ' radius_km=' . ($radius_km !== null ? $radius_km : 'default') . ' drivers_found=' . count($drivers));
|
||||
$this->response($message, 200);
|
||||
}
|
||||
|
||||
@@ -946,6 +1014,7 @@ class Pelanggan extends REST_Controller
|
||||
} else {
|
||||
$cek = $this->Pelanggan_model->check_banned_user($_SERVER['PHP_AUTH_USER']);
|
||||
if ($cek) {
|
||||
log_message('debug', 'request_transaksi_post: banned user ' . $_SERVER['PHP_AUTH_USER']);
|
||||
$message = array(
|
||||
'message' => 'fail',
|
||||
'data' => 'Status User Banned'
|
||||
@@ -956,6 +1025,7 @@ class Pelanggan extends REST_Controller
|
||||
|
||||
$data = file_get_contents("php://input");
|
||||
$dec_data = json_decode($data);
|
||||
log_message('debug', 'request_transaksi_post: payload=' . $data);
|
||||
|
||||
$data_req = array(
|
||||
'id_pelanggan' => $dec_data->id_pelanggan,
|
||||
@@ -977,12 +1047,18 @@ class Pelanggan extends REST_Controller
|
||||
|
||||
$request = $this->Pelanggan_model->insert_transaksi($data_req);
|
||||
if ($request['status']) {
|
||||
if (isset($request['data'][0]->id)) {
|
||||
log_message('debug', 'request_transaksi_post: success id_transaksi=' . $request['data'][0]->id . ' id_pelanggan=' . $dec_data->id_pelanggan . ' fitur=' . $dec_data->order_fitur);
|
||||
} else {
|
||||
log_message('debug', 'request_transaksi_post: success (no id in data) payload=' . json_encode($request['data']));
|
||||
}
|
||||
$message = array(
|
||||
'message' => 'success',
|
||||
'data' => $request['data']
|
||||
);
|
||||
$this->response($message, 200);
|
||||
} else {
|
||||
log_message('error', 'request_transaksi_post: insert_transaksi fail data=' . json_encode($request['data']));
|
||||
$message = array(
|
||||
'message' => 'fail',
|
||||
'data' => $request['data']
|
||||
@@ -1001,12 +1077,14 @@ class Pelanggan extends REST_Controller
|
||||
|
||||
$data = file_get_contents("php://input");
|
||||
$dec_data = json_decode($data);
|
||||
log_message('debug', 'check_status_transaksi_post: payload=' . $data);
|
||||
|
||||
$dataTrans = array(
|
||||
'id_transaksi' => $dec_data->id_transaksi
|
||||
);
|
||||
|
||||
$getStatus = $this->Pelanggan_model->check_status($dataTrans);
|
||||
log_message('debug', 'check_status_transaksi_post: result=' . json_encode($getStatus));
|
||||
$this->response($getStatus, 200);
|
||||
}
|
||||
|
||||
|
||||
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
+136
-11
@@ -12,11 +12,17 @@ if (!function_exists('fcm_v1_get_credentials')) {
|
||||
{
|
||||
$json = (defined('FCM_CREDENTIALS_JSON') ? FCM_CREDENTIALS_JSON : '');
|
||||
if ($json !== '') {
|
||||
log_message('debug', 'FCM v1: loading credentials from FCM_CREDENTIALS_JSON');
|
||||
return json_decode($json, true);
|
||||
}
|
||||
$path = (defined('FCM_CREDENTIALS_PATH') ? FCM_CREDENTIALS_PATH : '');
|
||||
if ($path !== '' && is_readable($path)) {
|
||||
return json_decode(file_get_contents($path), true);
|
||||
if ($path !== '') {
|
||||
if (is_readable($path)) {
|
||||
log_message('debug', 'FCM v1: loading credentials from path=' . $path);
|
||||
return json_decode(file_get_contents($path), true);
|
||||
} else {
|
||||
log_message('error', 'FCM v1: credentials path not readable: ' . $path);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -25,47 +31,113 @@ if (!function_exists('fcm_v1_get_credentials')) {
|
||||
if (!function_exists('fcm_v1_get_access_token')) {
|
||||
/**
|
||||
* Get OAuth2 access token for FCM using service account JWT.
|
||||
* Uses ngojol-trial-firebase-adminsdk JSON credentials.
|
||||
* Retries once on failure (relogin to Firebase).
|
||||
* @return string|null Access token or null on failure
|
||||
*/
|
||||
function fcm_v1_get_access_token()
|
||||
{
|
||||
$token = fcm_v1_fetch_access_token();
|
||||
if ($token) {
|
||||
return $token;
|
||||
}
|
||||
log_message('debug', 'FCM v1: Retrying Firebase auth (relogin)');
|
||||
return fcm_v1_fetch_access_token();
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('fcm_v1_fetch_access_token')) {
|
||||
/**
|
||||
* Single attempt to fetch OAuth2 access token from Firebase service account.
|
||||
* @return string|null Access token or null on failure
|
||||
*/
|
||||
function fcm_v1_fetch_access_token()
|
||||
{
|
||||
$cred = fcm_v1_get_credentials();
|
||||
if (!$cred || empty($cred['client_email']) || empty($cred['private_key'])) {
|
||||
log_message('error', 'FCM v1: Missing FCM_CREDENTIALS_JSON or FCM_CREDENTIALS_PATH');
|
||||
log_message('error', 'FCM v1: Missing credentials. Ensure ngojol-trial-firebase-adminsdk JSON is at FCM_CREDENTIALS_PATH');
|
||||
return null;
|
||||
}
|
||||
$now = time();
|
||||
$token_uri = !empty($cred['token_uri']) ? $cred['token_uri'] : 'https://oauth2.googleapis.com/token';
|
||||
// Use cloud-platform scope. If you get invalid_scope, enable Firebase Cloud Messaging API
|
||||
// in Google Cloud Console (APIs & Services → Library) for project ngojol-trial.
|
||||
$scope = 'https://www.googleapis.com/auth/cloud-platform';
|
||||
$jwt = array(
|
||||
'iss' => $cred['client_email'],
|
||||
'sub' => $cred['client_email'],
|
||||
'aud' => 'https://oauth2.googleapis.com/token',
|
||||
'iat' => $now,
|
||||
'exp' => $now + 3600,
|
||||
'scope' => $scope,
|
||||
);
|
||||
$jwt_b64 = fcm_v1_base64url_encode(json_encode(array('alg' => 'RS256', 'typ' => 'JWT')))
|
||||
. '.' . fcm_v1_base64url_encode(json_encode($jwt));
|
||||
$sig = '';
|
||||
$key = openssl_pkey_get_private($cred['private_key']);
|
||||
$pk = $cred['private_key'];
|
||||
if (strpos($pk, '\\n') !== false) {
|
||||
$pk = str_replace('\\n', "\n", $pk);
|
||||
}
|
||||
$key = openssl_pkey_get_private($pk);
|
||||
if (!$key) {
|
||||
log_message('error', 'FCM v1: Invalid private key');
|
||||
log_message('error', 'FCM v1: Invalid private key in service account JSON');
|
||||
return null;
|
||||
}
|
||||
openssl_sign($jwt_b64, $sig, $key, OPENSSL_ALGO_SHA256);
|
||||
openssl_free_key($key);
|
||||
$jwt_b64 .= '.' . fcm_v1_base64url_encode($sig);
|
||||
$resp = @file_get_contents('https://oauth2.googleapis.com/token', false, stream_context_create(array(
|
||||
$post_body = 'grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=' . rawurlencode($jwt_b64);
|
||||
$ctx = stream_context_create(array(
|
||||
'http' => array(
|
||||
'method' => 'POST',
|
||||
'header' => "Content-Type: application/x-www-form-urlencoded",
|
||||
'content' => 'grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=' . $jwt_b64,
|
||||
'content' => $post_body,
|
||||
'ignore_errors' => true,
|
||||
),
|
||||
)));
|
||||
));
|
||||
$resp = @file_get_contents($token_uri, false, $ctx);
|
||||
if ($resp === false) {
|
||||
log_message('error', 'FCM v1: Token request failed');
|
||||
log_message('error', 'FCM v1: Token request failed (network or OAuth error)');
|
||||
return null;
|
||||
}
|
||||
$data = json_decode($resp, true);
|
||||
return isset($data['access_token']) ? $data['access_token'] : null;
|
||||
if (isset($data['access_token'])) {
|
||||
return $data['access_token'];
|
||||
}
|
||||
log_message('error', 'FCM v1: Token response invalid: ' . substr($resp, 0, 200));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('fcm_v1_validate_token')) {
|
||||
/**
|
||||
* Validate that Firebase auth token can be obtained (for FCM send).
|
||||
* Call before kirim/send. If false, backend should prompt relogin/retry.
|
||||
* @return bool True if token is valid and ready for FCM
|
||||
*/
|
||||
function fcm_v1_validate_token()
|
||||
{
|
||||
$token = fcm_v1_get_access_token();
|
||||
return !empty($token);
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('fcm_v1_is_valid_device_token')) {
|
||||
/**
|
||||
* Check if string looks like a valid FCM v1 device token (not a placeholder).
|
||||
* Valid tokens from FirebaseMessaging.getToken() are typically 100+ chars.
|
||||
* Placeholders like "12345", "R1234567890" are rejected. Use relogin to update.
|
||||
*
|
||||
* @param string|null $token FCM device token from client
|
||||
* @return bool True if token looks valid and should be saved
|
||||
*/
|
||||
function fcm_v1_is_valid_device_token($token)
|
||||
{
|
||||
$s = $token === null ? '' : trim((string) $token);
|
||||
if ($s === '') return false;
|
||||
if (strlen($s) < 50) return false;
|
||||
if (preg_match('/^(12345|R\d+)$/', $s)) return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,6 +196,14 @@ if (!function_exists('fcm_v1_send')) {
|
||||
$message['android'] = array('priority' => 'HIGH');
|
||||
}
|
||||
$body = json_encode(array('message' => $message));
|
||||
// Log request (without auth token) for debugging
|
||||
$logTarget = $is_topic ? ('topic=' . (string)$target) : ('token=' . substr((string)$target, 0, 20) . '...');
|
||||
log_message(
|
||||
'debug',
|
||||
'FCM v1 request project_id=' . $project_id .
|
||||
' ' . $logTarget .
|
||||
' payload=' . $body
|
||||
);
|
||||
$ctx = stream_context_create(array(
|
||||
'http' => array(
|
||||
'method' => 'POST',
|
||||
@@ -136,6 +216,51 @@ if (!function_exists('fcm_v1_send')) {
|
||||
));
|
||||
$url = 'https://fcm.googleapis.com/v1/projects/' . $project_id . '/messages:send';
|
||||
$resp = @file_get_contents($url, false, $ctx);
|
||||
return $resp !== false ? $resp : false;
|
||||
if ($resp === false) {
|
||||
log_message('error', 'FCM v1 response error for ' . $logTarget);
|
||||
return false;
|
||||
}
|
||||
// Check for FCM error in response body (e.g. invalid topic, quota)
|
||||
$decoded = json_decode($resp, true);
|
||||
if (is_array($decoded) && isset($decoded['error'])) {
|
||||
log_message('error', 'FCM v1 API error for ' . $logTarget . ': ' . $resp);
|
||||
return false;
|
||||
}
|
||||
// On 401 (token expired), relogin and retry once
|
||||
$http_response_header_local = isset($http_response_header) ? $http_response_header : array();
|
||||
$is_401 = false;
|
||||
foreach ($http_response_header_local as $h) {
|
||||
if (preg_match('/^HTTP\/\d\.\d\s+401\b/', $h)) {
|
||||
$is_401 = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($is_401) {
|
||||
log_message('debug', 'FCM v1: 401 received, relogin and retry');
|
||||
$token = fcm_v1_get_access_token();
|
||||
if ($token) {
|
||||
$ctx = stream_context_create(array(
|
||||
'http' => array(
|
||||
'method' => 'POST',
|
||||
'header' =>
|
||||
"Content-Type: application/json\r\n" .
|
||||
"Authorization: Bearer " . $token . "\r\n",
|
||||
'content' => $body,
|
||||
'ignore_errors' => true,
|
||||
),
|
||||
));
|
||||
$resp = @file_get_contents($url, false, $ctx);
|
||||
}
|
||||
}
|
||||
log_message('debug', 'FCM v1 response for ' . $logTarget . ' body=' . $resp);
|
||||
// Treat FCM error in response body as failure
|
||||
if (is_string($resp)) {
|
||||
$decoded = json_decode($resp, true);
|
||||
if (is_array($decoded) && isset($decoded['error'])) {
|
||||
log_message('error', 'FCM v1 API error: ' . (isset($decoded['error']['message']) ? $decoded['error']['message'] : $resp));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return $resp;
|
||||
}
|
||||
}
|
||||
|
||||
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
+26
-1
@@ -124,6 +124,16 @@ class Driver_model extends CI_model
|
||||
}
|
||||
}
|
||||
|
||||
public function check_banned_by_email($email)
|
||||
{
|
||||
$stat = $this->db->query("SELECT id FROM driver WHERE status='3' AND email='" . $this->db->escape_str($email) . "'");
|
||||
if ($stat->num_rows() == 1) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function check_exist_phone_edit($id, $phone)
|
||||
{
|
||||
$cek = $this->db->query("SELECT no_telepon FROM driver where no_telepon='$phone' AND id!='$id'");
|
||||
@@ -242,6 +252,19 @@ class Driver_model extends CI_model
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update driver's FCM token (reg_id) so they receive order request notifications.
|
||||
*/
|
||||
public function update_driver_reg_id($id_driver, $reg_id)
|
||||
{
|
||||
if (empty($id_driver) || empty(trim((string) $reg_id))) {
|
||||
return false;
|
||||
}
|
||||
$this->db->where('id', $id_driver);
|
||||
$this->db->update('driver', array('reg_id' => trim((string) $reg_id)));
|
||||
return $this->db->affected_rows() >= 0;
|
||||
}
|
||||
|
||||
public function get_data_driver($condition)
|
||||
{
|
||||
$this->db->select('driver.*, saldo.saldo');
|
||||
@@ -862,7 +885,9 @@ class Driver_model extends CI_model
|
||||
$this->db->set('tempat_lahir', $data['tempat_lahir']);
|
||||
$this->db->set('tgl_lahir', $data['tgl_lahir']);
|
||||
$this->db->set('alamat_driver', $data['alamat_driver']);
|
||||
|
||||
if (isset($data['reg_id'])) {
|
||||
$this->db->set('reg_id', $data['reg_id']);
|
||||
}
|
||||
|
||||
$this->db->where('id', $data['id']);
|
||||
$this->db->update('driver', $data);
|
||||
|
||||
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
+162
-124
@@ -4,155 +4,193 @@ class notification_model extends CI_model
|
||||
{
|
||||
public function notif_cancel_user($id_driver, $id_transaksi, $token_user)
|
||||
{
|
||||
|
||||
$datanotif = array(
|
||||
'id_driver' => $id_driver,
|
||||
if ($this->is_token_empty($token_user) || !$this->is_valid_fcm_token($token_user)) {
|
||||
log_message('debug', 'notif_cancel_user: skip, no/invalid Firebase token for user');
|
||||
return true;
|
||||
}
|
||||
// Use FCM HTTP v1 via service account, not legacy keyfcm.
|
||||
$payload = array(
|
||||
'id_driver' => $id_driver,
|
||||
'id_transaksi' => $id_transaksi,
|
||||
'response' => '5',
|
||||
'type' => 1
|
||||
'response' => '5',
|
||||
'type' => 1,
|
||||
);
|
||||
$senderdata = array(
|
||||
'data' => $datanotif,
|
||||
'to' => $token_user
|
||||
);
|
||||
$headers = array(
|
||||
"Content-Type: application/json",
|
||||
"Authorization: key=" . keyfcm
|
||||
);
|
||||
$curl = curl_init();
|
||||
|
||||
curl_setopt_array($curl, array(
|
||||
CURLOPT_URL => "https://fcm.googleapis.com/fcm/send",
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_ENCODING => "",
|
||||
CURLOPT_MAXREDIRS => 10,
|
||||
CURLOPT_TIMEOUT => 30,
|
||||
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
|
||||
CURLOPT_CUSTOMREQUEST => "POST",
|
||||
CURLOPT_POSTFIELDS => json_encode($senderdata),
|
||||
CURLOPT_HTTPHEADER => $headers,
|
||||
));
|
||||
|
||||
$response = curl_exec($curl);
|
||||
$err = curl_error($curl);
|
||||
|
||||
curl_close($curl);
|
||||
return $response;
|
||||
$this->send_generic_to_token($token_user, $payload, array());
|
||||
return true;
|
||||
}
|
||||
|
||||
public function notif_cancel_driver($id_transaksi, $token_driver)
|
||||
{
|
||||
|
||||
$data = array(
|
||||
if ($this->is_token_empty($token_driver) || !$this->is_valid_fcm_token($token_driver)) {
|
||||
log_message('debug', 'notif_cancel_driver: skip, no/invalid Firebase token for driver');
|
||||
return true;
|
||||
}
|
||||
$payload = array(
|
||||
'id_transaksi' => $id_transaksi,
|
||||
'response' => '0',
|
||||
'type' => 1
|
||||
'response' => '0',
|
||||
'type' => 1,
|
||||
);
|
||||
$senderdata = array(
|
||||
'data' => $data,
|
||||
'to' => $token_driver
|
||||
);
|
||||
|
||||
$headers = array(
|
||||
"Content-Type: application/json",
|
||||
'Authorization: key=' . keyfcm
|
||||
);
|
||||
$curl = curl_init();
|
||||
|
||||
curl_setopt_array($curl, array(
|
||||
CURLOPT_URL => "https://fcm.googleapis.com/fcm/send",
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_ENCODING => "",
|
||||
CURLOPT_MAXREDIRS => 10,
|
||||
CURLOPT_TIMEOUT => 30,
|
||||
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
|
||||
CURLOPT_CUSTOMREQUEST => "POST",
|
||||
CURLOPT_POSTFIELDS => json_encode($senderdata),
|
||||
CURLOPT_HTTPHEADER => $headers,
|
||||
));
|
||||
|
||||
$response = curl_exec($curl);
|
||||
$err = curl_error($curl);
|
||||
|
||||
curl_close($curl);
|
||||
|
||||
return $response;
|
||||
$this->send_generic_to_token($token_driver, $payload, array());
|
||||
return true;
|
||||
}
|
||||
|
||||
public function send_notif($title, $message, $topic)
|
||||
/**
|
||||
* Check if token/target is empty (null, empty string, or whitespace).
|
||||
* Use before sending FCM to avoid sending when device has no token.
|
||||
*/
|
||||
private function is_token_empty($token)
|
||||
{
|
||||
return $token === null || trim((string) $token) === '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if string looks like a valid FCM v1 device token (not a placeholder).
|
||||
* Uses shared fcm_v1_is_valid_device_token helper.
|
||||
*/
|
||||
private function is_valid_fcm_token($token)
|
||||
{
|
||||
if (!function_exists('fcm_v1_is_valid_device_token')) {
|
||||
get_instance()->load->helper('fcm_v1_helper');
|
||||
}
|
||||
return fcm_v1_is_valid_device_token($token);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send notification via FCM HTTP v1 to a device token (reg_id, token, token_merchant).
|
||||
* Uses token API so reg_id can be used as FCM v1 target. Skips invalid/placeholder tokens.
|
||||
* @param string $target FCM device token (from driver.reg_id, pelanggan.token, etc.)
|
||||
* @return bool True on success or skip, false on failure
|
||||
*/
|
||||
public function send_notif($title, $message, $target)
|
||||
{
|
||||
if ($this->is_token_empty($target)) {
|
||||
log_message('debug', 'send_notif: skip, no token');
|
||||
return true;
|
||||
}
|
||||
if (!$this->is_valid_fcm_token($target)) {
|
||||
log_message('debug', 'send_notif: skip, invalid/placeholder FCM token');
|
||||
return true;
|
||||
}
|
||||
if (!function_exists('fcm_v1_validate_token')) {
|
||||
get_instance()->load->helper('fcm_v1_helper');
|
||||
}
|
||||
if (!fcm_v1_validate_token()) {
|
||||
log_message('error', 'send_notif: Firebase token not ready, skip send');
|
||||
return false;
|
||||
}
|
||||
$data = array(
|
||||
'title' => $title,
|
||||
'title' => $title,
|
||||
'message' => $message,
|
||||
'type' => 4
|
||||
'type' => 4,
|
||||
);
|
||||
$senderdata = array(
|
||||
'data' => $data,
|
||||
'to' => '/topics/' . $topic
|
||||
$options = array(
|
||||
'title' => $title,
|
||||
'body' => $message,
|
||||
);
|
||||
|
||||
$headers = array(
|
||||
'Content-Type : application/json',
|
||||
'Authorization: key=' . keyfcm
|
||||
);
|
||||
$curl = curl_init();
|
||||
|
||||
curl_setopt_array($curl, array(
|
||||
CURLOPT_URL => "https://fcm.googleapis.com/fcm/send",
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_ENCODING => "",
|
||||
CURLOPT_MAXREDIRS => 10,
|
||||
CURLOPT_TIMEOUT => 30,
|
||||
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
|
||||
CURLOPT_CUSTOMREQUEST => "POST",
|
||||
CURLOPT_POSTFIELDS => json_encode($senderdata),
|
||||
CURLOPT_HTTPHEADER => $headers,
|
||||
));
|
||||
|
||||
$response = curl_exec($curl);
|
||||
$err = curl_error($curl);
|
||||
|
||||
curl_close($curl);
|
||||
return $this->send_generic_to_token($target, $data, $options);
|
||||
}
|
||||
|
||||
public function send_notif_topup($title, $id, $message, $method, $token)
|
||||
{
|
||||
|
||||
if ($this->is_token_empty($token)) {
|
||||
log_message('debug', 'send_notif_topup: skip, no Firebase token for user id=' . $id);
|
||||
return;
|
||||
}
|
||||
if (!function_exists('fcm_v1_validate_token')) {
|
||||
get_instance()->load->helper('fcm_v1_helper');
|
||||
}
|
||||
if (!fcm_v1_validate_token()) {
|
||||
log_message('error', 'send_notif_topup: Firebase token not ready, skip send for user id=' . $id);
|
||||
return;
|
||||
}
|
||||
// Direct token notification for topup via HTTP v1.
|
||||
$data = array(
|
||||
'title' => $title,
|
||||
'id' => $id,
|
||||
'message' => $message,
|
||||
'title' => $title,
|
||||
'id' => $id,
|
||||
'message'=> $message,
|
||||
'method' => $method,
|
||||
'type' => 3
|
||||
'type' => 3,
|
||||
);
|
||||
$senderdata = array(
|
||||
'data' => $data,
|
||||
'to' => $token
|
||||
|
||||
$options = array(
|
||||
'title' => $title,
|
||||
'body' => $message,
|
||||
);
|
||||
$this->send_generic_to_token($token, $data, $options);
|
||||
}
|
||||
|
||||
$headers = array(
|
||||
'Content-Type : application/json',
|
||||
'Authorization: key=' . keyfcm
|
||||
);
|
||||
$curl = curl_init();
|
||||
/**
|
||||
* Send FCM via HTTP v1 API to a single device token.
|
||||
* Used by User and Driver apps (notification/send_generic).
|
||||
* $data must be flat key-value; values are stringified for FCM.
|
||||
*
|
||||
* @param string $target FCM device token
|
||||
* @param array $data Data payload (keys preserved; values cast to string)
|
||||
* @param array $options Optional 'title', 'body' for notification
|
||||
* @return bool True on success, false on failure
|
||||
*/
|
||||
public function send_generic_to_token($target, $data, $options = array())
|
||||
{
|
||||
if ($this->is_token_empty($target)) {
|
||||
log_message('debug', 'FCM v1 send_generic_to_token: skip, target token empty');
|
||||
return false;
|
||||
}
|
||||
if (!$this->is_valid_fcm_token($target)) {
|
||||
log_message('debug', 'FCM v1 send_generic_to_token: skip, invalid/placeholder token');
|
||||
return false;
|
||||
}
|
||||
if (!function_exists('fcm_v1_send')) {
|
||||
get_instance()->load->helper('fcm_v1_helper');
|
||||
}
|
||||
if (!fcm_v1_validate_token()) {
|
||||
log_message('error', 'FCM v1 send_generic_to_token: Firebase token not ready, skip send');
|
||||
return false;
|
||||
}
|
||||
$flat = array();
|
||||
foreach ($data as $k => $v) {
|
||||
if (is_array($v) || is_object($v)) {
|
||||
$flat[$k] = json_encode($v);
|
||||
} else {
|
||||
$flat[$k] = (string) $v;
|
||||
}
|
||||
}
|
||||
log_message('debug', 'FCM v1 send_generic_to_token target=' . substr((string)$target, 0, 20) . '... payload=' . json_encode($flat));
|
||||
$result = fcm_v1_send($target, $flat, false, $options);
|
||||
if ($result === false) {
|
||||
log_message('error', 'FCM v1 send_generic_to_token failed for target=' . substr((string)$target, 0, 20) . '...');
|
||||
}
|
||||
return $result !== false;
|
||||
}
|
||||
|
||||
curl_setopt_array($curl, array(
|
||||
CURLOPT_URL => "https://fcm.googleapis.com/fcm/send",
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_ENCODING => "",
|
||||
CURLOPT_MAXREDIRS => 10,
|
||||
CURLOPT_TIMEOUT => 30,
|
||||
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
|
||||
CURLOPT_CUSTOMREQUEST => "POST",
|
||||
CURLOPT_POSTFIELDS => json_encode($senderdata),
|
||||
CURLOPT_HTTPHEADER => $headers,
|
||||
));
|
||||
|
||||
$response = curl_exec($curl);
|
||||
$err = curl_error($curl);
|
||||
|
||||
curl_close($curl);
|
||||
/**
|
||||
* Send FCM via HTTP v1 API to a topic.
|
||||
*
|
||||
* @param string $target Topic name (without /topics/ prefix)
|
||||
* @param array $data Data payload
|
||||
* @param array $options Optional 'title', 'body'
|
||||
* @return bool True on success, false on failure
|
||||
*/
|
||||
public function send_generic_to_topic($target, $data, $options = array())
|
||||
{
|
||||
if (!function_exists('fcm_v1_send')) {
|
||||
get_instance()->load->helper('fcm_v1_helper');
|
||||
}
|
||||
if (!fcm_v1_validate_token()) {
|
||||
log_message('error', 'FCM v1 send_generic_to_topic: Firebase token not ready, skip send');
|
||||
return false;
|
||||
}
|
||||
$flat = array();
|
||||
foreach ($data as $k => $v) {
|
||||
if (is_array($v) || is_object($v)) {
|
||||
$flat[$k] = json_encode($v);
|
||||
} else {
|
||||
$flat[$k] = (string) $v;
|
||||
}
|
||||
}
|
||||
log_message('debug', 'FCM v1 send_generic_to_topic topic=' . (string)$target . ' payload=' . json_encode($flat));
|
||||
$result = fcm_v1_send($target, $flat, true, $options);
|
||||
if ($result === false) {
|
||||
log_message('error', 'FCM v1 send_generic_to_topic failed for topic=' . (string)$target);
|
||||
}
|
||||
return $result !== false;
|
||||
}
|
||||
}
|
||||
|
||||
Regular → Executable
Regular → Executable
Regular → Executable
+104
-18
@@ -269,19 +269,45 @@ class Pelanggan_model extends CI_model
|
||||
return true;
|
||||
}
|
||||
|
||||
public function get_driver_ride($lat, $lng, $fitur)
|
||||
/**
|
||||
* Get nearby drivers for ride: purely by GPS distance, no region/wilayah.
|
||||
* Uses config_driver (driver's real-time lat/long from app) and user (lat, lng).
|
||||
* Optional $radius_km (1–100): when set, used as search radius; else fitur.jarak_minimum with min 10 km.
|
||||
* Optimized: bounding-box pre-filter + Haversine + LIMIT 50.
|
||||
*/
|
||||
public function get_driver_ride($lat, $lng, $fitur, $radius_km = null)
|
||||
{
|
||||
$url_foto = base_url() . 'images/fotodriver/';
|
||||
$lat = (float) $lat;
|
||||
$lng = (float) $lng;
|
||||
$fitur = (int) $fitur;
|
||||
|
||||
if ($radius_km !== null && $radius_km > 0) {
|
||||
$radius_km = max(1, min(100, (float) $radius_km));
|
||||
}
|
||||
|
||||
$box_km = isset($radius_km) ? $radius_km : 50;
|
||||
$delta_lat = $box_km / 111.0;
|
||||
$cos_lat = max(0.01, cos(deg2rad($lat)));
|
||||
$delta_lng = $box_km / (111.0 * $cos_lat);
|
||||
$lat_min = $lat - $delta_lat;
|
||||
$lat_max = $lat + $delta_lat;
|
||||
$lng_min = $lng - $delta_lng;
|
||||
$lng_max = $lng + $delta_lng;
|
||||
|
||||
$having_radius = isset($radius_km)
|
||||
? (float) $radius_km
|
||||
: 'GREATEST(COALESCE(f.jarak_minimum, 10), 10)';
|
||||
|
||||
$result = $this->db->query("
|
||||
SELECT f.jarak_minimum, f.wallet_minimum, d.id as id, d.nama_driver, ld.latitude, ld.longitude, ld.bearing, ld.update_at,
|
||||
k.merek, k.nomor_kendaraan, k.warna, k.tipe, s.saldo,
|
||||
d.no_telepon, CONCAT('$url_foto', d.foto, '') as foto, d.reg_id, dj.driver_job,
|
||||
(6371 * acos(cos(radians($lat)) * cos(radians( ld.latitude ))"
|
||||
. " * cos(radians(ld.longitude) - radians($lng))"
|
||||
. " + sin(radians($lat)) * sin( radians(ld.latitude)))) AS distance
|
||||
FROM config_driver ld, driver d, driver_job dj, kendaraan k, saldo s,fitur f
|
||||
WHERE ld.id_driver = d.id
|
||||
(6371 * acos(cos(radians($lat)) * cos(radians(ld.latitude))
|
||||
* cos(radians(ld.longitude) - radians($lng))
|
||||
+ sin(radians($lat)) * sin(radians(ld.latitude)))) AS distance
|
||||
FROM config_driver ld, driver d, driver_job dj, kendaraan k, saldo s, fitur f
|
||||
WHERE ld.id_driver = d.id
|
||||
AND f.id_fitur = $fitur
|
||||
AND ld.status = '1'
|
||||
AND dj.id = d.job
|
||||
@@ -290,35 +316,88 @@ class Pelanggan_model extends CI_model
|
||||
AND k.id_k = d.kendaraan
|
||||
AND s.id_user = d.id
|
||||
AND s.saldo > f.wallet_minimum
|
||||
HAVING distance <= f.jarak_minimum
|
||||
ORDER BY distance ASC");
|
||||
AND ld.latitude BETWEEN $lat_min AND $lat_max
|
||||
AND ld.longitude BETWEEN $lng_min AND $lng_max
|
||||
HAVING distance <= $having_radius
|
||||
ORDER BY distance ASC
|
||||
LIMIT 50");
|
||||
$count = $result->num_rows();
|
||||
log_message('debug', 'get_driver_ride: fitur=' . $fitur . ' lat=' . $lat . ' lng=' . $lng . ' drivers_found=' . $count);
|
||||
if ($count === 0) {
|
||||
$this->log_driver_diagnostic('ride', $lat, $lng, $fitur, $lat_min, $lat_max, $lng_min, $lng_max, $radius_km);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function get_driver_car($lat, $lng, $fitur)
|
||||
/**
|
||||
* Diagnostic logging when 0 drivers found: counts online drivers, in-box, by job, etc.
|
||||
*/
|
||||
private function log_driver_diagnostic($type, $lat, $lng, $fitur, $lat_min, $lat_max, $lng_min, $lng_max, $radius_km)
|
||||
{
|
||||
$r_online = $this->db->query("SELECT COUNT(*) as c FROM config_driver WHERE status='1'")->row();
|
||||
$cnt_online = $r_online ? (int) $r_online->c : 0;
|
||||
$r_box = $this->db->query("SELECT COUNT(*) as c FROM config_driver ld JOIN driver d ON ld.id_driver=d.id WHERE ld.status='1' AND d.status='1' AND ld.latitude BETWEEN " . (float)$lat_min . " AND " . (float)$lat_max . " AND ld.longitude BETWEEN " . (float)$lng_min . " AND " . (float)$lng_max)->row();
|
||||
$cnt_in_box = $r_box ? (int) $r_box->c : 0;
|
||||
$fitur_row = $this->db->query("SELECT driver_job, jarak_minimum, wallet_minimum FROM fitur WHERE id_fitur=" . (int)$fitur)->row();
|
||||
$driver_job = $fitur_row ? $fitur_row->driver_job : null;
|
||||
$cnt_job = 0;
|
||||
if ($driver_job !== null) {
|
||||
$r_job = $this->db->query("SELECT COUNT(*) as c FROM driver WHERE status='1' AND job=" . (int)$driver_job)->row();
|
||||
$cnt_job = $r_job ? (int) $r_job->c : 0;
|
||||
}
|
||||
$fitur_exists = $fitur_row ? 'yes' : 'NO_FITUR_NOT_FOUND';
|
||||
log_message('debug', 'get_driver_' . $type . '_diagnostic: fitur=' . $fitur . ' fitur_exists=' . $fitur_exists . ' driver_job=' . ($driver_job !== null ? $driver_job : 'n/a') . ' radius_km=' . ($radius_km !== null ? $radius_km : 'default') . ' online_drivers=' . $cnt_online . ' in_box=' . $cnt_in_box . ' with_job=' . $cnt_job);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get nearby drivers for car: purely by GPS distance, no region/wilayah.
|
||||
* Optional $radius_km (1–100); else 10 km. Optimized: bounding-box + LIMIT 50.
|
||||
*/
|
||||
public function get_driver_car($lat, $lng, $fitur, $radius_km = null)
|
||||
{
|
||||
$range = 10;
|
||||
$url_foto = base_url() . 'images/fotodriver/';
|
||||
$lat = (float) $lat;
|
||||
$lng = (float) $lng;
|
||||
$fitur = (int) $fitur;
|
||||
$range = ($radius_km !== null && $radius_km > 0)
|
||||
? max(1, min(100, (float) $radius_km))
|
||||
: 10;
|
||||
|
||||
$delta_lat = $range / 111.0;
|
||||
$cos_lat = max(0.01, cos(deg2rad($lat)));
|
||||
$delta_lng = $range / (111.0 * $cos_lat);
|
||||
$lat_min = $lat - $delta_lat;
|
||||
$lat_max = $lat + $delta_lat;
|
||||
$lng_min = $lng - $delta_lng;
|
||||
$lng_max = $lng + $delta_lng;
|
||||
|
||||
$result = $this->db->query("
|
||||
SELECT f.jarak_minimum, f.wallet_minimum, d.id as id, d.nama_driver, ld.latitude, ld.longitude, ld.bearing, ld.update_at,
|
||||
k.merek, k.nomor_kendaraan, k.warna, k.tipe, s.saldo,
|
||||
d.no_telepon, CONCAT('$url_foto', d.foto, '') as foto, d.reg_id, dj.driver_job,
|
||||
(6371 * acos(cos(radians($lat)) * cos(radians( ld.latitude ))"
|
||||
. " * cos(radians(ld.longitude) - radians($lng))"
|
||||
. " + sin(radians($lat)) * sin( radians(ld.latitude)))) AS distance
|
||||
FROM config_driver ld, driver d, driver_job dj, kendaraan k, saldo s,fitur f
|
||||
WHERE ld.id_driver = d.id
|
||||
(6371 * acos(cos(radians($lat)) * cos(radians(ld.latitude))
|
||||
* cos(radians(ld.longitude) - radians($lng))
|
||||
+ sin(radians($lat)) * sin(radians(ld.latitude)))) AS distance
|
||||
FROM config_driver ld, driver d, driver_job dj, kendaraan k, saldo s, fitur f
|
||||
WHERE ld.id_driver = d.id
|
||||
AND f.id_fitur = $fitur
|
||||
AND ld.status = '1'
|
||||
AND dj.id = d.job
|
||||
AND d.job = '2'
|
||||
AND d.job = f.driver_job
|
||||
AND d.status = '1'
|
||||
AND k.id_k = d.kendaraan
|
||||
AND s.id_user = d.id
|
||||
AND s.saldo > 500
|
||||
AND s.saldo > GREATEST(COALESCE(f.wallet_minimum, 0), 500)
|
||||
AND ld.latitude BETWEEN $lat_min AND $lat_max
|
||||
AND ld.longitude BETWEEN $lng_min AND $lng_max
|
||||
HAVING distance <= $range
|
||||
ORDER BY distance ASC");
|
||||
ORDER BY distance ASC
|
||||
LIMIT 50");
|
||||
$count = $result->num_rows();
|
||||
log_message('debug', 'get_driver_car: fitur=' . $fitur . ' lat=' . $lat . ' lng=' . $lng . ' drivers_found=' . $count);
|
||||
if ($count === 0) {
|
||||
$this->log_driver_diagnostic('car', $lat, $lng, $fitur, $lat_min, $lat_max, $lng_min, $lng_max, $radius_km);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
@@ -467,6 +546,7 @@ class Pelanggan_model extends CI_model
|
||||
$this->delete_transaksi($dataTrans['id_transaksi']);
|
||||
$stat = FALSE;
|
||||
}
|
||||
log_message('debug', 'check_status: id_transaksi=' . $dataTrans['id_transaksi'] . ' raw_status=' . $cek->row('status') . ' stat=' . ($stat ? 'TRUE' : 'FALSE'));
|
||||
$dataCheck = array(
|
||||
'message' => 'check status',
|
||||
'status' => $stat,
|
||||
@@ -1273,6 +1353,10 @@ class Pelanggan_model extends CI_model
|
||||
return $this->db->get('category_merchant');
|
||||
}
|
||||
|
||||
/**
|
||||
* Merchant nearby: purely by GPS (merchant lat/long vs user lat/long), no region.
|
||||
* Distance <= fitur.jarak_minimum.
|
||||
*/
|
||||
public function merchantnearby($long, $lat)
|
||||
{
|
||||
$this->db->select("merchant.id_merchant , merchant.nama_merchant , merchant.alamat_merchant , merchant.rate_merchant, merchant.latitude_merchant , merchant.longitude_merchant , merchant.jam_buka , merchant.jam_tutup ,
|
||||
@@ -1329,6 +1413,7 @@ class Pelanggan_model extends CI_model
|
||||
return $data;
|
||||
}
|
||||
|
||||
/** Merchant promo nearby: purely GPS, no region. */
|
||||
public function merchantpromo($long, $lat)
|
||||
{
|
||||
$this->db->select("merchant.id_merchant , merchant.nama_merchant , merchant.alamat_merchant , merchant.rate_merchant, merchant.latitude_merchant , merchant.longitude_merchant , merchant.jam_buka , merchant.jam_tutup ,
|
||||
@@ -1411,6 +1496,7 @@ class Pelanggan_model extends CI_model
|
||||
return $this->db->get('merchant');
|
||||
}
|
||||
|
||||
/** All merchant nearby by fitur: purely GPS (merchant lat/long vs user), no region. */
|
||||
public function allmerchantnearby($long, $lat, $fitur)
|
||||
{
|
||||
$this->db->select("merchant.id_merchant , merchant.nama_merchant , merchant.alamat_merchant , merchant.rate_merchant, merchant.latitude_merchant , merchant.longitude_merchant , merchant.jam_buka , merchant.jam_tutup ,
|
||||
|
||||
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
+7
-34
@@ -146,39 +146,10 @@ class wallet_model extends CI_model
|
||||
|
||||
public function send_notif($title, $message, $topic)
|
||||
{
|
||||
|
||||
$data = array(
|
||||
'title' => $title,
|
||||
'message' => $message,
|
||||
'type' => 3
|
||||
);
|
||||
$senderdata = array(
|
||||
'data' => $data,
|
||||
'to' => $topic
|
||||
);
|
||||
|
||||
$headers = array(
|
||||
'Content-Type : application/json',
|
||||
'Authorization: key=' . keyfcm
|
||||
);
|
||||
$curl = curl_init();
|
||||
|
||||
curl_setopt_array($curl, array(
|
||||
CURLOPT_URL => "https://fcm.googleapis.com/fcm/send",
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_ENCODING => "",
|
||||
CURLOPT_MAXREDIRS => 10,
|
||||
CURLOPT_TIMEOUT => 30,
|
||||
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
|
||||
CURLOPT_CUSTOMREQUEST => "POST",
|
||||
CURLOPT_POSTFIELDS => json_encode($senderdata),
|
||||
CURLOPT_HTTPHEADER => $headers,
|
||||
));
|
||||
|
||||
$response = curl_exec($curl);
|
||||
$err = curl_error($curl);
|
||||
|
||||
curl_close($curl);
|
||||
// Delegate to Notification_model, which uses FCM HTTP v1 + service account.
|
||||
$CI = &get_instance();
|
||||
$CI->load->model('notification_model', 'notif');
|
||||
$CI->notif->send_notif($title, $message, $topic);
|
||||
}
|
||||
|
||||
public function updatesaldowallet($data)
|
||||
@@ -319,7 +290,9 @@ class wallet_model extends CI_model
|
||||
|
||||
$title = 'Dibatalkan';
|
||||
$desc = 'Pembayaran Kamu telah Dibatalkan';
|
||||
$this->Notification_model->send_notif_topup($title, $wl['id_user'], $desc, $wl['invoice'], $token);
|
||||
if ($token !== null && trim((string) $token) !== '') {
|
||||
$this->Notification_model->send_notif_topup($title, $wl['id_user'], $desc, $wl['invoice'], $token);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Regular → Executable
Regular → Executable
Regular → Executable
+6
-1
@@ -5,11 +5,16 @@
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<h4 class="card-title">Kirim Notifikasi</h4>
|
||||
<?php if ($this->session->flashdata()) : ?>
|
||||
<?php if ($this->session->flashdata('send')) : ?>
|
||||
<div class="alert alert-success" role="alert">
|
||||
<?php echo $this->session->flashdata('send'); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php if ($this->session->flashdata('error')) : ?>
|
||||
<div class="alert alert-danger" role="alert">
|
||||
<?php echo $this->session->flashdata('error'); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?= form_open_multipart('appnotification/send'); ?>
|
||||
<div class="form-group">
|
||||
<label for="newscategory">Kirim Ke</label>
|
||||
|
||||
Regular → Executable
Regular → Executable
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user