[FEAT] 取貨碼/通行碼改走 StarCloudAPI B660/B670(比照員工卡 B680)
舊的 httpAPI(memberVerification / checkAccessCode B024)改為新 StarCloudAPI: - StarCloudAPI 新增 verifyPickupCode(B660,回 code_id+slot_no)、 verifyPassCode(B670,回 code_id),及 PickupVerificationCallback。 - 通行碼 CheckoutAccessCodeDialog:手動+掃碼兩入口改走 verifyPassCode, 成功設 flowType=5、保存 accessCodeId 供 MQTT finalize(payment_type=5)。 - 取貨碼 FontendPickupCodeDialog:兩入口改走 verifyPickupCode,依回傳 slot_no 建立 BuyList、設 flowType=6、保存 accessCodeId(payment_type=6), 進入 BuyPickupCodeDialog 確認 → DispatchDialog;文案修正為「取貨碼」。 finalize 的 code_id 取自 ReportAccessCodeStructure.accessCodeId、payment_type 取自 flowType,App 端 TransactionFinalizeBuilder 既有支援。三 flavor 編譯/打包通過。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
f10f6f5879
commit
1720d2007e
@ -313,15 +313,7 @@ public class FontendPickupCodeDialog extends DialogAbstract {
|
||||
String barCodeString = new String(buffer, 0, size);
|
||||
getHandlerMain().start(getLogs().getClassName(), getCtx().getString(R.string.receive_barcode)+":"+ Tools.randomReplace(barCodeString, 0.3)+","+getCtx().getString(R.string.send_transaction));//收到條碼,送出交易
|
||||
|
||||
try {
|
||||
MyApp.getInstance().getMemberVerificationStructure().setProductId("0");
|
||||
MyApp.getInstance().getMemberVerificationStructure().setProductPrice(0);
|
||||
MyApp.getInstance().getMemberVerificationStructure().setMemberBarCode(barCodeString);
|
||||
MyApp.getInstance().getMemberVerificationStructure().setVerificationType(2);
|
||||
httpAPI.memberVerification(MyApp.getInstance().getMemberVerificationStructure());
|
||||
} catch (LogsParseException | LogsSettingEmptyException e) {
|
||||
getLogs().warning(e);
|
||||
}
|
||||
submitPickupCode(barCodeString.trim());
|
||||
|
||||
openBarcode = false;
|
||||
}
|
||||
@ -357,23 +349,65 @@ public class FontendPickupCodeDialog extends DialogAbstract {
|
||||
}
|
||||
|
||||
public void changeOk() {
|
||||
try {
|
||||
String number = binding.editTextNumber.getText().toString();
|
||||
// 長度檢查
|
||||
if (number.length() < 8) {
|
||||
getHandlerMain().start(getClass().getSimpleName(), "統一編號長度不能少於 8 碼");
|
||||
return;
|
||||
}
|
||||
MyApp.getInstance().getMemberVerificationStructure().setProductId("0");
|
||||
MyApp.getInstance().getMemberVerificationStructure().setProductPrice(0);
|
||||
MyApp.getInstance().getMemberVerificationStructure().setMemberBarCode(number);
|
||||
MyApp.getInstance().getMemberVerificationStructure().setVerificationType(2);
|
||||
httpAPI.memberVerification(MyApp.getInstance().getMemberVerificationStructure());
|
||||
} catch (LogsParseException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (LogsSettingEmptyException e) {
|
||||
throw new RuntimeException(e);
|
||||
String number = binding.editTextNumber.getText().toString().trim();
|
||||
// 長度檢查
|
||||
if (number.isEmpty() || number.length() < 8) {
|
||||
getHandlerMain().start(getClass().getSimpleName(), "取貨碼長度不能少於 8 碼");
|
||||
return;
|
||||
}
|
||||
submitPickupCode(number);
|
||||
}
|
||||
|
||||
/**
|
||||
* 取貨碼驗證改走 StarCloudAPI B660(邏輯比照員工卡 B680)。
|
||||
* 成功回傳 code_id 與要出貨的 slot_no:據此建立 BuyList、保存 code_id 供 MQTT
|
||||
* finalize(payment_type=6 取貨碼),再進入取貨確認 → 出貨。
|
||||
*/
|
||||
private void submitPickupCode(String code) {
|
||||
new com.unibuy.smartdevice.external.StarCloudAPI(getHandlerMain(), getHandlerMain())
|
||||
.verifyPickupCode(code, new com.unibuy.smartdevice.external.StarCloudAPI.PickupVerificationCallback() {
|
||||
@Override
|
||||
public void onSuccess(String codeId, int slotNo) {
|
||||
try {
|
||||
SlotStructure slotProduct = MyApp.getInstance().getSlotData(SlotField.VMC.getField(), slotNo);
|
||||
if (slotProduct == null) {
|
||||
setStatusText(getContext().getString(R.string.product_not_found));
|
||||
openBarcode = true;
|
||||
return;
|
||||
}
|
||||
if (slotProduct.isLock()) {
|
||||
getSrcHandlerMain().start("FontendPickupCodeDialog", "@" + getContext().getString(R.string.product_sales_suspended));
|
||||
dialogCancel();
|
||||
return;
|
||||
}
|
||||
if (slotProduct.getCount() == 0) {
|
||||
getSrcHandlerMain().start("FontendPickupCodeDialog", "@" + getContext().getString(R.string.product_out_of_stock));
|
||||
dialogCancel();
|
||||
return;
|
||||
}
|
||||
MyApp.getInstance().getBuyList().clear();
|
||||
MyApp.getInstance().getBuyList().add(
|
||||
new BuyStructure(slotProduct.getField(), slotProduct.getSlot(), slotProduct.getProduct(), 1));
|
||||
|
||||
MyApp.getInstance().getReportFlowInfoData().setFlowType(6); // 取貨碼 → payment_type 6
|
||||
MyApp.getInstance().getReportFlowInfoData().setFlowBarCode(code);
|
||||
MyApp.getInstance().getReportFlowInfoData().setReportFlowId(code);
|
||||
MyApp.getInstance().getReportFlowInfoData().setOrderId(Tools.generateTimeBasedUUID());
|
||||
MyApp.getInstance().getReportAccessCodeStructure().setAccessCodeId(codeId);
|
||||
|
||||
changeBuy(); // 開啟取貨確認 BuyPickupCodeDialog → 出貨
|
||||
} catch (LogsEmptyException e) {
|
||||
setStatusText(getContext().getString(R.string.product_not_found));
|
||||
openBarcode = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(String message) {
|
||||
openBarcode = true;
|
||||
setStatusText(message);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void changeBuy() {
|
||||
|
||||
@ -593,6 +593,187 @@ public class StarCloudAPI {
|
||||
void onFailure(String message);
|
||||
}
|
||||
|
||||
/** 取貨碼驗證回呼:成功時回傳 code_id 與要出貨的貨道 slot_no。 */
|
||||
public interface PickupVerificationCallback {
|
||||
void onSuccess(String codeId, int slotNo);
|
||||
void onFailure(String message);
|
||||
}
|
||||
|
||||
/**
|
||||
* B660: 取貨碼驗證(邏輯比照 B680 員工卡,驗證通道不同)。
|
||||
* 成功回傳 data.code_id 與 data.slot_no(要出貨的貨道)。
|
||||
*/
|
||||
public void verifyPickupCode(final String code, final PickupVerificationCallback callback) {
|
||||
final String url = getBaseUrl() + "machine/pickup/verify/B660";
|
||||
Log.i(TAG, "Starting B660 request for code: " + code);
|
||||
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
int responseCode = -1;
|
||||
String receive = "";
|
||||
try {
|
||||
JSONObject json = new JSONObject();
|
||||
json.put("code", code);
|
||||
|
||||
java.net.URL reqUrl = new java.net.URL(url);
|
||||
java.net.HttpURLConnection conn = (java.net.HttpURLConnection) reqUrl.openConnection();
|
||||
conn.setRequestMethod("POST");
|
||||
conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
|
||||
conn.setRequestProperty("Accept", "application/json");
|
||||
String machineToken = MyApp.getInstance().getMachine().getApiKey();
|
||||
if (machineToken != null && !machineToken.isEmpty()) {
|
||||
conn.setRequestProperty("Authorization", "Bearer " + machineToken);
|
||||
}
|
||||
conn.setConnectTimeout(10000);
|
||||
conn.setReadTimeout(10000);
|
||||
conn.setDoOutput(true);
|
||||
conn.getOutputStream().write(json.toString().getBytes("UTF-8"));
|
||||
conn.getOutputStream().flush();
|
||||
|
||||
responseCode = conn.getResponseCode();
|
||||
java.io.InputStream is = (responseCode >= 200 && responseCode < 300)
|
||||
? conn.getInputStream() : conn.getErrorStream();
|
||||
if (is != null) {
|
||||
java.io.BufferedReader br = new java.io.BufferedReader(new java.io.InputStreamReader(is, "UTF-8"));
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) sb.append(line);
|
||||
receive = sb.toString();
|
||||
}
|
||||
conn.disconnect();
|
||||
Log.d(TAG, "B660 Response (" + responseCode + "): " + receive);
|
||||
} catch (final Exception e) {
|
||||
Log.e(TAG, "B660 Network Error", e);
|
||||
new android.os.Handler(android.os.Looper.getMainLooper()).post(() -> callback.onFailure("連線失敗: " + e.getMessage()));
|
||||
return;
|
||||
}
|
||||
|
||||
final int finalCode = responseCode;
|
||||
final String finalReceive = receive;
|
||||
new android.os.Handler(android.os.Looper.getMainLooper()).post(() -> {
|
||||
if (finalCode >= 200 && finalCode < 300) {
|
||||
try {
|
||||
JSONObject res = new JSONObject(finalReceive);
|
||||
if (res.optBoolean("success", false)) {
|
||||
JSONObject data = res.optJSONObject("data");
|
||||
String codeId = data != null ? data.optString("code_id", "") : "";
|
||||
int slotNo = data != null ? data.optInt("slot_no", -1) : -1;
|
||||
callback.onSuccess(codeId, slotNo);
|
||||
} else {
|
||||
callback.onFailure(res.optString("message", "取貨碼驗證失敗"));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
callback.onFailure("解析錯誤: " + finalCode);
|
||||
}
|
||||
} else if (finalCode == 404) {
|
||||
callback.onFailure("查無此取貨碼或已使用");
|
||||
} else if (finalCode == 429) {
|
||||
callback.onFailure("錯誤次數過多,請稍後再試");
|
||||
} else if (finalCode == 401) {
|
||||
callback.onFailure("系統認證失效,請聯繫管理員");
|
||||
} else {
|
||||
try {
|
||||
JSONObject res = new JSONObject(finalReceive);
|
||||
callback.onFailure(res.optString("message", "系統連線錯誤 (" + finalCode + ")"));
|
||||
} catch (Exception e) {
|
||||
callback.onFailure("系統連線錯誤 (" + finalCode + ")");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
/**
|
||||
* B670: 通行碼驗證(技師用,邏輯比照 B680,驗證通道不同)。
|
||||
* 成功回傳 data.code_id。
|
||||
*/
|
||||
public void verifyPassCode(final String code, final VerificationCallback callback) {
|
||||
final String url = getBaseUrl() + "machine/passcode/verify/B670";
|
||||
Log.i(TAG, "Starting B670 request for code: " + code);
|
||||
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
int responseCode = -1;
|
||||
String receive = "";
|
||||
try {
|
||||
JSONObject json = new JSONObject();
|
||||
json.put("code", code);
|
||||
|
||||
java.net.URL reqUrl = new java.net.URL(url);
|
||||
java.net.HttpURLConnection conn = (java.net.HttpURLConnection) reqUrl.openConnection();
|
||||
conn.setRequestMethod("POST");
|
||||
conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
|
||||
conn.setRequestProperty("Accept", "application/json");
|
||||
String machineToken = MyApp.getInstance().getMachine().getApiKey();
|
||||
if (machineToken != null && !machineToken.isEmpty()) {
|
||||
conn.setRequestProperty("Authorization", "Bearer " + machineToken);
|
||||
}
|
||||
conn.setConnectTimeout(10000);
|
||||
conn.setReadTimeout(10000);
|
||||
conn.setDoOutput(true);
|
||||
conn.getOutputStream().write(json.toString().getBytes("UTF-8"));
|
||||
conn.getOutputStream().flush();
|
||||
|
||||
responseCode = conn.getResponseCode();
|
||||
java.io.InputStream is = (responseCode >= 200 && responseCode < 300)
|
||||
? conn.getInputStream() : conn.getErrorStream();
|
||||
if (is != null) {
|
||||
java.io.BufferedReader br = new java.io.BufferedReader(new java.io.InputStreamReader(is, "UTF-8"));
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) sb.append(line);
|
||||
receive = sb.toString();
|
||||
}
|
||||
conn.disconnect();
|
||||
Log.d(TAG, "B670 Response (" + responseCode + "): " + receive);
|
||||
} catch (final Exception e) {
|
||||
Log.e(TAG, "B670 Network Error", e);
|
||||
new android.os.Handler(android.os.Looper.getMainLooper()).post(() -> callback.onFailure("連線失敗: " + e.getMessage()));
|
||||
return;
|
||||
}
|
||||
|
||||
final int finalCode = responseCode;
|
||||
final String finalReceive = receive;
|
||||
new android.os.Handler(android.os.Looper.getMainLooper()).post(() -> {
|
||||
if (finalCode >= 200 && finalCode < 300) {
|
||||
try {
|
||||
JSONObject res = new JSONObject(finalReceive);
|
||||
if (res.optBoolean("success", false)) {
|
||||
String codeId = "";
|
||||
if (res.has("data")) {
|
||||
codeId = res.optJSONObject("data").optString("code_id", "");
|
||||
} else {
|
||||
codeId = res.optString("code_id", "");
|
||||
}
|
||||
callback.onSuccess(codeId);
|
||||
} else {
|
||||
callback.onFailure(res.optString("message", "通行碼驗證失敗"));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
callback.onFailure("解析錯誤: " + finalCode);
|
||||
}
|
||||
} else if (finalCode == 404) {
|
||||
callback.onFailure("查無此通行碼或已失效");
|
||||
} else if (finalCode == 429) {
|
||||
callback.onFailure("錯誤次數過多,請稍後再試");
|
||||
} else if (finalCode == 401) {
|
||||
callback.onFailure("系統認證失效,請聯繫管理員");
|
||||
} else {
|
||||
try {
|
||||
JSONObject res = new JSONObject(finalReceive);
|
||||
callback.onFailure(res.optString("message", "系統連線錯誤 (" + finalCode + ")"));
|
||||
} catch (Exception e) {
|
||||
callback.onFailure("系統連線錯誤 (" + finalCode + ")");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
private void saveSettings(JSONObject config) {
|
||||
// 使用 optString 避免欄位缺失導致 JSONException
|
||||
|
||||
|
||||
@ -272,12 +272,7 @@ public class CheckoutAccessCodeDialog extends DialogAbstract {
|
||||
String barCodeString = new String(buffer, 0, size);
|
||||
getHandlerMain().start(getLogs().getClassName(), getContext().getString(R.string.receive_barcode)+":"+ Tools.randomReplace(barCodeString, 0.3)+","+getContext().getString(R.string.send_transaction));//收到條碼,送出交易
|
||||
|
||||
try {
|
||||
MyApp.getInstance().getAccessCodeStructure().setPassCode(barCodeString);
|
||||
httpAPI.checkAccessCode(MyApp.getInstance().getAccessCodeStructure());
|
||||
} catch (LogsParseException | LogsSettingEmptyException e) {
|
||||
getLogs().warning(e);
|
||||
}
|
||||
submitPassCode(barCodeString.trim());
|
||||
|
||||
openBarcode = false;
|
||||
}
|
||||
@ -329,13 +324,36 @@ public class CheckoutAccessCodeDialog extends DialogAbstract {
|
||||
getHandlerMain().start(getClass().getSimpleName(), "通行碼長度不能少於 8 碼");
|
||||
return;
|
||||
}
|
||||
MyApp.getInstance().getAccessCodeStructure().setPassCode(number);
|
||||
httpAPI.checkAccessCode(MyApp.getInstance().getAccessCodeStructure());
|
||||
} catch (LogsParseException | LogsSettingEmptyException e) {
|
||||
submitPassCode(number);
|
||||
} catch (Exception e) {
|
||||
getLogs().warning(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通行碼驗證改走 StarCloudAPI B670(邏輯比照員工卡 B680)。
|
||||
* 成功後保存 code_id 供 MQTT finalize(payment_type=5 通行碼),再進入出貨。
|
||||
*/
|
||||
private void submitPassCode(String code) {
|
||||
new com.unibuy.smartdevice.external.StarCloudAPI(getHandlerMain(), getHandlerMain())
|
||||
.verifyPassCode(code, new com.unibuy.smartdevice.external.StarCloudAPI.VerificationCallback() {
|
||||
@Override
|
||||
public void onSuccess(String codeId) {
|
||||
MyApp.getInstance().getReportFlowInfoData().setFlowType(5); // 通行碼 → payment_type 5
|
||||
MyApp.getInstance().getReportFlowInfoData().setFlowBarCode(code);
|
||||
MyApp.getInstance().getReportFlowInfoData().setReportFlowId(code);
|
||||
MyApp.getInstance().getReportAccessCodeStructure().setAccessCodeId(codeId);
|
||||
getHandlerMain().send(getClass().getSimpleName(), Option.CHANGE_DISPATCH.getOption(), "change dispatch");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(String message) {
|
||||
openBarcode = true; // 允許重新掃碼/輸入
|
||||
getHandlerMain().start(getClass().getSimpleName(), Option.SET_STATUS_TEXT.getOption(), message);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void changeBuy() {
|
||||
closeDialogCountdown.shutdown();
|
||||
changeDialog(BuyDialog.class);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user