demo transaksi
This commit is contained in:
@@ -44,6 +44,8 @@ $config['fcm_credentials_json'] = '';
|
||||
$config['fcm_credentials_path'] = FCPATH . 'ngojol-trial-firebase-adminsdk-lc81n-00c9e935db.json';
|
||||
$config['fcm_limit_per_hour'] = 100;
|
||||
$config['fcm_limit_per_day'] = 500;
|
||||
// When true, Pelanggan/Merchant/Driver login does not require an FCM device token (e.g. API tests).
|
||||
$config['fcm_login_allow_no_device_token'] = false;
|
||||
$config['maps_limit_per_hour'] = 1000;
|
||||
$config['maps_limit_per_day'] = 5000;
|
||||
|
||||
@@ -59,6 +61,10 @@ define('FCM_CREDENTIALS_JSON', $config['fcm_credentials_json']);
|
||||
define('FCM_CREDENTIALS_PATH', $config['fcm_credentials_path']);
|
||||
define('FCM_LIMIT_PER_HOUR', $config['fcm_limit_per_hour']);
|
||||
define('FCM_LIMIT_PER_DAY', $config['fcm_limit_per_day']);
|
||||
define(
|
||||
'FCM_LOGIN_ALLOW_NO_DEVICE_TOKEN',
|
||||
filter_var($config['fcm_login_allow_no_device_token'], FILTER_VALIDATE_BOOLEAN)
|
||||
);
|
||||
define('MAPS_LIMIT_PER_HOUR', $config['maps_limit_per_hour']);
|
||||
define('MAPS_LIMIT_PER_DAY', $config['maps_limit_per_day']);
|
||||
|
||||
|
||||
@@ -6,9 +6,14 @@ defined('BASEPATH') or exit('No direct script access allowed');
|
||||
| Legacy FCM config – DO NOT USE
|
||||
|--------------------------------------------------------------------------
|
||||
| Push notifications use FCM HTTP v1 only (see application/helpers/fcm_v1_helper.php).
|
||||
| Set FCM_CREDENTIALS_PATH or FCM_CREDENTIALS_JSON and FCM_PROJECT_ID in the environment.
|
||||
| This file exists so the deprecated application/libraries/Fcm.php does not
|
||||
| load a missing config; the legacy library must not be used (no legacy API key).
|
||||
| Service account path/project id live in application/config/config.php (constants
|
||||
| FCM_CREDENTIALS_PATH, FCM_CREDENTIALS_JSON, FCM_PROJECT_ID). This file exists so the
|
||||
| deprecated application/libraries/Fcm.php does not load a missing config; do not
|
||||
| use the legacy library (no legacy API key).
|
||||
|
|
||||
| Mobile login (Pelanggan/login, Merchant/login, Driver/login) expects a device token
|
||||
| from the APK (Firebase getToken). To allow clients without a token (e.g. API tests),
|
||||
| set $config['fcm_login_allow_no_device_token'] = true in config.php.
|
||||
*/
|
||||
$config['fcm_api_key'] = '';
|
||||
$config['fcm_api_send_address'] = 'https://fcm.googleapis.com/fcm/send';
|
||||
|
||||
@@ -11,14 +11,15 @@ class appnotification extends CI_Controller
|
||||
is_logged_in();
|
||||
|
||||
$this->load->model('notification_model', 'notif');
|
||||
$this->load->model('Pelanggan_model', 'pelanggan_model');
|
||||
$this->load->library('form_validation');
|
||||
}
|
||||
|
||||
public function index()
|
||||
{
|
||||
|
||||
$data['pelanggan_list'] = $this->pelanggan_model->get_all_for_notification_picker();
|
||||
$this->load->view('includes/header');
|
||||
$this->load->view('appnotification/index');
|
||||
$this->load->view('appnotification/index', $data);
|
||||
$this->load->view('includes/footer');
|
||||
}
|
||||
|
||||
@@ -33,10 +34,57 @@ class appnotification extends CI_Controller
|
||||
return;
|
||||
}
|
||||
|
||||
$topic = $this->input->post('topic');
|
||||
$title = $this->input->post('title');
|
||||
$message = $this->input->post('message');
|
||||
$send_target = $this->input->post('send_target');
|
||||
|
||||
if ($send_target === 'users') {
|
||||
$user_ids = $this->input->post('user_ids');
|
||||
if (!is_array($user_ids)) {
|
||||
$user_ids = array();
|
||||
}
|
||||
$user_ids = array_unique(array_filter(array_map('intval', $user_ids)));
|
||||
if (empty($user_ids)) {
|
||||
$this->session->set_flashdata('error', 'Pilih minimal satu pengguna (user).');
|
||||
redirect('appnotification/index');
|
||||
return;
|
||||
}
|
||||
$sent = 0;
|
||||
$skipped = 0;
|
||||
foreach ($user_ids as $uid) {
|
||||
if ($uid <= 0) {
|
||||
continue;
|
||||
}
|
||||
$row = $this->pelanggan_model->get_notification_row_by_id($uid);
|
||||
if (!$row) {
|
||||
$skipped++;
|
||||
continue;
|
||||
}
|
||||
$tok = isset($row->token) ? trim((string) $row->token) : '';
|
||||
if ($tok === '' || !fcm_v1_is_valid_device_token($tok)) {
|
||||
$skipped++;
|
||||
continue;
|
||||
}
|
||||
if ($this->notif->send_notif($title, $message, $tok)) {
|
||||
$sent++;
|
||||
} else {
|
||||
$skipped++;
|
||||
}
|
||||
}
|
||||
if ($sent > 0) {
|
||||
$msg = 'Notifikasi terkirim ke ' . $sent . ' pengguna.';
|
||||
if ($skipped > 0) {
|
||||
$msg .= ' ' . $skipped . ' dilewati (tanpa token FCM valid atau gagal kirim).';
|
||||
}
|
||||
$this->session->set_flashdata('send', $msg);
|
||||
} else {
|
||||
$this->session->set_flashdata('error', 'Tidak ada notifikasi terkirim. Pastikan pengguna memiliki token FCM valid (login dari aplikasi).');
|
||||
}
|
||||
redirect('appnotification/index');
|
||||
return;
|
||||
}
|
||||
|
||||
$topic = $this->input->post('topic');
|
||||
$ok = $this->notif->send_notif($title, $message, $topic);
|
||||
if ($ok) {
|
||||
$this->session->set_flashdata('send', 'Notifikasi berhasil dikirim');
|
||||
|
||||
@@ -76,10 +76,24 @@ class Driver extends REST_Controller
|
||||
|
||||
$data = file_get_contents("php://input");
|
||||
$decoded_data = json_decode($data);
|
||||
if (!$decoded_data || !isset($decoded_data->password)) {
|
||||
$this->response(array('code' => '400', 'message' => 'Invalid request', 'data' => []), 200);
|
||||
return;
|
||||
}
|
||||
if (function_exists('fcm_v1_validate_login_device_token_from_app')) {
|
||||
$fcm_err = fcm_v1_validate_login_device_token_from_app($decoded_data);
|
||||
if (is_array($fcm_err)) {
|
||||
$this->response(
|
||||
array('code' => $fcm_err['code'], 'message' => $fcm_err['message'], 'data' => []),
|
||||
200
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// 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;
|
||||
$token = function_exists('fcm_v1_device_token_from_request')
|
||||
? fcm_v1_device_token_from_request($decoded_data)
|
||||
: '';
|
||||
$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;
|
||||
@@ -149,8 +163,10 @@ 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) : '';
|
||||
// When driver sends valid FCM token with location, update so they receive order requests.
|
||||
$reg_id = function_exists('fcm_v1_device_token_from_request')
|
||||
? fcm_v1_device_token_from_request($decoded_data)
|
||||
: (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);
|
||||
}
|
||||
@@ -372,6 +388,22 @@ class Driver extends REST_Controller
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Persist driver accept exchange on transaksi row (admin order detail API log).
|
||||
*/
|
||||
private function log_driver_accept_api($id_transaksi, $raw_body, $response_message)
|
||||
{
|
||||
$id_transaksi = (int) $id_transaksi;
|
||||
if ($id_transaksi <= 0) {
|
||||
return;
|
||||
}
|
||||
$line = json_encode(array(
|
||||
'driver_request_raw' => $raw_body,
|
||||
'backend_response' => $response_message,
|
||||
), JSON_UNESCAPED_UNICODE);
|
||||
$this->Pelanggan_model->append_transaksi_driver_request_log($id_transaksi, $line);
|
||||
}
|
||||
|
||||
function accept_post()
|
||||
{
|
||||
if (!isset($_SERVER['PHP_AUTH_USER'])) {
|
||||
@@ -383,6 +415,7 @@ class Driver extends REST_Controller
|
||||
$data = file_get_contents("php://input");
|
||||
$dec_data = json_decode($data);
|
||||
log_message('debug', 'accept_post: payload=' . $data);
|
||||
$tid_for_log = (is_object($dec_data) && isset($dec_data->id_transaksi)) ? (int) $dec_data->id_transaksi : 0;
|
||||
|
||||
$data_req = array(
|
||||
'id_driver' => $dec_data->id,
|
||||
@@ -390,13 +423,13 @@ class Driver extends REST_Controller
|
||||
);
|
||||
|
||||
$condition = array(
|
||||
'id_driver' => $dec_data->id,
|
||||
'status' => '1'
|
||||
'id_driver' => $dec_data->id
|
||||
);
|
||||
|
||||
$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) {
|
||||
$driver_status = $cek_login->num_rows() > 0 ? (string) $cek_login->row('status') : '';
|
||||
log_message('debug', 'accept_post: get_status_driver rows=' . $cek_login->num_rows() . ' status=' . $driver_status);
|
||||
if ($cek_login->num_rows() > 0 && ($driver_status === '1' || $driver_status === '4')) {
|
||||
|
||||
$acc_req = $this->Driver_model->accept_request($data_req);
|
||||
log_message('debug', 'accept_post: accept_request result=' . json_encode($acc_req));
|
||||
@@ -405,6 +438,7 @@ class Driver extends REST_Controller
|
||||
'message' => 'berhasil',
|
||||
'data' => 'berhasil'
|
||||
);
|
||||
$this->log_driver_accept_api($tid_for_log, $data, $message);
|
||||
$this->response($message, 200);
|
||||
} else {
|
||||
if ($acc_req['data'] == 'canceled') {
|
||||
@@ -412,12 +446,14 @@ class Driver extends REST_Controller
|
||||
'message' => 'canceled',
|
||||
'data' => 'canceled'
|
||||
);
|
||||
$this->log_driver_accept_api($tid_for_log, $data, $message);
|
||||
$this->response($message, 200);
|
||||
} else {
|
||||
$message = array(
|
||||
'message' => 'unknown fail',
|
||||
'data' => 'canceled'
|
||||
);
|
||||
$this->log_driver_accept_api($tid_for_log, $data, $message);
|
||||
$this->response($message, 200);
|
||||
}
|
||||
}
|
||||
@@ -426,6 +462,7 @@ class Driver extends REST_Controller
|
||||
'message' => 'unknown fail',
|
||||
'data' => 'canceled'
|
||||
);
|
||||
$this->log_driver_accept_api($tid_for_log, $data, $message);
|
||||
$this->response($message, 200);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,9 +65,31 @@ class Merchant extends REST_Controller
|
||||
|
||||
$data = file_get_contents("php://input");
|
||||
$decoded_data = json_decode($data);
|
||||
$no_telepon_val =
|
||||
isset($decoded_data->no_telepon) ? trim((string)$decoded_data->no_telepon) : '';
|
||||
$email_val = isset($decoded_data->email)
|
||||
? trim((string)$decoded_data->email)
|
||||
: '';
|
||||
|
||||
if (!$decoded_data || !isset($decoded_data->password) || ($no_telepon_val === '' && $email_val === '')) {
|
||||
$this->response(array('code' => '400', 'message' => 'Invalid request', 'data' => []), 200);
|
||||
return;
|
||||
}
|
||||
$login_by_phone = $no_telepon_val !== '';
|
||||
if (function_exists('fcm_v1_validate_login_device_token_from_app')) {
|
||||
$fcm_err = fcm_v1_validate_login_device_token_from_app($decoded_data);
|
||||
if (is_array($fcm_err)) {
|
||||
$this->response(
|
||||
array('code' => $fcm_err['code'], 'message' => $fcm_err['message'], '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;
|
||||
$token = function_exists('fcm_v1_device_token_from_request')
|
||||
? fcm_v1_device_token_from_request($decoded_data)
|
||||
: '';
|
||||
$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;
|
||||
@@ -75,10 +97,18 @@ class Merchant extends REST_Controller
|
||||
|
||||
$condition = array(
|
||||
'password' => sha1($decoded_data->password),
|
||||
'telepon_mitra' => $decoded_data->no_telepon,
|
||||
//'token' => $decoded_data->token
|
||||
);
|
||||
$check_banned = $this->Merchantapi_model->check_banned($decoded_data->no_telepon);
|
||||
|
||||
if ($login_by_phone) {
|
||||
$condition['telepon_mitra'] = $no_telepon_val;
|
||||
} else {
|
||||
$condition['email_mitra'] = $email_val;
|
||||
}
|
||||
|
||||
$check_banned = $login_by_phone
|
||||
? $this->Merchantapi_model->check_banned($no_telepon_val)
|
||||
: $this->Merchantapi_model->check_banned_by_email($email_val);
|
||||
if ($check_banned) {
|
||||
$message = array(
|
||||
'message' => 'banned',
|
||||
@@ -90,7 +120,19 @@ class Merchant extends REST_Controller
|
||||
$message = array();
|
||||
if ($cek_login->num_rows() > 0) {
|
||||
if (!empty($reg_id)) {
|
||||
$this->Merchantapi_model->edit_profile_token($reg_id, $decoded_data->no_telepon);
|
||||
$loginRow = $cek_login->row();
|
||||
$phone_for_token = '';
|
||||
if ($login_by_phone) {
|
||||
$phone_for_token = $no_telepon_val;
|
||||
} else if (!empty($loginRow) && isset($loginRow->telepon_merchant) && $loginRow->telepon_merchant !== '') {
|
||||
$phone_for_token = $loginRow->telepon_merchant;
|
||||
} else if (!empty($loginRow) && isset($loginRow->telepon_mitra) && $loginRow->telepon_mitra !== '') {
|
||||
$phone_for_token = $loginRow->telepon_mitra;
|
||||
}
|
||||
|
||||
if ($phone_for_token !== '') {
|
||||
$this->Merchantapi_model->edit_profile_token($reg_id, $phone_for_token);
|
||||
}
|
||||
}
|
||||
$get_pelanggan = $this->Merchantapi_model->get_data_merchant($condition);
|
||||
$message = array(
|
||||
@@ -102,7 +144,7 @@ class Merchant extends REST_Controller
|
||||
} else {
|
||||
$message = array(
|
||||
'code' => '404',
|
||||
'message' => 'nomor hp atau password salah!',
|
||||
'message' => 'nomor hp/email atau password salah!',
|
||||
'data' => []
|
||||
);
|
||||
$this->response($message, 200);
|
||||
@@ -450,24 +492,24 @@ class Merchant 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(
|
||||
|
||||
@@ -18,6 +18,71 @@ class Pelanggan extends REST_Controller
|
||||
date_default_timezone_set('Asia/Jakarta');
|
||||
}
|
||||
|
||||
/**
|
||||
* Structured API request log for order-related endpoints.
|
||||
*/
|
||||
private function log_order_api_request($endpoint, $rawBody)
|
||||
{
|
||||
log_message('debug', '[ORDER_API][' . $endpoint . '][REQUEST] ' . $rawBody);
|
||||
}
|
||||
|
||||
/**
|
||||
* Structured API response log for order-related endpoints.
|
||||
*/
|
||||
private function log_order_api_response($endpoint, $responsePayload)
|
||||
{
|
||||
log_message('debug', '[ORDER_API][' . $endpoint . '][RESPONSE] ' . json_encode($responsePayload));
|
||||
}
|
||||
|
||||
/**
|
||||
* Log candidate drivers targeted by customer order flow.
|
||||
*/
|
||||
private function log_order_driver_targets($endpoint, $idTransaksi, $driverList)
|
||||
{
|
||||
$ids = array();
|
||||
if (is_array($driverList)) {
|
||||
foreach ($driverList as $d) {
|
||||
if (is_object($d) && isset($d->id)) {
|
||||
$ids[] = (string) $d->id;
|
||||
} else if (is_array($d) && isset($d['id'])) {
|
||||
$ids[] = (string) $d['id'];
|
||||
}
|
||||
}
|
||||
}
|
||||
log_message(
|
||||
'debug',
|
||||
'[ORDER_API][' . $endpoint . '][DRIVER_TARGETS] id_transaksi=' . $idTransaksi .
|
||||
' total=' . count($ids) . ' driver_ids=' . implode(',', $ids)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store raw request/response on transaksi row for dashboard detail (requires DB columns).
|
||||
*/
|
||||
private function save_order_creation_logs($id_transaksi, $raw_request, $response_payload, $driver_targets)
|
||||
{
|
||||
$id_transaksi = (int) $id_transaksi;
|
||||
if ($id_transaksi <= 0) {
|
||||
return;
|
||||
}
|
||||
$rows = array();
|
||||
if (is_array($driver_targets)) {
|
||||
foreach ($driver_targets as $d) {
|
||||
$rows[] = json_decode(json_encode($d), true);
|
||||
}
|
||||
}
|
||||
$backend_driver = json_encode(array(
|
||||
'note' => 'Candidate drivers from get_data_driver_histroy after order create; client apps may use Firebase/FCM for dispatch.',
|
||||
'candidate_drivers' => $rows,
|
||||
), JSON_UNESCAPED_UNICODE);
|
||||
$this->Pelanggan_model->save_transaksi_api_log(
|
||||
$id_transaksi,
|
||||
$raw_request,
|
||||
json_encode($response_payload, JSON_UNESCAPED_UNICODE),
|
||||
$backend_driver
|
||||
);
|
||||
}
|
||||
|
||||
function index_get()
|
||||
{
|
||||
$this->response("Api for Ontime!", 200);
|
||||
@@ -120,9 +185,20 @@ class Pelanggan extends REST_Controller
|
||||
$this->response(array('code' => '400', 'message' => 'Invalid request', 'data' => []), 200);
|
||||
return;
|
||||
}
|
||||
if (function_exists('fcm_v1_validate_login_device_token_from_app')) {
|
||||
$fcm_err = fcm_v1_validate_login_device_token_from_app($decoded_data);
|
||||
if (is_array($fcm_err)) {
|
||||
$this->response(
|
||||
array('code' => $fcm_err['code'], 'message' => $fcm_err['message'], '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;
|
||||
$token = function_exists('fcm_v1_device_token_from_request')
|
||||
? fcm_v1_device_token_from_request($decoded_data)
|
||||
: '';
|
||||
$reg_id = array();
|
||||
if ($token !== '' && function_exists('fcm_v1_is_valid_device_token') && fcm_v1_is_valid_device_token($token)) {
|
||||
$reg_id['token'] = $token;
|
||||
@@ -236,7 +312,9 @@ class Pelanggan extends REST_Controller
|
||||
// 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) : '';
|
||||
$incomingToken = function_exists('fcm_v1_device_token_from_request')
|
||||
? fcm_v1_device_token_from_request($dec_data)
|
||||
: (isset($dec_data->token) ? trim((string) $dec_data->token) : '');
|
||||
if ($incomingToken === '') {
|
||||
$emailForToken = isset($dec_data->email) ? strtolower(trim((string) $dec_data->email)) : '';
|
||||
if ($emailForToken !== '') {
|
||||
@@ -1007,6 +1085,7 @@ class Pelanggan extends REST_Controller
|
||||
|
||||
function request_transaksi_post()
|
||||
{
|
||||
$endpoint = 'request_transaksi_post';
|
||||
if (!isset($_SERVER['PHP_AUTH_USER'])) {
|
||||
header("WWW-Authenticate: Basic realm=\"Private Area\"");
|
||||
header("HTTP/1.0 401 Unauthorized");
|
||||
@@ -1014,18 +1093,19 @@ 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'
|
||||
);
|
||||
log_message('debug', '[ORDER_API][' . $endpoint . '] banned user ' . $_SERVER['PHP_AUTH_USER']);
|
||||
$this->log_order_api_response($endpoint, $message);
|
||||
$this->response($message, 200);
|
||||
}
|
||||
}
|
||||
|
||||
$data = file_get_contents("php://input");
|
||||
$dec_data = json_decode($data);
|
||||
log_message('debug', 'request_transaksi_post: payload=' . $data);
|
||||
$this->log_order_api_request($endpoint, $data);
|
||||
|
||||
$data_req = array(
|
||||
'id_pelanggan' => $dec_data->id_pelanggan,
|
||||
@@ -1046,9 +1126,23 @@ class Pelanggan extends REST_Controller
|
||||
);
|
||||
|
||||
$request = $this->Pelanggan_model->insert_transaksi($data_req);
|
||||
$idTransaksiNum = 0;
|
||||
if ($request['status'] && !empty($request['data'])) {
|
||||
foreach ($request['data'] as $row) {
|
||||
if (is_object($row) && isset($row->id)) {
|
||||
$idTransaksiNum = (int) $row->id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
$idTransaksi = $idTransaksiNum > 0 ? $idTransaksiNum : 'unknown';
|
||||
$driverTargets = $idTransaksiNum > 0
|
||||
? $this->Pelanggan_model->get_data_driver_histroy($idTransaksiNum)->result()
|
||||
: array();
|
||||
$this->log_order_driver_targets($endpoint, $idTransaksi, $driverTargets);
|
||||
if ($idTransaksiNum > 0) {
|
||||
log_message('debug', 'request_transaksi_post: success id_transaksi=' . $idTransaksiNum . ' 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']));
|
||||
}
|
||||
@@ -1056,6 +1150,8 @@ class Pelanggan extends REST_Controller
|
||||
'message' => 'success',
|
||||
'data' => $request['data']
|
||||
);
|
||||
$this->log_order_api_response($endpoint, $message);
|
||||
$this->save_order_creation_logs($idTransaksiNum, $data, $message, $driverTargets);
|
||||
$this->response($message, 200);
|
||||
} else {
|
||||
log_message('error', 'request_transaksi_post: insert_transaksi fail data=' . json_encode($request['data']));
|
||||
@@ -1063,12 +1159,14 @@ class Pelanggan extends REST_Controller
|
||||
'message' => 'fail',
|
||||
'data' => $request['data']
|
||||
);
|
||||
$this->log_order_api_response($endpoint, $message);
|
||||
$this->response($message, 200);
|
||||
}
|
||||
}
|
||||
|
||||
function check_status_transaksi_post()
|
||||
{
|
||||
$endpoint = 'check_status_transaksi_post';
|
||||
if (!isset($_SERVER['PHP_AUTH_USER'])) {
|
||||
header("WWW-Authenticate: Basic realm=\"Private Area\"");
|
||||
header("HTTP/1.0 401 Unauthorized");
|
||||
@@ -1077,14 +1175,19 @@ 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);
|
||||
$this->log_order_api_request($endpoint, $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->log_order_driver_targets(
|
||||
$endpoint,
|
||||
isset($dec_data->id_transaksi) ? $dec_data->id_transaksi : 'unknown',
|
||||
isset($getStatus['list_driver']) ? $getStatus['list_driver'] : array()
|
||||
);
|
||||
$this->log_order_api_response($endpoint, $getStatus);
|
||||
$this->response($getStatus, 200);
|
||||
}
|
||||
|
||||
@@ -1321,6 +1424,7 @@ class Pelanggan extends REST_Controller
|
||||
|
||||
function request_transaksi_send_post()
|
||||
{
|
||||
$endpoint = 'request_transaksi_send_post';
|
||||
if (!isset($_SERVER['PHP_AUTH_USER'])) {
|
||||
header("WWW-Authenticate: Basic realm=\"Private Area\"");
|
||||
header("HTTP/1.0 401 Unauthorized");
|
||||
@@ -1332,12 +1436,15 @@ class Pelanggan extends REST_Controller
|
||||
'message' => 'fail',
|
||||
'data' => 'Status User Banned'
|
||||
);
|
||||
log_message('debug', '[ORDER_API][' . $endpoint . '] banned user ' . $_SERVER['PHP_AUTH_USER']);
|
||||
$this->log_order_api_response($endpoint, $message);
|
||||
$this->response($message, 200);
|
||||
}
|
||||
}
|
||||
|
||||
$data = file_get_contents("php://input");
|
||||
$dec_data = json_decode($data);
|
||||
$this->log_order_api_request($endpoint, $data);
|
||||
|
||||
$data_req = array(
|
||||
'id_pelanggan' => $dec_data->id_pelanggan,
|
||||
@@ -1368,16 +1475,29 @@ class Pelanggan extends REST_Controller
|
||||
|
||||
$request = $this->Pelanggan_model->insert_transaksi_send($data_req, $dataDetail);
|
||||
if ($request['status']) {
|
||||
$resultRows = $request['data']->result();
|
||||
$message = array(
|
||||
'message' => 'success',
|
||||
'data' => $request['data']->result()
|
||||
'data' => $resultRows
|
||||
);
|
||||
$idTransaksiNum = 0;
|
||||
if (!empty($resultRows[0]) && is_object($resultRows[0]) && isset($resultRows[0]->id)) {
|
||||
$idTransaksiNum = (int) $resultRows[0]->id;
|
||||
}
|
||||
$idTransaksi = $idTransaksiNum > 0 ? $idTransaksiNum : 'unknown';
|
||||
$driverTargets = $idTransaksiNum > 0
|
||||
? $this->Pelanggan_model->get_data_driver_histroy($idTransaksiNum)->result()
|
||||
: array();
|
||||
$this->log_order_driver_targets($endpoint, $idTransaksi, $driverTargets);
|
||||
$this->log_order_api_response($endpoint, $message);
|
||||
$this->save_order_creation_logs($idTransaksiNum, $data, $message, $driverTargets);
|
||||
$this->response($message, 200);
|
||||
} else {
|
||||
$message = array(
|
||||
'message' => 'fail',
|
||||
'data' => []
|
||||
);
|
||||
$this->log_order_api_response($endpoint, $message);
|
||||
$this->response($message, 200);
|
||||
}
|
||||
}
|
||||
@@ -1457,6 +1577,7 @@ class Pelanggan extends REST_Controller
|
||||
|
||||
function inserttransaksimerchant_post()
|
||||
{
|
||||
$endpoint = 'inserttransaksimerchant_post';
|
||||
if (!isset($_SERVER['PHP_AUTH_USER'])) {
|
||||
header("WWW-Authenticate: Basic realm=\"Private Area\"");
|
||||
header("HTTP/1.0 401 Unauthorized");
|
||||
@@ -1468,12 +1589,15 @@ class Pelanggan extends REST_Controller
|
||||
'message' => 'fail',
|
||||
'data' => 'Status User Banned'
|
||||
);
|
||||
log_message('debug', '[ORDER_API][' . $endpoint . '] banned user ' . $_SERVER['PHP_AUTH_USER']);
|
||||
$this->log_order_api_response($endpoint, $message);
|
||||
$this->response($message, 200);
|
||||
}
|
||||
}
|
||||
|
||||
$data = file_get_contents("php://input");
|
||||
$dec_data = json_decode($data);
|
||||
$this->log_order_api_request($endpoint, $data);
|
||||
|
||||
$data_transaksi = array(
|
||||
'id_pelanggan' => $dec_data->id_pelanggan,
|
||||
@@ -1531,9 +1655,14 @@ class Pelanggan extends REST_Controller
|
||||
$message = array(
|
||||
'message' => 'success',
|
||||
'data' => $result['data'],
|
||||
|
||||
|
||||
);
|
||||
$tid = isset($result['id_transaksi']) ? (int) $result['id_transaksi'] : 0;
|
||||
$driverTargets = $tid > 0
|
||||
? $this->Pelanggan_model->get_data_driver_histroy($tid)->result()
|
||||
: array();
|
||||
$this->log_order_driver_targets($endpoint, $tid ?: 'unknown', $driverTargets);
|
||||
$this->log_order_api_response($endpoint, $message);
|
||||
$this->save_order_creation_logs($tid, $data, $message, $driverTargets);
|
||||
$this->response($message, 200);
|
||||
} else {
|
||||
$message = array(
|
||||
@@ -1541,6 +1670,7 @@ class Pelanggan extends REST_Controller
|
||||
'data' => []
|
||||
|
||||
);
|
||||
$this->log_order_api_response($endpoint, $message);
|
||||
$this->response($message, 200);
|
||||
}
|
||||
} else {
|
||||
@@ -1549,6 +1679,7 @@ class Pelanggan extends REST_Controller
|
||||
'data' => []
|
||||
|
||||
);
|
||||
$this->log_order_api_response($endpoint, $message);
|
||||
$this->response($message, 200);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,9 @@ defined('BASEPATH') or exit('No direct script access allowed');
|
||||
|
||||
/**
|
||||
* FCM HTTP v1 API helper (Firebase Cloud Messaging).
|
||||
* Uses OAuth2 access token from service account credentials (env: FCM_CREDENTIALS_PATH or FCM_CREDENTIALS_JSON).
|
||||
* Requires FCM_PROJECT_ID. Optional: FCM_LIMIT_PER_HOUR, FCM_LIMIT_PER_DAY for quota (used by callers).
|
||||
* OAuth2 access token from service account: FCM_CREDENTIALS_PATH or FCM_CREDENTIALS_JSON
|
||||
* and FCM_PROJECT_ID (set in application/config/config.php).
|
||||
* Optional: FCM_LIMIT_PER_HOUR, FCM_LIMIT_PER_DAY for quota (used by callers).
|
||||
*/
|
||||
|
||||
if (!function_exists('fcm_v1_get_credentials')) {
|
||||
@@ -264,3 +265,80 @@ if (!function_exists('fcm_v1_send')) {
|
||||
return $resp;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('fcm_v1_device_token_from_request')) {
|
||||
/**
|
||||
* FCM device registration token from API JSON body (mobile APK).
|
||||
* First non-empty among: firebase_token, fcm_token, reg_id, token.
|
||||
*
|
||||
* @param object|null $decoded_data json_decode() result
|
||||
* @return string Trimmed token or empty string
|
||||
*/
|
||||
function fcm_v1_device_token_from_request($decoded_data)
|
||||
{
|
||||
if (!$decoded_data || !is_object($decoded_data)) {
|
||||
return '';
|
||||
}
|
||||
foreach (array('firebase_token', 'fcm_token', 'reg_id', 'token') as $key) {
|
||||
if (!isset($decoded_data->$key)) {
|
||||
continue;
|
||||
}
|
||||
$v = trim((string) $decoded_data->$key);
|
||||
if ($v !== '') {
|
||||
return $v;
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('fcm_v1_login_allow_missing_device_token')) {
|
||||
/**
|
||||
* When true, Pelanggan/Merchant/Driver login skips FCM token presence validation (e.g. Postman / legacy).
|
||||
* Controlled by FCM_LOGIN_ALLOW_NO_DEVICE_TOKEN in application/config/config.php.
|
||||
*/
|
||||
function fcm_v1_login_allow_missing_device_token()
|
||||
{
|
||||
if (defined('FCM_LOGIN_ALLOW_NO_DEVICE_TOKEN')) {
|
||||
return (bool) FCM_LOGIN_ALLOW_NO_DEVICE_TOKEN;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('fcm_v1_validate_login_device_token_from_app')) {
|
||||
/**
|
||||
* Enforces that the APK sent a Firebase-generated device token on login.
|
||||
* Token is produced only on-device (FirebaseMessaging.getToken); backend never mints it.
|
||||
*
|
||||
* @param object|null $decoded_data json_decode body
|
||||
* @return array|null Null if OK or enforcement disabled; else array with keys code, message for API response
|
||||
*/
|
||||
function fcm_v1_validate_login_device_token_from_app($decoded_data)
|
||||
{
|
||||
if (fcm_v1_login_allow_missing_device_token()) {
|
||||
return null;
|
||||
}
|
||||
if (!function_exists('fcm_v1_device_token_from_request')) {
|
||||
return null;
|
||||
}
|
||||
$raw = fcm_v1_device_token_from_request($decoded_data);
|
||||
if ($raw === '') {
|
||||
return array(
|
||||
'code' => '400',
|
||||
'message' =>
|
||||
'Wajib kirim token FCM dari aplikasi (firebase_token, fcm_token, token, atau reg_id). '
|
||||
. 'Token dibuat oleh Firebase di perangkat setelah Firebase.initializeApp dan izin notifikasi.',
|
||||
);
|
||||
}
|
||||
if (!function_exists('fcm_v1_is_valid_device_token') || !fcm_v1_is_valid_device_token($raw)) {
|
||||
return array(
|
||||
'code' => '400',
|
||||
'message' =>
|
||||
'Token FCM tidak valid. Pastikan aplikasi berhasil memanggil Firebase Messaging getToken() '
|
||||
. 'di perangkat (bukan string buatan server).',
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ defined('BASEPATH') or exit('No direct script access allowed');
|
||||
* UNIQUE KEY uk_key_period (key_name, period_type, period_value)
|
||||
* );
|
||||
*
|
||||
* Config via env: FCM_LIMIT_PER_HOUR, FCM_LIMIT_PER_DAY, MAPS_LIMIT_PER_DAY, etc.
|
||||
* Callers pass limits; backend defaults often use FCM_LIMIT_PER_HOUR / FCM_LIMIT_PER_DAY from config.php.
|
||||
*/
|
||||
|
||||
if (!function_exists('quota_limiter_allow')) {
|
||||
|
||||
@@ -15,6 +15,16 @@ class Merchantapi_model extends CI_model
|
||||
}
|
||||
}
|
||||
|
||||
public function check_banned_by_email($email)
|
||||
{
|
||||
$stat = $this->db->query("SELECT id_mitra FROM mitra WHERE status_mitra='3' AND email_mitra='$email'");
|
||||
if ($stat->num_rows() == 1) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function check_exist($email, $phone)
|
||||
{
|
||||
$cek = $this->db->query("SELECT id_mitra FROM mitra where email_mitra = '$email' AND telepon_mitra='$phone'");
|
||||
|
||||
@@ -64,11 +64,7 @@ class notification_model extends CI_model
|
||||
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');
|
||||
log_message('debug', 'send_notif: skip, empty target');
|
||||
return true;
|
||||
}
|
||||
if (!function_exists('fcm_v1_validate_token')) {
|
||||
@@ -87,7 +83,11 @@ class notification_model extends CI_model
|
||||
'title' => $title,
|
||||
'body' => $message,
|
||||
);
|
||||
return $this->send_generic_to_token($target, $data, $options);
|
||||
if ($this->is_valid_fcm_token($target)) {
|
||||
return $this->send_generic_to_token($target, $data, $options);
|
||||
}
|
||||
// Values like pelanggan, driver, mitra, ouride are FCM topic names (broadcast).
|
||||
return $this->send_generic_to_topic(trim((string) $target), $data, $options);
|
||||
}
|
||||
|
||||
public function send_notif_topup($title, $id, $message, $method, $token)
|
||||
|
||||
@@ -309,7 +309,7 @@ class Pelanggan_model extends CI_model
|
||||
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 ld.status IN ('1','4')
|
||||
AND dj.id = d.job
|
||||
AND d.job = f.driver_job
|
||||
AND d.status = '1'
|
||||
@@ -334,9 +334,9 @@ class Pelanggan_model extends CI_model
|
||||
*/
|
||||
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();
|
||||
$r_online = $this->db->query("SELECT COUNT(*) as c FROM config_driver WHERE status IN ('1','4')")->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();
|
||||
$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 IN ('1','4') 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;
|
||||
@@ -381,7 +381,7 @@ class Pelanggan_model extends CI_model
|
||||
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 ld.status IN ('1','4')
|
||||
AND dj.id = d.job
|
||||
AND d.job = f.driver_job
|
||||
AND d.status = '1'
|
||||
@@ -1849,5 +1849,80 @@ class Pelanggan_model extends CI_model
|
||||
$this->db->update('history_transaksi', $data);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Customers for admin FCM screen: label with fullnama / phone / email plus id.
|
||||
*/
|
||||
public function get_all_for_notification_picker()
|
||||
{
|
||||
$this->db->select('id, fullnama, email, no_telepon, token');
|
||||
$this->db->from('pelanggan');
|
||||
$this->db->order_by('fullnama', 'ASC');
|
||||
$this->db->order_by('id', 'ASC');
|
||||
return $this->db->get()->result();
|
||||
}
|
||||
|
||||
/**
|
||||
* One row for sending push: registration token and display name.
|
||||
*/
|
||||
public function get_notification_row_by_id($id)
|
||||
{
|
||||
$this->db->select('id, fullnama, token');
|
||||
$this->db->from('pelanggan');
|
||||
$this->db->where('id', (int) $id);
|
||||
return $this->db->get()->row();
|
||||
}
|
||||
|
||||
/**
|
||||
* Truncate for MEDIUMTEXT logging (safety cap).
|
||||
*/
|
||||
private function truncate_api_log_value($value, $max_bytes = 1048576)
|
||||
{
|
||||
$s = is_string($value) ? $value : (string) $value;
|
||||
if (strlen($s) > $max_bytes) {
|
||||
return substr($s, 0, $max_bytes) . "\n...[truncated]";
|
||||
}
|
||||
return $s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Persist raw pelanggan order API + backend snapshot for driver candidates (admin detail).
|
||||
*/
|
||||
public function save_transaksi_api_log($id_transaksi, $raw_request, $response_json, $backend_to_driver_json)
|
||||
{
|
||||
$id_transaksi = (int) $id_transaksi;
|
||||
if ($id_transaksi <= 0) {
|
||||
return;
|
||||
}
|
||||
$this->db->where('id', $id_transaksi);
|
||||
$this->db->update('transaksi', array(
|
||||
'api_log_pelanggan_request' => $this->truncate_api_log_value($raw_request),
|
||||
'api_log_pelanggan_response' => $this->truncate_api_log_value($response_json),
|
||||
'api_log_backend_to_driver' => $this->truncate_api_log_value($backend_to_driver_json),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Append driver → backend raw body (e.g. accept_post JSON) for this transaction.
|
||||
*/
|
||||
public function append_transaksi_driver_request_log($id_transaksi, $raw_inbound)
|
||||
{
|
||||
$id_transaksi = (int) $id_transaksi;
|
||||
if ($id_transaksi <= 0) {
|
||||
return;
|
||||
}
|
||||
$raw_inbound = $this->truncate_api_log_value($raw_inbound, 262144);
|
||||
$this->db->select('api_log_driver_request');
|
||||
$this->db->where('id', $id_transaksi);
|
||||
$row = $this->db->get('transaksi')->row();
|
||||
$prev = ($row && isset($row->api_log_driver_request) && $row->api_log_driver_request !== null)
|
||||
? (string) $row->api_log_driver_request : '';
|
||||
$stamp = date('c');
|
||||
$line = '[' . $stamp . "] accept/driver inbound:\n" . $raw_inbound;
|
||||
$merged = $prev === '' ? $line : $prev . "\n\n" . $line;
|
||||
$merged = $this->truncate_api_log_value($merged, 1048576);
|
||||
$this->db->where('id', $id_transaksi);
|
||||
$this->db->update('transaksi', array('api_log_driver_request' => $merged));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,14 +17,55 @@
|
||||
<?php endif; ?>
|
||||
<?= form_open_multipart('appnotification/send'); ?>
|
||||
<div class="form-group">
|
||||
<label for="newscategory">Kirim Ke</label>
|
||||
<select class="js-example-basic-single" style="width:100%" name='topic'>
|
||||
<label>Tipe kirim</label>
|
||||
<div class="d-flex flex-wrap align-items-center" style="gap:1rem;">
|
||||
<label class="mb-0 font-weight-normal">
|
||||
<input type="radio" name="send_target" value="topic" checked onchange="toggleAppnotifTarget()"> Topik (broadcast)
|
||||
</label>
|
||||
<label class="mb-0 font-weight-normal">
|
||||
<input type="radio" name="send_target" value="users" onchange="toggleAppnotifTarget()"> Pengguna terpilih (by ID)
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="wrap-topic">
|
||||
<label for="topic">Kirim ke topik</label>
|
||||
<select id="topic" class="js-example-basic-single" style="width:100%" name="topic">
|
||||
<option value="pelanggan">User</option>
|
||||
<option value="driver">Driver</option>
|
||||
<option value="mitra">Merchant Partner</option>
|
||||
<option value="ouride">Semua</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group" id="wrap-users" style="display:none;">
|
||||
<label for="user_ids">Pilih pengguna <span class="text-muted">(nama dan ID)</span></label>
|
||||
<select id="user_ids" class="js-example-basic-multiple" name="user_ids[]" multiple="multiple" style="width:100%" data-placeholder="Cari nama atau ID…">
|
||||
<?php if (!empty($pelanggan_list)) : ?>
|
||||
<?php foreach ($pelanggan_list as $u) : ?>
|
||||
<?php
|
||||
$label = $u->fullnama;
|
||||
if ($label === null || trim((string) $label) === '') {
|
||||
$label = $u->no_telepon ?: $u->email ?: ('User #' . (int) $u->id);
|
||||
}
|
||||
$option_text = $label . ' (ID: ' . (int) $u->id . ')';
|
||||
?>
|
||||
<option value="<?= (int) $u->id ?>"><?= htmlspecialchars($option_text, ENT_QUOTES, 'UTF-8') ?></option>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</select>
|
||||
<small class="form-text text-muted">Hanya pengguna yang pernah login dari aplikasi dengan token FCM valid yang menerima push.</small>
|
||||
</div>
|
||||
<script>
|
||||
function toggleAppnotifTarget() {
|
||||
var r = document.querySelector('input[name="send_target"]:checked');
|
||||
var topic = document.getElementById('wrap-topic');
|
||||
var users = document.getElementById('wrap-users');
|
||||
if (!r || !topic || !users) return;
|
||||
var isTopic = r.value === 'topic';
|
||||
topic.style.display = isTopic ? 'block' : 'none';
|
||||
users.style.display = isTopic ? 'none' : 'block';
|
||||
}
|
||||
document.addEventListener('DOMContentLoaded', toggleAppnotifTarget);
|
||||
</script>
|
||||
<div class="form-group">
|
||||
<label for="title">Judul</label>
|
||||
<input type="text" class="form-control" placeholder="notification" name="title" required>
|
||||
|
||||
@@ -233,6 +233,36 @@
|
||||
<?= $transaksi['catatan'] ?></p>
|
||||
<hr>
|
||||
|
||||
<?php
|
||||
$log_pel_req = isset($transaksi['api_log_pelanggan_request']) ? $transaksi['api_log_pelanggan_request'] : '';
|
||||
$log_pel_res = isset($transaksi['api_log_pelanggan_response']) ? $transaksi['api_log_pelanggan_response'] : '';
|
||||
$log_bk_drv = isset($transaksi['api_log_backend_to_driver']) ? $transaksi['api_log_backend_to_driver'] : '';
|
||||
$log_drv = isset($transaksi['api_log_driver_request']) ? $transaksi['api_log_driver_request'] : '';
|
||||
$has_api_log = (trim((string) $log_pel_req) !== '' || trim((string) $log_pel_res) !== '' || trim((string) $log_bk_drv) !== '' || trim((string) $log_drv) !== '');
|
||||
?>
|
||||
<?php if ($has_api_log) { ?>
|
||||
<div class="text-left mt-4 mb-4">
|
||||
<h5 class="mb-3">Log API pesanan</h5>
|
||||
<?php if (trim((string) $log_pel_req) !== '') { ?>
|
||||
<h6 class="text-muted small text-uppercase">Pelanggan → backend (raw request)</h6>
|
||||
<pre class="p-3 bg-light border rounded small" style="max-height:240px;overflow:auto;"><?= htmlspecialchars($log_pel_req, ENT_QUOTES, 'UTF-8') ?></pre>
|
||||
<?php } ?>
|
||||
<?php if (trim((string) $log_pel_res) !== '') { ?>
|
||||
<h6 class="text-muted small text-uppercase mt-3">Backend → pelanggan (raw response)</h6>
|
||||
<pre class="p-3 bg-light border rounded small" style="max-height:240px;overflow:auto;"><?= htmlspecialchars($log_pel_res, ENT_QUOTES, 'UTF-8') ?></pre>
|
||||
<?php } ?>
|
||||
<?php if (trim((string) $log_bk_drv) !== '') { ?>
|
||||
<h6 class="text-muted small text-uppercase mt-3">Backend → driver (snapshot / kandidat)</h6>
|
||||
<pre class="p-3 bg-light border rounded small" style="max-height:240px;overflow:auto;"><?= htmlspecialchars($log_bk_drv, ENT_QUOTES, 'UTF-8') ?></pre>
|
||||
<?php } ?>
|
||||
<?php if (trim((string) $log_drv) !== '') { ?>
|
||||
<h6 class="text-muted small text-uppercase mt-3">Driver ↔ backend (accept: raw + response JSON)</h6>
|
||||
<pre class="p-3 bg-light border rounded small" style="max-height:280px;overflow:auto;"><?= htmlspecialchars($log_drv, ENT_QUOTES, 'UTF-8') ?></pre>
|
||||
<?php } ?>
|
||||
</div>
|
||||
<hr>
|
||||
<?php } ?>
|
||||
|
||||
<?php if ($transaksi['home'] == 4) { ?>
|
||||
<div class="container-fluid mt-5 d-flex justify-content-center w-100">
|
||||
<div class="table-responsive w-100">
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
-- Run once on the application database so order detail can show API traces.
|
||||
-- MySQL / MariaDB
|
||||
|
||||
ALTER TABLE `transaksi`
|
||||
ADD COLUMN `api_log_pelanggan_request` MEDIUMTEXT NULL COMMENT 'Raw pelanggan app JSON body on order create',
|
||||
ADD COLUMN `api_log_pelanggan_response` MEDIUMTEXT NULL COMMENT 'JSON response body returned to pelanggan',
|
||||
ADD COLUMN `api_log_backend_to_driver` MEDIUMTEXT NULL COMMENT 'Backend snapshot: candidate drivers JSON',
|
||||
ADD COLUMN `api_log_driver_request` MEDIUMTEXT NULL COMMENT 'Driver accept: raw request + backend response JSON lines';
|
||||
Reference in New Issue
Block a user