diff --git a/CHANGELOG.md b/CHANGELOG.md index 22261b7..3a397e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -89,4 +89,9 @@ Refund - 1000 - 6. Reprint Last Settlement Report - Same process with settlement \ No newline at end of file + Same process with settlement + +## [2.41] + - clear batch time fix + - removed mock qr button + - support Id fix for signature \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 2fcc547..c1a4f47 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -39,8 +39,8 @@ android { applicationId "com.utsmm.kbz.uat" versionNameSuffix "-uat" resValue "string", "app_name", "KBZ-UAT" - versionCode 44 - versionName "2.39" + versionCode 46 + versionName "2.41" } prod { diff --git a/app/src/main/java/com/utsmm/kbz/ui/core_ui/ProcessingFragment.java b/app/src/main/java/com/utsmm/kbz/ui/core_ui/ProcessingFragment.java index 4c4ebaf..1d07631 100644 --- a/app/src/main/java/com/utsmm/kbz/ui/core_ui/ProcessingFragment.java +++ b/app/src/main/java/com/utsmm/kbz/ui/core_ui/ProcessingFragment.java @@ -573,6 +573,7 @@ public class ProcessingFragment extends DataBindingFragment { request.setDE39(isSuccess ? "A" : "E"); request.setDE41(terminalId); request.setDE42(merchantId); + request.setHostId(SystemParamsOperation.getInstance().getHostId()); request.setDE49(mapCurrency(payDetail.getCurrencyCode())); request.setSerial(serial); request.setInvoiceNumber(payDetail.getInvoiceNo()); diff --git a/app/src/main/java/com/utsmm/kbz/ui/core_ui/SignatureFragment.java b/app/src/main/java/com/utsmm/kbz/ui/core_ui/SignatureFragment.java index 647932a..c26f46b 100644 --- a/app/src/main/java/com/utsmm/kbz/ui/core_ui/SignatureFragment.java +++ b/app/src/main/java/com/utsmm/kbz/ui/core_ui/SignatureFragment.java @@ -169,7 +169,15 @@ public class SignatureFragment extends DataBindingFragment { } else { // Handle manual signature on paper sharedViewModel.signBitmap = null; // No digital signature - LogUtil.d(TAG, "Manual signature on paper selected - no digital signature stored"); + PayDetail payDetail = sharedViewModel.payDetail.getValue(); + EReceiptCardRequest request = EReceiptHelper.buildEReceiptCardReceipt( + requireContext(), + payDetail, + true, + BaseErrorCode.getCode(payDetail.getTradeAnswerCode()), + null); + sharedViewModel.pushReceipt(request); + LogUtil.d(TAG, "Manual signature on paper selected - receipt submitted without image"); callNextScreen(); } } diff --git a/app/src/main/java/com/utsmm/kbz/ui/qr_pay/QRPayFragment.java b/app/src/main/java/com/utsmm/kbz/ui/qr_pay/QRPayFragment.java index 4d8b27f..1962a26 100644 --- a/app/src/main/java/com/utsmm/kbz/ui/qr_pay/QRPayFragment.java +++ b/app/src/main/java/com/utsmm/kbz/ui/qr_pay/QRPayFragment.java @@ -63,7 +63,7 @@ public class QRPayFragment extends DataBindingFragment { features.add(new QRPayItem("Refund", R.drawable.ic_refund, true)); } features.add(new QRPayItem("History", R.drawable.ic_history, true)); - features.add(new QRPayItem("Mock QR", R.drawable.ic_qr_pay, true)); +// features.add(new QRPayItem("Mock QR", R.drawable.ic_qr_pay, true)); // List features = List.of( // new QRPayItem("Sale", R.drawable.ic_qr_pay, true), diff --git a/app/src/main/java/com/utsmm/kbz/util/helper/EReceiptHelper.java b/app/src/main/java/com/utsmm/kbz/util/helper/EReceiptHelper.java index 35e7cb8..e244eb1 100644 --- a/app/src/main/java/com/utsmm/kbz/util/helper/EReceiptHelper.java +++ b/app/src/main/java/com/utsmm/kbz/util/helper/EReceiptHelper.java @@ -56,6 +56,7 @@ public class EReceiptHelper { request.setDE39(isSuccess ? "A" : "E"); request.setDE41(terminalId); request.setDE42(merchantId); + request.setHostId(SystemParamsOperation.getInstance().getHostId()); request.setDE49(mapCurrency(payDetail.getCurrencyCode())); request.setSerial(serial); request.setInvoiceNumber(payDetail.getInvoiceNo()); diff --git a/app/src/main/java/com/utsmm/kbz/util/tms/TMSSetupsImpl.java b/app/src/main/java/com/utsmm/kbz/util/tms/TMSSetupsImpl.java index f2faffe..1632244 100644 --- a/app/src/main/java/com/utsmm/kbz/util/tms/TMSSetupsImpl.java +++ b/app/src/main/java/com/utsmm/kbz/util/tms/TMSSetupsImpl.java @@ -460,7 +460,7 @@ public class TMSSetupsImpl implements TMSSetups{ SystemParamsOperation.getInstance().setRandomPinPad(parseBoolean(data)); } else if (TextUtils.equals(name,"clear_batch_time")) { - SystemParamsOperation.getInstance().setClearBatchTime("22:00"); + SystemParamsOperation.getInstance().setClearBatchTime(data); } else if (TextUtils.equals(name,"alert_sound_enable")) { SystemParamsOperation.getInstance().setAlertSound(parseBoolean(data)); diff --git a/app/src/test/java/com/utsmm/kbz/SignGenerateTest.java b/app/src/test/java/com/utsmm/kbz/SignGenerateTest.java index 17e9159..5ec0c57 100644 --- a/app/src/test/java/com/utsmm/kbz/SignGenerateTest.java +++ b/app/src/test/java/com/utsmm/kbz/SignGenerateTest.java @@ -12,6 +12,19 @@ import java.util.TreeMap; public class SignGenerateTest { + @Test + public void tmsSignatureMatchesToolForFixedTimestamp() { + String secret = "y812J21lhha11OS"; + String timestamp = "1786609802730"; + + String signature = EReceiptHelper.sha256("{}" + secret + timestamp); + + assertEquals( + "3f1bfe50289d706074560fa22f424f3665c9c3022362aa89a6ea9c37469a0774", + signature + ); + } + private static final String APP_KEY = "UTSMMuat@2025"; private static final String EXPECTED_SIGN = "D86AE09024C6581273C27B95A3BDBDBF3AC8EC20191365C8047ED6C42FC00DA5"; @@ -425,4 +438,4 @@ public class SignGenerateTest { // This test is for debugging - it doesn't need to pass assertTrue("This test is for debugging purposes", true); } -} \ No newline at end of file +} diff --git a/app/uat/release/baselineProfiles/0/app-uat-release.dm b/app/uat/release/baselineProfiles/0/app-uat-release.dm index 8218f27..d07737f 100644 Binary files a/app/uat/release/baselineProfiles/0/app-uat-release.dm and b/app/uat/release/baselineProfiles/0/app-uat-release.dm differ diff --git a/app/uat/release/baselineProfiles/1/app-uat-release.dm b/app/uat/release/baselineProfiles/1/app-uat-release.dm index 6929be1..f22384c 100644 Binary files a/app/uat/release/baselineProfiles/1/app-uat-release.dm and b/app/uat/release/baselineProfiles/1/app-uat-release.dm differ diff --git a/app/uat/release/output-metadata.json b/app/uat/release/output-metadata.json index c65d3e6..d9a3153 100644 --- a/app/uat/release/output-metadata.json +++ b/app/uat/release/output-metadata.json @@ -11,8 +11,8 @@ "type": "SINGLE", "filters": [], "attributes": [], - "versionCode": 44, - "versionName": "2.39-uat", + "versionCode": 46, + "versionName": "2.41-uat", "outputFile": "app-uat-release.apk" } ], diff --git a/baselib/src/main/java/com/utsmyanmar/baselib/emv/EmvParamOperation.java b/baselib/src/main/java/com/utsmyanmar/baselib/emv/EmvParamOperation.java index f848932..6bd8a1b 100644 --- a/baselib/src/main/java/com/utsmyanmar/baselib/emv/EmvParamOperation.java +++ b/baselib/src/main/java/com/utsmyanmar/baselib/emv/EmvParamOperation.java @@ -116,7 +116,7 @@ public class EmvParamOperation extends ParamOperation{ processPayWave(); processPayPass(); processQuickPass(); -// processJSpeedy(); + processJSpeedy(); processMPUCtls(); processChips(); processRids(); diff --git a/baselib/src/main/java/com/utsmyanmar/baselib/network/model/e_receipt/EReceiptCardRequest.java b/baselib/src/main/java/com/utsmyanmar/baselib/network/model/e_receipt/EReceiptCardRequest.java index 4bb9148..4c086f9 100644 --- a/baselib/src/main/java/com/utsmyanmar/baselib/network/model/e_receipt/EReceiptCardRequest.java +++ b/baselib/src/main/java/com/utsmyanmar/baselib/network/model/e_receipt/EReceiptCardRequest.java @@ -14,6 +14,7 @@ public class EReceiptCardRequest { private String DE7; private String DE4; private String appId; + private String hostId; private String invoiceNumber; private String DE11; private String description; @@ -72,6 +73,10 @@ public class EReceiptCardRequest { public String getAppId(){ return appId; } + + public String getHostId(){ + return hostId; + } public String getDE55(){return DE55;} @@ -133,6 +138,10 @@ public class EReceiptCardRequest { this.appId = appId; } + public void setHostId(String hostId){ + this.hostId = hostId; + } + public void setInvoiceNumber(String invoiceNumber){ this.invoiceNumber = invoiceNumber; } diff --git a/baselib/src/main/java/com/utsmyanmar/baselib/repo/Repository.java b/baselib/src/main/java/com/utsmyanmar/baselib/repo/Repository.java index 51fab5a..a39489a 100644 --- a/baselib/src/main/java/com/utsmyanmar/baselib/repo/Repository.java +++ b/baselib/src/main/java/com/utsmyanmar/baselib/repo/Repository.java @@ -41,10 +41,7 @@ import com.utsmyanmar.baselib.network.model.KPayRefund; import com.utsmyanmar.baselib.repo.local.PayWaveRepository; import com.utsmyanmar.baselib.util.EReceiptHelper; import com.utsmyanmar.paylibs.model.PayDetail; -import com.utsmyanmar.paylibs.utils.LogUtil; -import java.util.HashMap; -import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.TreeMap; @@ -128,7 +125,6 @@ public class Repository { } public Observable sendReceipt(Object body){ String apiSecret = BuildConfig.ERECEIPT_SECRET; -// LogUtil.d("kmk", "receipt secret =>" + apiSecret); String timestamp = String.valueOf(System.currentTimeMillis()); String bodyString = new Gson().toJson(body); String dataToHash = bodyString + apiSecret + timestamp; @@ -141,7 +137,6 @@ public class Repository { String timestamp = String.valueOf(System.currentTimeMillis()); String bodyString = buildMultipartSignaturePayload(request); String dataToHash = bodyString + apiSecret + timestamp; -// LogUtil.d("HTTP", dataToHash); String apiKey = EReceiptHelper.sha256(dataToHash); Map fields = buildFormFields(request); @@ -155,31 +150,33 @@ public class Repository { } private String buildMultipartSignaturePayload(EReceiptCardRequest request) { - Map flatBody = new LinkedHashMap<>(); + Map flatBody = new TreeMap<>(); putIfNotEmpty(flatBody, "DE2", request.getDE2()); - putIfNotEmpty(flatBody, "DE3", request.getDE3()); - putIfNotEmpty(flatBody, "DE4", request.getDE4()); - putIfNotEmpty(flatBody, "DE7", request.getDE7()); - putIfNotEmpty(flatBody, "DE11", request.getDE11()); - putIfNotEmpty(flatBody, "DE14", request.getDE14()); putIfNotEmpty(flatBody, "DE22", request.getDE22()); - putIfNotEmpty(flatBody, "DE37", request.getDE37()); - putIfNotEmpty(flatBody, "DE38", request.getDE38()); + putIfNotEmpty(flatBody, "DE3", request.getDE3()); putIfNotEmpty(flatBody, "DE39", request.getDE39()); putIfNotEmpty(flatBody, "DE41", request.getDE41()); putIfNotEmpty(flatBody, "DE42", request.getDE42()); - putIfNotEmpty(flatBody, "DE43", request.getDE43()); - putIfNotEmpty(flatBody, "DE48", request.getDE48()); - putIfNotEmpty(flatBody, "DE49", request.getDE49()); - putIfNotEmpty(flatBody, "DE55", request.getDE55()); - putIfNotEmpty(flatBody, "appId", request.getAppId()); - putIfNotEmpty(flatBody, "batchNumber", request.getBatchNumber()); - putIfNotEmpty(flatBody, "cardLabel", request.getCardLabel()); - putIfNotEmpty(flatBody, "description", request.getDescription()); - putIfNotEmpty(flatBody, "invoiceNumber", request.getInvoiceNumber()); putIfNotEmpty(flatBody, "serial", request.getSerial()); + putIfNotEmpty(flatBody, "DE49", request.getDE49()); + putIfNotEmpty(flatBody, "DE37", request.getDE37()); + putIfNotEmpty(flatBody, "DE7", request.getDE7()); + putIfNotEmpty(flatBody, "DE4", request.getDE4()); + putIfNotEmpty(flatBody, "appId", request.getAppId()); + putIfNotEmpty(flatBody, "hostId", request.getHostId()); + putIfNotEmpty(flatBody, "invoiceNumber", request.getInvoiceNumber()); + putIfNotEmpty(flatBody, "DE11", request.getDE11()); + putIfNotEmpty(flatBody, "description", request.getDescription()); + putIfNotEmpty(flatBody, "DE38", request.getDE38()); + putIfNotEmpty(flatBody, "batchNumber", request.getBatchNumber()); + putValueOrEmpty(flatBody, "DE55", request.getDE55()); + putIfNotEmpty(flatBody, "DE14", request.getDE14()); + putIfNotEmpty(flatBody, "cardLabel", request.getCardLabel()); + putIfNotEmpty(flatBody, "DE43", request.getDE43()); + putValueOrEmpty(flatBody, "DE48", request.getDE48()); - return new Gson().toJson(new TreeMap<>(flatBody)); + // DE115 is intentionally omitted because it is sent as the image part. + return new Gson().toJson(flatBody); } private void putIfNotEmpty(Map map, String key, String value) { @@ -188,8 +185,12 @@ public class Repository { } } + private void putValueOrEmpty(Map map, String key, String value) { + map.put(key, value == null || value.trim().isEmpty() ? "" : value); + } + private Map buildFormFields(EReceiptCardRequest request) { - Map map = new HashMap<>(); + Map map = new TreeMap<>(); putField(map, "DE2", request.getDE2()); putField(map, "DE3", request.getDE3()); putField(map, "DE4", request.getDE4()); @@ -203,10 +204,11 @@ public class Repository { putField(map, "DE41", request.getDE41()); putField(map, "DE42", request.getDE42()); putField(map, "DE43", request.getDE43()); - putField(map, "DE48", request.getDE48()); + putFieldValueOrEmpty(map, "DE48", request.getDE48()); putField(map, "DE49", request.getDE49()); - putField(map, "DE55", request.getDE55()); + putFieldValueOrEmpty(map, "DE55", request.getDE55()); putField(map, "appId", request.getAppId()); + putField(map, "hostId", request.getHostId()); putField(map, "batchNumber", request.getBatchNumber()); putField(map, "cardLabel", request.getCardLabel()); putField(map, "description", request.getDescription()); @@ -221,6 +223,11 @@ public class Repository { } } + private void putFieldValueOrEmpty(Map map, String key, String value) { + String normalizedValue = value == null || value.trim().isEmpty() ? "" : value; + map.put(key, RequestBody.create(MediaType.parse("text/plain"), normalizedValue)); + } + public void insertPayDetail(PayDetail payDetail){ payDetailDao.insert(payDetail);} public Completable insertPay(PayDetail payDetail) { return payDetailDao.insertPay(payDetail); } diff --git a/baselib/src/main/res/raw/contacts_config.json b/baselib/src/main/res/raw/contacts_config.json index e4066af..dedb685 100644 --- a/baselib/src/main/res/raw/contacts_config.json +++ b/baselib/src/main/res/raw/contacts_config.json @@ -530,7 +530,7 @@ "currencyCode": "0104" }, { - "aidEnable": false, + "aidEnable": true, "aid": "A00000006510", "cardScheme": "JCB", "applicationVersion": "0200", @@ -553,7 +553,7 @@ "currencyCode": "0104" }, { - "aidEnable": false, + "aidEnable": true, "aid": "A0000000651010", "cardScheme": "JCB", "applicationVersion": "0200", @@ -576,7 +576,7 @@ "currencyCode": "0104" }, { - "aidEnable": false, + "aidEnable": true, "aid": "A0000001570040", "cardScheme": "JCB", "applicationVersion": "0200", diff --git a/paylibs/src/main/java/com/utsmyanmar/paylibs/utils/core_utils/SystemParamsSettings.java b/paylibs/src/main/java/com/utsmyanmar/paylibs/utils/core_utils/SystemParamsSettings.java index 8d4b4fe..172e37e 100644 --- a/paylibs/src/main/java/com/utsmyanmar/paylibs/utils/core_utils/SystemParamsSettings.java +++ b/paylibs/src/main/java/com/utsmyanmar/paylibs/utils/core_utils/SystemParamsSettings.java @@ -46,7 +46,6 @@ public class SystemParamsSettings implements Serializable { // private String ereceiptAddress = "https://api-tms-uat.kbzbank.com:8443/receipt"; private String tmsAddress = "https://sirius-nest.utsmyanmar.com/api/v1"; private String ereceiptAddress = "https://receipt-nest.utsmyanmar.com"; -// private String ereceiptAddress = "http://192.168.10.104:3003"; private String binValues = ""; private String restrictedBinValues = "";