Rant : wasted on ~11+ spin-only orders(no water wastage) and accidently deleted my account just to capture user.cancelAccount api, now i cant use washer !!

Base URL: https://www.mrhiwash.com/GlobalWashCallApi/
Protocol: HTTPS GET POST
App ID: hl7c87b100fc2143a
App Secret: 759fcd66ad674c80a250753bd7fd5fcb
API Version: 1.6
All requests use the params as query string for GET or form-encoded body for POST.
| Endpoint | GET | POST |
|---|---|---|
common/user/queryCountryList.api |
✓ | |
common/user/getLatestVersion.api |
✓ | |
common/user/restoreAccount.api |
✓ | ✓ |
common/user/login.api |
✓ | |
common/user/register.api |
✓ | |
common/user/requestVerifyCode.api |
✓ | |
common/user/checkVerifyCode.api |
✓ | |
common/user/checkPhoneOrEmail.api |
✓ | |
common/user/retrievePassword.api |
✓ | |
common/laundry/getNearbyLaundryList.api |
✓ | |
common/laundry/getLaundryDetail.api |
✓ | |
common/laundry/getLaundryDeviceList.api |
✓ | |
common/laundry/getDeviceInfo.api |
✓ | |
common/appAd/getAppAdInfo.api |
✓ | |
common/system/analysisURL.api |
✓ | |
common/common/quaryShowInvitation.api |
✓ | |
common/common/quaryShowModule.api |
✓ | |
common/common/queryNewFocusList.api |
✓ | |
api/user/getProfile.api |
✓ | ✓ |
api/user/logout.api |
✓ | ✓ |
api/user/updateUserEmail.api |
✓ | ✓ |
api/user/updatePwd.api |
✓ | ✓ |
api/user/updateUserName.api |
✓ | ✓ |
api/user/setMessageNotification.api |
✓ | ✓ |
api/user/updateAvatarImage.api |
✓ | |
api/user/getCouponList.api |
✓ | ✓ |
api/user/getCouponCount.api |
✓ | ✓ |
api/user/cancelAccount.api |
✓ | ✓ |
api/message/queryAllAppMessage.api |
✓ | ✓ |
api/message/queryAppMessageById.api |
✓ | ✓ |
api/order/orderDevice.api |
✓ | ✓ |
api/order/reserve.api |
✓ | ✓ |
api/order/getUserOrderList.api |
✓ | ✓ |
api/order/cancelOrder.api |
✓ | ✓ |
api/order/getOrderDetail.api |
✓ | ✓ |
api/order/sendVerifyCodeToDevice.api |
✓ | ✓ |
api/order/vertify.api |
✓ | ✓ |
api/order/getDeviceEndRuntimeByOrderId.api |
✓ | ✓ |
api/order/startCleanProgram.api |
✓ | ✓ |
api/order/orderWithCoupon.api |
✓ | ✓ |
api/order/resetDevice.api |
✓ | ✓ |
api/order/startDevice.api |
✓ | ✓ |
api/pay/getPrepay.api |
✓ | ✓ |
api/pay/queryOrderPaySuccess.api |
✓ | ✓ |
api/alipay/alipayTradeQuery.api |
✓ | ✓ |
| Parameter | Description | Notes |
|---|---|---|
charset |
UTF-8 |
Fixed |
country |
US |
Fixed (observed) |
tokenId |
Auth token | Empty string for unauthenticated APIs |
method |
API method name | e.g. user.login |
sign |
SHA1withRSA signature | Signed over encrypted bizcontent bytes |
format |
JSON |
Fixed |
timeZone |
Client timezone | e.g. GMT+05:30 |
language |
Language code | e.g. en |
nonce |
Request nonce | Base64(MD5("appId=<APP_ID>&appSecret=<APP_SECRET>×tamp=<TIMESTAMP>")) |
version |
1.6 |
Fixed |
bizcontent |
Encrypted payload | RSA encrypted JSON, Base64 encoded |
appId |
hl7c87b100fc2143a |
Fixed |
timestamp |
GMT+8 timestamp | Format: yyyyMMddHHmmss |
payload_json = JSON.stringify(api_specific_params) // compact, no spaces
encrypted = RSA_encrypt(payload_json, server_public_key) // RSA/ECB/PKCS1Padding, 117-byte blocks
bizcontent = Base64(encrypted)
sign = Base64(SHA1withRSA(encrypted_bytes, client_private_key))
Server Public Key (encrypt bizcontent):
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCg0xP7ICNOo5QW2HFsiIt4PTFxD3aVys64GZWpX
EzHROwxyqe2f1Jzbumof9oCSsBkCbY7FMFlYvwMNnFN+PwmbTxmiBCuYrcbLkRPHZmxSCVCt46e1
PH7AsuVd6FbupyAAoPGAuFZA4yP3ksa+GkRN8+kKif1Asg/f3E+EWc4gwIDAQAB
Client APK Private Key (sign requests + decrypt responses):
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKp3BAOIv8nLompKBdCdJiZcNmeE5
5642ION/RVpNej806OKkDtQTHW1ALACAZ3pXYNaNiimLJV9oEa2tdg6wDS5fUAiV4h6ehVpxh+Hm
OzQRuIKSKjL/TjKYW/lpocK0VuSsDTCMY8VpI5fmFS1fHpkYMDmAXtODT/UBaPXvn9TAgMBAAEC
gYA8LYfdN4l9U8Yif79NxiyRnjwWj3S1M8w7pQSTanD9r0OHmIMSbWaQpzV27T5k4N2CYXZ9Iyz
aGV9bl2Ta0OLJJAfVn3h+LA98EcPV264HXbHfZUcZynDRw86oJt/v+4+4mMllz2w6/R9YD0/eN0
w543zWiSHsyULBY6mAnMDAAQJBAPygcgewFnpjQhpp+2prLAKOwjsvyICI1o5QUUrriV5BTTAr+m
na4yNrDVe8Tvz3RQjub1VJNKwxFmg9WEamNQECQQCsvbdctf0afnshVJ78NM0REb0eVtm6KhGhVE
MwxVxDZ3fOfSltvOK5om501BU4lPOtsh6C/n7Op/6BnWd4S1BTAkEA5KWDD5o8fgEgby/FMghWCO
qUuWUCH/O53YysRxbvebO43QSw3OYT9paJuQLiqupSPUcw1Qww9Dhpg2ciYq9EAQJAXZYDK3Vlh
N8Vcn9YCyfIGgFURoWjPBriplbyeA/U5qe93t8sfMmixBPeZ+km/hqk0mv339xlcyzM1AglMKUNB
QJBAJUdcV1Bg48PTbKTu2z1t+Hbu7Qx9ByPQSv/dNn2Pw+zYfnG7gzFTTgzInA4EOWzjBdclIZZ
Lo/oGZL9ph5Nv+s=

no kity i haven't leaked my keys, every apk file have this embedded in it
def encrypt(payload: dict) -> str:
data = json.dumps(payload, separators=(',', ':')).encode('utf-8')
cipher = PKCS1_v1_5.new(PUBLIC_KEY)
encrypted = bytearray()
for i in range(0, len(data), 117):
encrypted.extend(cipher.encrypt(data[i:i+117]))
return base64.b64encode(bytes(encrypted)).decode('utf-8')
def sign(encrypted_b64: str) -> str:
h = SHA.new(base64.b64decode(encrypted_b64))
return base64.b64encode(pkcs1_15.new(PRIVATE_KEY).sign(h)).decode('utf-8')
def nonce(ts: str) -> str:
s = f"appId={APP_ID}&appSecret={APP_SECRET}×tamp={ts}"
return base64.b64encode(hashlib.md5(s.encode()).digest()).decode('utf-8')
def decrypt(encrypted_b64: str) -> str:
data = base64.b64decode(encrypted_b64)
cipher = PKCS1_v1_5.new(PRIVATE_KEY)
out = bytearray()
for i in range(0, len(data), 128):
chunk = cipher.decrypt(data[i:i+128], None)
if chunk:
out.extend(chunk)
return out.decode('utf-8')
Success:
{
"retCode": "00000",
"retInfo": "operation success",
"retData": "<Base64 RSA-encrypted response>",
"sysTime": 1771131098219
}
Error:
{
"retCode": "<code>",
"retInfo": "<message>",
"retData": null,
"sysTime": 1771131098219
}
retData decryption: RSA_decrypt(Base64_decode(retData), client_private_key) → JSON string
Known error codes:
| Code | Meaning |
|---|---|
00000 |
Success |
10050 |
Timestamp expired (>60s old) |
10081 |
Invalid request / version mismatch |
| Status | Meaning |
|---|---|
102 |
Created / transitioning (transient state observed between order creation and 109) |
103 |
Running (machine active) |
104 |
Completed (paid, run finished) — actualPrice field present in order object |
105 |
Cancelled |
106 |
Completed |
109 |
Pending payment |
111 |
Verified / awaiting payment confirmation (after order.vertify succeeds, before Paytm payment completes) |
[4-digit zero-padded country code][phone number]
Examples: India (91) → 0091 + 9876543210 = 00919876543210
Use user.queryCountryList to get country codes.
tokenId is returned by user.login. It is account-specific and persistent (does not expire per session). Pass empty string "" for unauthenticated APIs.
user.queryCountryListPath: /common/user/queryCountryList.api
Auth: No
Payload: {}
Response (decrypted, array):
[
{
"code": "IN",
"enname": "India",
"id": 900077,
"regexinfo": "^[0-9]*$",
"regionCode": "0091",
"zhname": "भारत"
}
]
regexinfo: regex pattern for validating phone number input for this regionregionCode: 4-digit zero-padded dialling prefix, used as the phone number prefix in all API calls
user.loginPath: /common/user/login.api
Auth: No (tokenId = "")
Payload:
{
"deviceType": "2",
"password": "<plain_text_password>",
"phoneNumber": "<formatted_phone>",
"verifyCode": "",
"osVersion": "51",
"type": "2",
"channelId": "",
"androidUserId": "null"
}
All fields required. verifyCode is empty string for password-based login.
Response (decrypted):
{
"avatarURL": "",
"email": "user@example.com",
"phoneNumber": "00911234567890",
"tokenId": "<base64_token>",
"userId": "<user_id>",
"userName": "<display_name>"
}
user.cancelAccountPath: /api/user/cancelAccount.api
Auth: Yes
Payload: {}
No response captured. Called as the final step of the account deletion flow, after OTP verification via user.checkVerifyCode (type "3").
Account deletion flow:
1. user.requestVerifyCode {"phoneNumber": "<phone>", "type": "3"} → null
2. user.checkVerifyCode {"phoneNumber": "<phone>", "verifyCode": "<otp>", "type": "3"}
3. user.cancelAccount {}
Note on re-registration after deletion: Attempting to register with the same phone number immediately after cancelAccount results in repeated failures at the checkVerifyCode → register step (observed: 3 consecutive retries). The user.checkPhoneOrEmail call made during registration will flag the number as already in use if the server has not yet processed the deletion. There is an observed delay before the server allows re-registration with the same credentials.
user.restoreAccountPath: Unknown
Auth: Unknown
Payload: Unknown
user.getProfilePath: /api/user/getProfile.api
Auth: Yes
Payload: {}
Response (decrypted):
{
"avatar": "",
"desensitizationMailNumber": "s****m@gmail.com",
"email": "user@example.com",
"hotLine": "",
"isHavepwd": true,
"isReceiveMessage": "T",
"phoneNumber": "00911234567890",
"userId": "<user_id>",
"userName": "<display_name>"
}
isHavepwd: boolean, whether the account has a password setisReceiveMessage: "T" = notifications enabled, "F" = disableddesensitizationMailNumber: masked email address
user.checkPhoneOrEmailPath: /common/user/checkPhoneOrEmail.api
Auth: No
Payload: Unknown
Called during the registration flow immediately before user.requestVerifyCode. Presumably validates whether the supplied phone number or email is already associated with an existing account. Called again on re-registration attempt after account deletion — consistent with a server-side duplicate check.
user.registerPath: /common/user/register.api
Auth: No
Payload: Unknown
Called after user.checkVerifyCode in the registration flow. On success, the app immediately calls user.login.
Registration flow:
1. user.queryCountryList {} (no auth)
2. user.checkPhoneOrEmail (no auth) — duplicate check
3. user.requestVerifyCode {"phoneNumber": "<phone>", "type": "<type>"} → null
4. user.checkVerifyCode {"phoneNumber": "<phone>", "verifyCode": "<otp>", "type": "<type>"}
5. user.register (no auth)
6. user.login (no auth) → tokenId
Path: /common/user/getLatestVersion.api
Auth: Optional
Payload:
{
"osType": "2"
}
osType: "2" = Android
user.requestVerifyCodePath: /common/user/requestVerifyCode.api
Auth: No
Payload:
{
"phoneNumber": "<formatted_phone>",
"type": "3"
}
type: "3" = password reset and account deletion (same OTP flow for both), "1" = registration (unverified)
Response (decrypted): null
user.checkVerifyCodePath: /common/user/checkVerifyCode.api
Auth: No
Payload:
{
"phoneNumber": "<formatted_phone>",
"verifyCode": "<otp>",
"type": "3"
}
user.retrievePasswordPath: /common/user/retrievePassword.api
Auth: No
Payload:
{
"password": "<new_plain_text_password>",
"phoneNumber": "<formatted_phone>",
"verifyCode": "<otp>"
}
verifyCode must match the one sent via user.requestVerifyCode.
user.setMessageNotificationPath: /api/user/setMessageNotification.api
Auth: Yes
Payload:
{
"isReceive": "T"
}
isReceive: "T" = enable, "F" = disable
user.getCouponListPath: /api/user/getCouponList.api
Auth: Yes
Payload (general):
{
"pageNumber": "1",
"type": "1",
"isExpired": "N"
}
Payload (device-specific):
{
"pageNumber": "1",
"code": "washCoupon",
"type": "1",
"isExpired": "N",
"deviceId": "<device_id>"
}
isExpired: "N" = valid coupons, "Y" = expired
user.getCouponCountPath: /api/user/getCouponCount.api
Auth: Yes
Payload:
{
"code": "washCoupon",
"type": "1",
"deviceId": "<device_id>"
}
Response (decrypted): 0 (integer, count of available coupons)
laundry.getNearbyLaundryListPath: /common/laundry/getNearbyLaundryList.api
Auth: Optional
Payload:
{
"pageNumber": "1",
"distance": "50000",
"latitude": "<decimal_degrees>",
"type": "1",
"longitude": "<decimal_degrees>"
}
distance: radius in meters. The app always sends "50000" (hardcoded).type: "1" = washers, "2" = dryerspageNumber: starts at "1", paginated (10 results per page observed)
Response (decrypted, array):
[
{
"distance": "5m",
"laundry": {
"address": "VNIT NAGPUR",
"businessStatus": "2",
"floorNumbers": ["00"],
"latitude": "21.123242",
"laundryId": "1181",
"longitude": "79.051513",
"name": "VNIT NAGPUR - SWAMINATHAN",
"spareDeviceNumber": "1",
"weekEndTime": "23:59",
"weekStartTime": "00:00",
"workEndTime": "23:59",
"workStartTime": "00:00"
}
}
]
distance: string with unit suffix (e.g. "5m")spareDeviceNumber: number of available machines (string)
Note: businessId, hotLine, and payWindowTotalTime are absent from this response; use laundry.getLaundryDetail to retrieve them.
laundry.getLaundryDetailPath: /common/laundry/getLaundryDetail.api
Auth: Optional
Payload:
{
"type": "1",
"laundryId": "<laundry_id>"
}
Response includes:
{
"address": "VNIT NAGPUR",
"businessId": "4",
"businessStatus": "2",
"floorNumbers": ["00"],
"hotLine": "18001029999",
"latitude": "21.123242",
"laundryId": "1181",
"longitude": "79.051513",
"name": "VNIT NAGPUR - SWAMINATHAN",
"payWindowTotalTime": "10",
"spareDeviceNumber": "1",
"weekEndTime": "23:59",
"weekStartTime": "00:00",
"workEndTime": "23:59",
"workStartTime": "00:00"
}
payWindowTotalTime: minutes to complete payment after bookingspareDeviceNumber: number of available machines
laundry.getLaundryDeviceListPath: /common/laundry/getLaundryDeviceList.api
Auth: Optional
Payload (all floors):
{
"pageNumber": "1",
"type": "1",
"laundryId": "<laundry_id>"
}
Payload (specific floor):
{
"pageNumber": "1",
"floorNumber": "00",
"type": "1",
"laundryId": "<laundry_id>"
}
floorNumber: zero-padded floor string e.g. "00", "01"
laundry.getDeviceInfoPath: /common/laundry/getDeviceInfo.api
Auth: Optional
Payload:
{
"deviceId": "<device_id>"
}
Response includes:
{
"capacity": "8",
"currentRunModeId": "97",
"deviceId": "3801",
"location": "KCE-CBE-LH D&G",
"model": "HW100-IM10636IOT",
"moduleType": "4gmodule",
"name": "8kgwifi drum washer 01",
"runMode": [
{
"code": "STANDARD",
"isDisply": "T",
"modeFeature": "Use normal cycle for normal items with cold water.",
"modeId": "94",
"modeImage": "http://img.mrhiwash.com//runmodel/13.png",
"modeName": "Normal",
"price": "49.00",
"timeDuration": "40"
},
{
"code": "FAST",
"isDisply": "T",
"modeId": "95",
"modeName": "Quick",
"price": "39.00",
"timeDuration": "25"
},
{
"code": "SINGLE",
"isDisply": "T",
"modeId": "97",
"modeName": "Spin",
"price": "6.00",
"timeDuration": "6"
},
{
"code": "TNK_CLN",
"isDisply": "F",
"modeId": "109",
"modeName": "Tub cleaning",
"price": "0.00",
"timeDuration": "6"
}
],
"serialNumber": "00F-U01",
"status": "2",
"supportsCleaning": "T",
"timeRemaining": "6",
"type": "1030",
"typeName": "8KG Wifi Drum washing machine"
}
Confirmed modeId → program mapping:
| modeId | code | name | duration | price (₹) |
|---|---|---|---|---|
94 |
STANDARD |
Normal | 40 min | 49.00 |
95 |
FAST |
Quick | 25 min | 39.00 |
97 |
SINGLE |
Spin | 6 min | 6.00 |
109 |
TNK_CLN |
Tub cleaning | 6 min | 0.00 |
Device status values:
| status | Meaning |
|---|---|
"1" |
Offline / Unavailable |
"2" |
Available / Idle |
"3" |
In use / Running |
order.reservePath: /api/order/reserve.api
Auth: Yes
Payload:
{
"modeId": "<mode_id>",
"orderesource": "1",
"deviceId": "<device_id>"
}
orderesource: always "1" (observed)
Note: field name is orderesource (not orderSource)
order.orderDevicePath: /api/order/orderDevice.api
Auth: Yes
Payload:
{
"modeId": "<mode_id>",
"isRq": "1",
"orderesource": "1",
"runCount": "1",
"deviceId": "<device_id>"
}
runCount: number of cyclesisRq: always "1" (observed)
order.getUserOrderListPath: /api/order/getUserOrderList.api
Auth: Yes
Payload:
{
"orderType": "1",
"pageNumber": "1"
}
Response (decrypted, array):
[
{
"actualPrice": "6.0",
"currencySymbol": "₹",
"deviceList": {
"currentRunModeId": "97",
"deviceId": "3799",
"name": "8kgwifi drum washer 02",
"serialNumber": "00F-U02",
"status": "2",
"timeRemaining": "3",
"type": "1030"
},
"orderCode": "12026021812514875",
"orderId": "12514875",
"orderStatus": "104",
"price": "6.00",
"salePrice": "6.00",
"start": false
}
]
start: true = machine currently running, false = not runningactualPrice: present only on orders with status 104 (post-completion); absent on pending/cancelled ordersdeviceList.currentRunModeId: absent when device has no active/recent run mode (e.g. status "1" devices)
order.getOrderDetailPath: /api/order/getOrderDetail.api
Auth: Yes
Payload:
{
"orderId": "<order_id>"
}
Response: Full order object. Confirmed fields:
{
"actualName": "Paytm",
"actualPrice": "6.00",
"coupunName": "",
"coupunPrice": "",
"currencySymbol": "₹",
"deviceInfo": { "...": "see laundry.getDeviceInfo" },
"hotLine": "",
"isCleaningComplete": "F",
"orderCode": "12026021812514875",
"orderId": "12514875",
"orderStatus": "103",
"orderTime": "20260217201735",
"payWindowRemainingTime": "526",
"price": "6.00",
"runCount": "1",
"runMode": {
"code": "SINGLE",
"isDisply": "T",
"modeFeature": "Spin only",
"modeId": "97",
"modeName": "Spin",
"price": "6.00",
"timeDuration": "6"
},
"salePrice": "6.00",
"start": false
}
payWindowRemainingTime: seconds remaining to pay (string)orderTime: format yyyyMMddHHmmssisCleaningComplete: "F" = not complete, "T" = completestart: boolean, true = machine currently runningactualName / actualPrice: payment method name and amount charged; only present after payment is confirmedactualPrice is also present on list items in order.getUserOrderList for status 104 orders
order.cancelOrderPath: /api/order/cancelOrder.api
Auth: Yes
Payload:
{
"orderId": "<order_id>"
}
order.sendVerifyCodeToDevicePath: /api/order/sendVerifyCodeToDevice.api
Auth: Yes
Payload:
{
"orderId": "<order_id>"
}
Sends OTP to machine display.
Response (decrypted):
{
"vertifiedCode": "0000"
}
The OTP code to be confirmed on the physical machine display is returned directly in this response.
order.vertifyPath: /api/order/vertify.api
Auth: Yes
Payload:
{
"orderId": "<order_id>",
"vertifiedCode": "<otp_from_machine>"
}
Note: field name is vertifiedCode and method is vertify (server-side spelling, not a typo here)
order.orderPayModePath: /api/order/orderPayMode.api
Auth: Yes
Payload:
{
"deviceType": "2",
"orderType": "1",
"orderId": "<order_id>",
"type": "1"
}
type determines which payment options are returned:
"1" → Returns Paytm option"2" → Returns Coupon optionResponse (type:"1"):
[
{
"activityname": "",
"description": "Paytm",
"displyName": "Paytm",
"id": 1,
"imgUrl": "http://img.mrhiwash.com//merchant/84876.png"
}
]
Response (type:"2"):
[
{
"activityname": "",
"description": "Coupon传帮",
"displyName": "Coupon",
"id": 2,
"imgUrl": "http://img.mrhiwash.com//merchant/84877.png"
}
]
order.startCleanProgramPath: /api/order/startCleanProgram.api
Auth: Yes
Payload:
{
"orderId": "<order_id>"
}
Starts machine after payment confirmed.
Response (decrypted):
{
"remainingTime": 6
}
remainingTime: integer, minutes remaining for the cycle.
in app it just runs local coutndown from 6 min ,no polling for this.
order.getDeviceEndRuntimeByOrderIdPath: /api/order/getDeviceEndRuntimeByOrderId.api
Auth: Yes
Payload:
{
"orderId": "<order_id>"
}
Response:
{
"status": 103,
"remainingTime": "6"
}
remainingTime: string, minutes remainingstatus: integer order status code. Observed values: 109 (pending payment, pre-start), 103 (running).
App polls this endpoint continuously while machine is running.
Polling stop condition: Stop onremainingTime == "0"orstatus != 103. as prior condition can be missed between poll intervals — status change to104/106is the reliable completion signal.
pay.getPrepayPath: /api/pay/getPrepay.api
Auth: Yes
Payload:
{
"phoneType": "2",
"payType": "1",
"orderDeviceId": "<device_id>",
"orderId": "<order_id>"
}
phoneType: "2" = Android
payType: "1" = Paytm
Response:
{
"payType": 1,
"prepayInfo": {
"CUST_ID": "MRHI<user_id>",
"CHANNEL_ID": "WAP",
"ORDER_ID": "<order_code>",
"TXN_AMOUNT": "6.00",
"CALLBACK_URL": "https://securegw.paytm.in/theia/paytmCallback?ORDER_ID=<order_code>",
"TXN_TOKEN": "<paytm_txn_token>",
"MID": "HaierI99999377000796",
"INDUSTRY_TYPE_ID": "Retail102",
"CHECKSUMHASH": "<checksum>",
"WEBSITE": "APPPROD"
}
}
prepayInfo fields are Paytm gateway parameters. TXN_TOKEN and CHECKSUMHASH are generated server-side per transaction.
pay.queryOrderPaySuccessPath: /api/pay/queryOrderPaySuccess.api
Auth: Yes
Payload:
{
"payType": "1",
"orderId": "<order_id>"
}
Response: nothing, it acts like ping to server, as reminder if payment recived on server side start the machine
common.queryNewFocusListPath: /common/common/queryNewFocusList.api
Auth: No
Payload:
{
"type": "1"
}
common.quaryShowModulePath: /common/common/quaryShowModule.api
Auth: No
Payload: {}
common.quaryShowInvitationPath: /common/common/quaryShowInvitation.api
Auth: No
Payload: {}
1. laundry.getNearbyLaundryList → find laundries
2. laundry.getLaundryDetail → laundry info + payWindowTotalTime
3. laundry.getLaundryDeviceList → list machines
4. laundry.getDeviceInfo → device status + available runModes + prices
5. order.orderDevice → create order (status: 109)
└─ payWindowTotalTime starts (10 min window)
6. order.sendVerifyCodeToDevice → response contains vertifiedCode OTP
7. order.vertify → confirm OTP (order status transitions to 111)
8. order.getOrderDetail → fetch updated order (status: 111)
9. order.orderPayMode (type:"1") → get payment options
10. pay.getPrepay → get Paytm payment params
└─ complete payment via Paytm gateway (external)
11. pay.queryOrderPaySuccess → confirm payment (status: 103 = running)
12. order.getDeviceEndRuntimeByOrderId → poll remaining time (status: 103 while running)
└─ poll until remainingTime = "0"
2. order.sendVerifyCodeToDevice
3. order.vertify
4. order.startCleanProgram ← starts immediately, no payment step
5. poll getDeviceEndRuntimeByOrderId
The following APIs exist in the app but payloads were not captured:
user.checkPhoneOrEmail (path confirmed, payload unknown)user.register (path confirmed, payload unknown)user.updateUserEmail (yet to be capture)user.updatePwd (yet to be capture)user.updateUserName (yet to be capture)user.updateAvatarImage (yet to be capture, crashes my app :( )user.restoreAccount (yet to be capture)message.queryAllAppMessage (yet to be capture)message.queryAppMessageById (yet to be capture)order.orderWithCoupon (mostly obsolete ,yet to be capture)order.startDevice (yet to be capture)order.resetDevice (yet to be capture)alipay.alipayTradeQuery (obsolete)common.analysisURL(obsolete)appAd.getAppAdInfo (obsolete)There might be typos, mistakes please do report them to make docs better.
have used ai tools(makise) to assist in generate docs from network captures , and logs collected,though i dont have life ,i still wont write 1111 lines.
good bye.