7.0 KiB
7.0 KiB
OnTime Ordering Workflow & Firebase Alignment
Order flow (User → Driver → Tujuan)
- User: Set jemput (pickup) – In RideCarActivity, user sets pickup via map/Places (
pickUpText,pickUpLatLang). - User: Set tujuan (destination) – User sets destination (
destinationText,destinationLatLang). Route and price are calculated. - User: Set payment – Cash or wallet (
checkedpaywallet,cashpayment/walletpayment). - Search driver –
GetNearRideCarRequestJson/GetNearRideCarResponseJsonloads nearby drivers;driverAvailableis used for FCM. - User: Order –
sendRequestTransaksi()calls backend, thenfcmBroadcast()sends FCM to each driver token via backendnotification/send_generic. - Driver: Bid or auto bid – Driver receives FCM in
MessagingService(type=1), opensNewOrderActivity. Manual: tap "order"; Auto:getaccept(true)after 2s if setting is ON. - Driver: Accept –
getaccept()calls backendaccept, then sends FCM to user token (regid) withOrderFCM(response="2", type=1, id_driver, id_transaksi). - User: Driver accepted – User app
MessagingServicegets type=1, response="2", postsDriverResponsevia EventBus;RideCarActivity.onMessageEventstartsProgressActivity(response "2"). - Progress (until tujuan) – User stays in
ProgressActivity; driver inOrderFragmentcan tap "finish" (start) then "finish" (arrive). Each action: driver calls backend (startrequest/finishrequest), then FCM to user with response "3" (start) or "4" (finish/tujuan). - User: Start / Finish –
MessagingServiceparses type=1 and response "3"/"4", postsDriverResponse;ProgressActivityreceives via EventBus or broadcast,orderHandler()updates status (e.g. "driver start", "finish/tiba di tujuan").
Test backend API
To test backend, use endpoint: apitest.semestaterpadu.my.id
All apps and the backend panel use the same test API base URL:
| Component | Config location | Base URL | API base |
|---|---|---|---|
| User app | OnTime_User_live → Constants.java |
https://apitest.semestaterpadu.my.id/ |
.../api/ |
| Driver app | OnTime_Driver_live → Constants.java |
https://apitest.semestaterpadu.my.id/ |
.../api/ |
| Backend | backendpanel/application/config/config.php → $config['base_url'] |
https://apitest.semestaterpadu.my.id/ |
same |
Example test endpoints:
- Base:
https://apitest.semestaterpadu.my.id/ - API (login, transaksi, etc.):
https://apitest.semestaterpadu.my.id/api/ - FCM send:
POST https://apitest.semestaterpadu.my.id/api/notification/send_generic
Firebase: same project for User, Backend, Driver
- Backend – Single FCM project: uses
fcm_v1_helper(HTTP v1) with service account (e.g.FCM_CREDENTIALS_PATH/FCM_PROJECT_ID). All sends go through backendapi/notification/send_generic(POST). - User app – Receives FCM via
FirebaseMessagingService; sends by calling same backendConstants.CONNECTION + "notification/send_generic"withtarget= driver token anddata=DriverRequest(order offer). - Driver app – Receives FCM via
FirebaseMessagingService; sends by calling same backendConstants.CONNECTION + "notification/send_generic"withtarget= user token anddata=OrderFCM(accept/start/finish).
Both apps use the same BASE_URL (e.g. https://apitest.semestaterpadu.my.id/) and same endpoint, so they share the same Firebase project and backend.
FCM type and payload alignment
| Type | Meaning | Sender | Receiver | Key payload |
|---|---|---|---|---|
| 1 | Order | User→Driver: DriverRequest (offer); Driver→User: OrderFCM (accept/start/finish/cancel) |
Both | id_transaksi, id_driver, response ("2"/"3"/"4"/"5"), plus offer fields for driver |
| 2 | Chat | User/Driver | User/Driver | chat fields |
| 3 | Other | Backend | User/Driver | title, message |
| 4 | Other2 | Backend | User/Driver | title, message |
Backend send_generic_to_token / send_generic_to_topic flatten data and stringify values so FCM receives a flat string map.
Driver & merchant matching: purely GPS (no region)
- Driver nearby (
list_ride/list_car): Uses only real GPS – driver position fromconfig_driver(updated by driver app’supdate_location) and user/customer position from the request. No region/wilayah is used. Radius isfitur.jarak_minimum(km), with a minimum of 10 km. - Merchant nearby: Uses only real GPS –
merchant.latitude_merchant,merchant.longitude_merchantand user’s lat/long. No region filter. Distance cap isfitur.jarak_minimum.
Driver’s wilayah (partner_region) is only used in the admin panel for display; it is not used when finding nearby drivers or merchants for the user.
"Tidak ada pengemudi di sekitar Anda" – checklist
If the user always sees "Maaf, tidak ada pengemudi di sekitar Anda" even when a driver is close:
- Driver must be "online" – In the driver app the driver must be in "online" / status 1 mode. The backend only returns drivers where
config_driver.status = '1'. - Driver location – The driver app sends location via
driver/update_location. Ensure the driver has opened the app and location permission is granted soconfig_driverhas recent latitude/longitude. - Backend radius – The backend uses
fitur.jarak_minimum(km). A minimum radius of 10 km is now applied so that small values in the admin panel (e.g. 1–2 km) still show drivers within 10 km. Admin can set Services → jarak_minimum to a larger value (e.g. 15 or 20 km) if needed. - User app – If the first fetch was slow or location was not ready, the user can tap Order anyway: the app will refetch nearby drivers once (using pickup or last location) and then either place the order or show the message.
Fixes applied
- Backend: Implemented
send_generic_to_tokenandsend_generic_to_topicinNotification_modelusingfcm_v1_send; controller loadsfcm_v1_helperso generic FCM from both apps works. - User MessagingService: Null-safe handling for
getData()andtype; broadcast bundle now includescode,response,id_transaksi,id_driverso ProgressActivity can update when driver sends start/finish. - ProgressActivity: BroadcastReceiver only applies updates when
id_transaksimatches; updates localresponseand callsorderHandler(code)so status and flow (e.g. sampai tujuan) stay correct. - Driver MessagingService: Null-safe handling for
getData(),type, andhargato avoid NPE/crash on malformed FCM. - "No driver near you": Backend
get_driver_ridenow uses a minimum radius of 10 km (GREATEST(COALESCE(f.jarak_minimum, 10), 10)) so drivers within 10 km are found even if the fitur’sjarak_minimumis set very small. User app: when the user taps Order and the driver list is empty, the app refetches nearby drivers once (using pickup or last location) and then proceeds or shows the message.