add expire time on QR
This commit is contained in:
parent
7d894116dd
commit
7452443a45
@ -14,8 +14,8 @@ android {
|
||||
applicationId "com.utsmm.kbz"
|
||||
minSdk 24
|
||||
targetSdk 33
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
versionCode 2
|
||||
versionName "1.01"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
|
||||
BIN
app/sit/release/baselineProfiles/0/app-sit-release.dm
Normal file
BIN
app/sit/release/baselineProfiles/0/app-sit-release.dm
Normal file
Binary file not shown.
BIN
app/sit/release/baselineProfiles/1/app-sit-release.dm
Normal file
BIN
app/sit/release/baselineProfiles/1/app-sit-release.dm
Normal file
Binary file not shown.
37
app/sit/release/output-metadata.json
Normal file
37
app/sit/release/output-metadata.json
Normal file
@ -0,0 +1,37 @@
|
||||
{
|
||||
"version": 3,
|
||||
"artifactType": {
|
||||
"type": "APK",
|
||||
"kind": "Directory"
|
||||
},
|
||||
"applicationId": "com.utsmm.kbz.sit",
|
||||
"variantName": "sitRelease",
|
||||
"elements": [
|
||||
{
|
||||
"type": "SINGLE",
|
||||
"filters": [],
|
||||
"attributes": [],
|
||||
"versionCode": 2,
|
||||
"versionName": "1.01-sit",
|
||||
"outputFile": "app-sit-release.apk"
|
||||
}
|
||||
],
|
||||
"elementType": "File",
|
||||
"baselineProfiles": [
|
||||
{
|
||||
"minApi": 28,
|
||||
"maxApi": 30,
|
||||
"baselineProfiles": [
|
||||
"baselineProfiles/1/app-sit-release.dm"
|
||||
]
|
||||
},
|
||||
{
|
||||
"minApi": 31,
|
||||
"maxApi": 2147483647,
|
||||
"baselineProfiles": [
|
||||
"baselineProfiles/0/app-sit-release.dm"
|
||||
]
|
||||
}
|
||||
],
|
||||
"minSdkVersionForDexing": 24
|
||||
}
|
||||
@ -42,8 +42,11 @@ import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsSettings;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
@ -190,10 +193,37 @@ public class KPayViewModel extends ViewModel {
|
||||
return createQR(amount, String.valueOf(System.currentTimeMillis()),mid);
|
||||
}
|
||||
|
||||
private int expireTime = 1;
|
||||
|
||||
private void calculateTimeoutMinutes() {
|
||||
String data = SystemParamsOperation.getInstance().getWaveIntervalTime();
|
||||
if (data == null || !data.contains("-")) {
|
||||
data = "15-60"; // fallback
|
||||
}
|
||||
|
||||
try {
|
||||
String[] parts = data.split("-");
|
||||
int waitingTimeSec = Integer.parseInt(parts[1]); // only take second part
|
||||
|
||||
// convert seconds → minutes
|
||||
expireTime = waitingTimeSec / 60;
|
||||
|
||||
// enforce limits 1–120
|
||||
if (expireTime < 1) expireTime = 1;
|
||||
if (expireTime > 120) expireTime = 120;
|
||||
|
||||
} catch (Exception e) {
|
||||
expireTime = 1; // safety fallback
|
||||
LogUtil.d(TAG, "Invalid format for timeout config: " + data);
|
||||
}
|
||||
}
|
||||
|
||||
public KPayQRRequest.QrRequest createQR(String amount, String time,String mid) {
|
||||
String merchOrderId = "NEX"+SystemParamsOperation.getInstance().getCurrentSerialNum()+generateRandomTwoChars();
|
||||
String serialNum = TerminalUtil.getInstance().getSerialNo();
|
||||
String nonceStr = generateNonceStr(); // Generate random nonce_str
|
||||
calculateTimeoutMinutes();
|
||||
String timeoutExpress = expireTime + "m";
|
||||
|
||||
Map<String, Object> bizContent = new HashMap<>();
|
||||
bizContent.put("merch_order_id", merchOrderId);
|
||||
@ -203,7 +233,7 @@ public class KPayViewModel extends ViewModel {
|
||||
bizContent.put("total_amount", amount);
|
||||
bizContent.put("title", "testing");
|
||||
// bizContent.put("operator_id", serialNum);
|
||||
bizContent.put("timeout_express", "100m");
|
||||
bizContent.put("timeout_express", timeoutExpress);
|
||||
bizContent.put("trans_currency", "MMK");
|
||||
bizContent.put("callback_info", "callback");
|
||||
|
||||
@ -226,7 +256,7 @@ public class KPayViewModel extends ViewModel {
|
||||
"testing",
|
||||
amount,
|
||||
"MMK",
|
||||
"100m",
|
||||
timeoutExpress,
|
||||
"callback"
|
||||
);
|
||||
|
||||
|
||||
@ -58,7 +58,7 @@ public class QRPayFragment extends DataBindingFragment {
|
||||
List<QRPayItem> features = new ArrayList<>();
|
||||
features.add(new QRPayItem("Sale", R.drawable.ic_qr_pay, true));
|
||||
if(isQrRefundEnable){
|
||||
features.add(new QRPayItem("Refund", R.drawable.ic_refund, false));
|
||||
features.add(new QRPayItem("Refund", R.drawable.ic_refund, true));
|
||||
}
|
||||
features.add(new QRPayItem("History", R.drawable.ic_history, true));
|
||||
|
||||
|
||||
@ -6,34 +6,89 @@ import com.utsmyanmar.paylibs.utils.LogUtil;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
|
||||
import okhttp3.OkHttp;
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.rxjava3.core.Observable;
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
|
||||
public class DownloadUtil {
|
||||
|
||||
final static String TAG = DownloadUtil.class.getSimpleName();
|
||||
private void downloadFile(String url){
|
||||
try{
|
||||
OkHttpClient okHttpClient = new OkHttpClient();
|
||||
private static final String TAG = DownloadUtil.class.getSimpleName();
|
||||
|
||||
// ==============================
|
||||
// CALLBACK INTERFACE
|
||||
// ==============================
|
||||
public interface DownloadCallback {
|
||||
void onDownloadSuccess(String path);
|
||||
}
|
||||
|
||||
// ==============================
|
||||
// RX ASYNC DOWNLOAD METHOD
|
||||
// ==============================
|
||||
public static void downloadCertificateRx(String url,
|
||||
String dynamicFilename,
|
||||
DownloadCallback callback) {
|
||||
|
||||
Observable.fromCallable(() -> downloadCert(url, dynamicFilename))
|
||||
.subscribeOn(Schedulers.io()) // download on background thread
|
||||
.observeOn(AndroidSchedulers.mainThread()) // callback on main thread
|
||||
.subscribe(path -> {
|
||||
if (path != null) {
|
||||
LogUtil.d(TAG, "Certificate saved at: " + path);
|
||||
if (callback != null) callback.onDownloadSuccess(path);
|
||||
} else {
|
||||
LogUtil.e(TAG, "Certificate download failed.");
|
||||
if (callback != null) callback.onDownloadSuccess(null);
|
||||
}
|
||||
}, error -> {
|
||||
error.printStackTrace();
|
||||
if (callback != null) callback.onDownloadSuccess(null);
|
||||
});
|
||||
}
|
||||
|
||||
// ==============================
|
||||
// ACTUAL DOWNLOAD LOGIC
|
||||
// ==============================
|
||||
public static String downloadCert(String url, String dynamicFilename) {
|
||||
try {
|
||||
OkHttpClient client = new OkHttpClient();
|
||||
Request request = new Request.Builder().url(url).build();
|
||||
Response response = okHttpClient.newCall(request).execute();
|
||||
|
||||
if(!response.isSuccessful()){
|
||||
LogUtil.e(TAG, "file download failed");
|
||||
return;
|
||||
Response response = client.newCall(request).execute();
|
||||
|
||||
if (!response.isSuccessful()) {
|
||||
LogUtil.e(TAG, "Download failed: " + response.code());
|
||||
return null;
|
||||
}
|
||||
byte[] bytes = response.body().bytes();
|
||||
saveFile("cert_file.ctr", bytes);
|
||||
LogUtil.d(TAG, "file saved successfully.");
|
||||
}catch (Exception e){
|
||||
|
||||
// Detect extension (MIME or URL fallback)
|
||||
String contentType = response.header("Content-Type", "");
|
||||
String ext = getExtensionFromContentType(contentType);
|
||||
|
||||
if (ext.isEmpty()) ext = getExtensionFromUrl(url);
|
||||
if (ext.isEmpty()) ext = ".bin"; // final fallback
|
||||
|
||||
// build dynamic filename
|
||||
String filename = dynamicFilename + ext;
|
||||
|
||||
byte[] data = response.body().bytes();
|
||||
String savedPath = saveFile(filename, data);
|
||||
|
||||
return savedPath;
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void saveFile(String filename, byte[] data){
|
||||
try{
|
||||
// ==============================
|
||||
// SAVE FILE TO INTERNAL STORAGE
|
||||
// ==============================
|
||||
private static String saveFile(String filename, byte[] data) {
|
||||
try {
|
||||
File dir = MyApplication.getInstance().getFilesDir();
|
||||
File file = new File(dir, filename);
|
||||
|
||||
@ -42,9 +97,42 @@ public class DownloadUtil {
|
||||
fos.flush();
|
||||
fos.close();
|
||||
|
||||
LogUtil.d(TAG, "Saved file at => " + file.getAbsolutePath());
|
||||
return file.getAbsolutePath();
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// ==============================
|
||||
// MIME TYPE → EXTENSION
|
||||
// ==============================
|
||||
private static String getExtensionFromContentType(String contentType) {
|
||||
if (contentType == null) return "";
|
||||
|
||||
switch (contentType) {
|
||||
case "application/x-x509-ca-cert":
|
||||
return ".crt";
|
||||
case "application/pkix-cert":
|
||||
return ".cer";
|
||||
case "application/x-pem-file":
|
||||
case "application/octet-stream":
|
||||
return ".pem";
|
||||
case "application/x-pkcs12":
|
||||
return ".p12";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
// ==============================
|
||||
// URL EXTENSION PARSER
|
||||
// ==============================
|
||||
private static String getExtensionFromUrl(String url) {
|
||||
if (url == null) return "";
|
||||
int lastDot = url.lastIndexOf('.');
|
||||
if (lastDot == -1) return "";
|
||||
return url.substring(lastDot);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@ import android.content.pm.PackageInfo;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.utsmm.kbz.util.DownloadUtil;
|
||||
import com.utsmyanmar.baselib.emv.EmvParamOperation;
|
||||
import com.utsmyanmar.baselib.network.model.sirius.SiriusHost;
|
||||
import com.utsmyanmar.baselib.network.model.sirius.SiriusMerchant;
|
||||
@ -608,6 +609,17 @@ public class TMSSetupsImpl implements TMSSetups{
|
||||
SystemParamsOperation.getInstance().setQrRefundEnable(parseBoolean(data));
|
||||
} else if (TextUtils.equals(name, "tpdu_value")){
|
||||
SystemParamsOperation.getInstance().setTpduValue(data);
|
||||
} else if (TextUtils.equals(name, "certificate_file")){
|
||||
String tmsAddress = SystemParamsOperation.getInstance().getTmsAddress();
|
||||
String url = tmsAddress+"/file/download?filePath="+data;
|
||||
DownloadUtil.downloadCertificateRx(url, "certificate_file", path -> {
|
||||
if(path != null){
|
||||
SystemParamsOperation.getInstance().setCertFilePath(path);
|
||||
LogUtil.d(TAG, "Cert file path saved in SystemParams => " + path);
|
||||
}else{
|
||||
LogUtil.e(TAG, "Failed to download certificate file");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -285,8 +285,8 @@ public class NetworkModule {
|
||||
tmsAddress = getTMSUrlFromNative();
|
||||
}
|
||||
|
||||
String baseUrl = tmsAddress.trim() + "/api/v1/";
|
||||
// String baseUrl = tmsAddress.trim() + "/";
|
||||
// String baseUrl = tmsAddress.trim() + "/api/v1/";
|
||||
String baseUrl = tmsAddress.trim() + "/";
|
||||
|
||||
final Gson gson =
|
||||
new GsonBuilder().create();
|
||||
|
||||
@ -0,0 +1 @@
|
||||
i/nexgo-sdk-dlkey-1.0.3-runtime_dex
|
||||
@ -0,0 +1 @@
|
||||
i/jars/classes.jar
|
||||
@ -0,0 +1 @@
|
||||
o/nexgo-sdk-dlkey-1.0.3-runtime
|
||||
Binary file not shown.
@ -0,0 +1 @@
|
||||
i/nexgo-sdk-dlkey-1.0.3-runtime_global-synthetics
|
||||
@ -1605,4 +1605,15 @@ public class SystemParamsOperation {
|
||||
SystemParamsSettings params = getSystemParamsSettings();
|
||||
return params.getQrRefundEnable();
|
||||
}
|
||||
|
||||
public void setCertFilePath(String path) {
|
||||
SystemParamsSettings params = getSystemParamsSettings();
|
||||
params.setCertFilePath(path);
|
||||
saveSystemParamsSettings(params);
|
||||
}
|
||||
|
||||
public String getCertFilePath(){
|
||||
SystemParamsSettings params = getSystemParamsSettings();
|
||||
return params.getCertFilePath();
|
||||
}
|
||||
}
|
||||
@ -42,8 +42,8 @@ public class SystemParamsSettings implements Serializable {
|
||||
|
||||
// private String tmsAddress = "https://tms.smile-mm.com";
|
||||
// private String tmsAddress = "http://128.199.170.203";
|
||||
private String tmsAddress = "http://sirius-nest.utsmyanmar.com";
|
||||
// private String tmsAddress = "https://api-tms-uat.kbzbank.com:8443/sirius";
|
||||
// private String tmsAddress = "http://sirius-nest.utsmyanmar.com";
|
||||
private String tmsAddress = "https://api-tms-uat.kbzbank.com:8443/sirius";
|
||||
private String ereceiptAddress = "http://receipt-nest.utsmyanmar.com";
|
||||
|
||||
private String terminalCapability = "E0E8C8";
|
||||
@ -242,6 +242,7 @@ public class SystemParamsSettings implements Serializable {
|
||||
|
||||
private boolean qrDecimalEnable = false;
|
||||
private boolean qrRefundEnable = false;
|
||||
private String certFilePath = "";
|
||||
|
||||
public boolean isQrPartialRefundEnable(){
|
||||
return qrPartialRefundEnable;
|
||||
@ -961,6 +962,14 @@ public class SystemParamsSettings implements Serializable {
|
||||
return qrRefundEnable;
|
||||
}
|
||||
|
||||
public void setCertFilePath(String path) {
|
||||
this.certFilePath = path;
|
||||
}
|
||||
|
||||
public String getCertFilePath() {
|
||||
return certFilePath;
|
||||
}
|
||||
|
||||
/* // 流水号起始
|
||||
private String serialNum = Configs.getInstance().SERIAL_NUM();
|
||||
// 批次号起始
|
||||
|
||||
Loading…
Reference in New Issue
Block a user