dynamic refund certi

This commit is contained in:
MooN 2025-12-11 23:43:27 +06:30
parent f2e797a0dc
commit 299c8fc892
6 changed files with 242 additions and 74 deletions

View File

@ -194,7 +194,8 @@ public class QRTransactionFragment extends DataBindingFragment implements DataBi
} }
private void setUpCountDown() { private void setUpCountDown() {
setupTimeout(10, new TimeoutCallback() { int totalTime = intervalInSec * totalCount;
setupTimeout(totalTime, new TimeoutCallback() {
@Override @Override
public void onTrick(long trickTime) { public void onTrick(long trickTime) {
sharedViewModel.countDownTxt.setValue((trickTime / 1000)+""); sharedViewModel.countDownTxt.setValue((trickTime / 1000)+"");

View File

@ -120,7 +120,7 @@ public class DownloadUtil {
case "application/octet-stream": case "application/octet-stream":
return ".pem"; return ".pem";
case "application/x-pkcs12": case "application/x-pkcs12":
return ".p12"; return ".pkcs12";
default: default:
return ""; return "";
} }

View File

@ -215,7 +215,6 @@ public class TMSSetupsImpl implements TMSSetups{
// SystemParamsOperation.getInstance().setSecHostCurrency(currencyTextToCode(siriusHost.getCurrency())); // SystemParamsOperation.getInstance().setSecHostCurrency(currencyTextToCode(siriusHost.getCurrency()));
// } // }
} }
if (siriusHost.getShortCode().isEmpty()) { if (siriusHost.getShortCode().isEmpty()) {
SystemParamsOperation.getInstance().setShortCode(""); SystemParamsOperation.getInstance().setShortCode("");
} }
@ -608,8 +607,18 @@ public class TMSSetupsImpl implements TMSSetups{
} else if (TextUtils.equals(name, "tpdu_value")){ } else if (TextUtils.equals(name, "tpdu_value")){
SystemParamsOperation.getInstance().setTpduValue(data); SystemParamsOperation.getInstance().setTpduValue(data);
} else if (TextUtils.equals(name, "certificate_file")){ } else if (TextUtils.equals(name, "certificate_file")){
if (TextUtils.isEmpty(data)) {
LogUtil.e(TAG, "certificate_file value NULL from TMS");
continue;
}
String tmsAddress = SystemParamsOperation.getInstance().getTmsAddress(); String tmsAddress = SystemParamsOperation.getInstance().getTmsAddress();
String url = tmsAddress+"/file/download?filePath="+data; if (TextUtils.isEmpty(tmsAddress)) {
LogUtil.e(TAG, "TMS address is NULL — cannot download certificate");
continue; // or return;
}
// String url = tmsAddress+"/file/download?filePath="+data;
String url = tmsAddress+"/api/v1/file/download?filePath="+data; //for local
DownloadUtil.downloadCertificateRx(url, "certificate_file", path -> { DownloadUtil.downloadCertificateRx(url, "certificate_file", path -> {
if(path != null){ if(path != null){
SystemParamsOperation.getInstance().setCertFilePath(path); SystemParamsOperation.getInstance().setCertFilePath(path);
@ -618,6 +627,30 @@ public class TMSSetupsImpl implements TMSSetups{
LogUtil.e(TAG, "Failed to download certificate file"); LogUtil.e(TAG, "Failed to download certificate file");
} }
}); });
} else if (TextUtils.equals(name, "certificate_client")){
if (TextUtils.isEmpty(data)) {
LogUtil.e(TAG, "certificate_file value NULL from TMS");
continue;
}
String tmsAddress = SystemParamsOperation.getInstance().getTmsAddress();
if (TextUtils.isEmpty(tmsAddress)) {
LogUtil.e(TAG, "TMS address is NULL — cannot download certificate");
continue; // or return;
}
// String url = tmsAddress+"/file/download?filePath="+data;
String url = tmsAddress+"/api/v1/file/download?filePath="+data; //for local
DownloadUtil.downloadCertificateRx(url, "certificate_client", path -> {
if(path != null){
SystemParamsOperation.getInstance().setCertClientFilePath(path);
LogUtil.d(TAG, "Cert client file path saved in SystemParams => " + path);
}else{
LogUtil.e(TAG, "Failed to download certificate client file");
}
});
}
else if (TextUtils.equals(name, "certificate_password")) {
SystemParamsOperation.getInstance().setCertificatePassword(data);
} }
} }

View File

@ -1,6 +1,8 @@
package com.utsmyanmar.baselib.di; package com.utsmyanmar.baselib.di;
import android.content.Context; import android.content.Context;
import android.text.TextUtils;
import android.util.Log;
import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -20,6 +22,7 @@ import com.utsmyanmar.paylibs.Constant;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation; import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import com.utsmyanmar.baselib.R; import com.utsmyanmar.baselib.R;
import java.io.FileInputStream;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
@ -46,6 +49,7 @@ import javax.net.ssl.X509TrustManager;
import dagger.Module; import dagger.Module;
import dagger.Provides; import dagger.Provides;
import dagger.Reusable;
import dagger.hilt.InstallIn; import dagger.hilt.InstallIn;
import dagger.hilt.android.qualifiers.ApplicationContext; import dagger.hilt.android.qualifiers.ApplicationContext;
import dagger.hilt.components.SingletonComponent; import dagger.hilt.components.SingletonComponent;
@ -301,85 +305,175 @@ public class NetworkModule {
} }
@Provides // @Provides
@Singleton // @Singleton
@KPayRefundRetrofit // @KPayRefundRetrofit
public Retrofit provideKPayRefundRetrofit(@ApplicationContext Context context) { // public Retrofit provideKPayRefundRetrofit(@ApplicationContext Context context) {
char[] password = "test123".toCharArray(); // char[] password = "test123".toCharArray();
//
// try {
//
// if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
// Security.addProvider(new BouncyCastleProvider());
// }
// // Client keystore
// KeyStore clientKeyStore = KeyStore.getInstance("PKCS12",new BouncyCastleProvider());
// InputStream clientStream = context.getResources().openRawResource(R.raw.client);
// clientKeyStore.load(clientStream, password);
// clientStream.close();
//
// KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
// kmf.init(clientKeyStore, password);
// KeyManager[] keyManagers = kmf.getKeyManagers();
//
// InputStream caInput = context.getResources().openRawResource(R.raw.certi);
// CertificateFactory cf = CertificateFactory.getInstance("X.509");
// Certificate ca = cf.generateCertificate(caInput);
//
// KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
// keyStore.load(null, null);
// keyStore.setCertificateEntry("ca", ca);
//
// TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
// tmf.init(keyStore);
// TrustManager[] trustManagers = tmf.getTrustManagers();
//
// X509TrustManager x509TrustManager = null;
// for (TrustManager tm : trustManagers) {
// if (tm instanceof X509TrustManager) {
// x509TrustManager = (X509TrustManager) tm;
// break;
// }
// }
//
// SSLContext sslContext = SSLContext.getInstance("TLS");
// sslContext.init(kmf.getKeyManagers(), new TrustManager[]{x509TrustManager}, null);
//
// HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
// loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
//
// OkHttpClient okHttp = new OkHttpClient.Builder()
// .sslSocketFactory(sslContext.getSocketFactory(), x509TrustManager)
// .addInterceptor(loggingInterceptor)
// .hostnameVerifier(new HostnameVerifier() {
// @Override
// public boolean verify(String hostname, SSLSession session) {
// return true;
// }
// })
// .build();
//
// return new Retrofit.Builder()
// .baseUrl(Refund_Base_Url)
// .client(okHttp)
// .addCallAdapterFactory(RxJava3CallAdapterFactory.create())
// .addConverterFactory(GsonConverterFactory.create())
// .build();
//
// } catch (Exception e) {
// e.printStackTrace();
//
// OkHttpClient okHttp = new OkHttpClient();
// return new Retrofit.Builder()
// .baseUrl(Refund_Base_Url)
// .client(okHttp)
// .addConverterFactory(GsonConverterFactory.create())
// .build();
//
//// throw new RuntimeException("Failed to create Retrofit instance", e);
// }
//
// }
try { @Provides
@Reusable
@KPayRefundRetrofit
public Retrofit provideKPayRefundRetrofit(@ApplicationContext Context context) {
if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) { // char[] password = "test123".toCharArray();
Security.addProvider(new BouncyCastleProvider());
}
// Client keystore
KeyStore clientKeyStore = KeyStore.getInstance("PKCS12",new BouncyCastleProvider());
InputStream clientStream = context.getResources().openRawResource(R.raw.client);
clientKeyStore.load(clientStream, password);
clientStream.close();
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); String pass = SystemParamsOperation.getInstance().getCertificatePassword();
kmf.init(clientKeyStore, password); if (TextUtils.isEmpty(pass)) {
KeyManager[] keyManagers = kmf.getKeyManagers(); LogUtil.e("RefundCert", "Certificate password is missing!");
pass = "test123";
}
LogUtil.d("kmk", "pass => "+pass);
InputStream caInput = context.getResources().openRawResource(R.raw.certi); char[] password = pass.toCharArray();
CertificateFactory cf = CertificateFactory.getInstance("X.509");
Certificate ca = cf.generateCertificate(caInput);
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); try {
keyStore.load(null, null); // Required for PKCS12 loading on Android
keyStore.setCertificateEntry("ca", ca); Security.removeProvider("BC");
Security.addProvider(new BouncyCastleProvider());
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); String clientPath = SystemParamsOperation.getInstance().getCertClientFilePath();
tmf.init(keyStore); LogUtil.d("kmk", "client path => " + clientPath);
TrustManager[] trustManagers = tmf.getTrustManagers(); String caPath = SystemParamsOperation.getInstance().getCertFilePath();
LogUtil.d("kmk", "ca path => " + caPath);
X509TrustManager x509TrustManager = null; if (TextUtils.isEmpty(clientPath) || TextUtils.isEmpty(caPath)) {
for (TrustManager tm : trustManagers) { LogUtil.e("RefundCert", "Certificate files missing.");
if (tm instanceof X509TrustManager) { throw new RuntimeException("No certificate files found.");
x509TrustManager = (X509TrustManager) tm;
break;
}
}
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(kmf.getKeyManagers(), new TrustManager[]{x509TrustManager}, null);
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient okHttp = new OkHttpClient.Builder()
.sslSocketFactory(sslContext.getSocketFactory(), x509TrustManager)
.addInterceptor(loggingInterceptor)
.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
})
.build();
return new Retrofit.Builder()
.baseUrl(Refund_Base_Url)
.client(okHttp)
.addCallAdapterFactory(RxJava3CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
} catch (Exception e) {
e.printStackTrace();
OkHttpClient okHttp = new OkHttpClient();
return new Retrofit.Builder()
.baseUrl(Refund_Base_Url)
.client(okHttp)
.addConverterFactory(GsonConverterFactory.create())
.build();
// throw new RuntimeException("Failed to create Retrofit instance", e);
} }
// Load PKCS12 file
KeyStore clientKeyStore = KeyStore.getInstance("PKCS12", "BC");
FileInputStream clientStream = new FileInputStream(clientPath);
clientKeyStore.load(clientStream, password);
clientStream.close();
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(clientKeyStore, password);
// Load CA certificate from .crt
FileInputStream caStream = new FileInputStream(caPath);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
Certificate ca = cf.generateCertificate(caStream);
caStream.close();
// Create trust store
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(null);
trustStore.setCertificateEntry("ca", ca);
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(trustStore);
X509TrustManager x509TrustManager = (X509TrustManager) tmf.getTrustManagers()[0];
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(kmf.getKeyManagers(), new TrustManager[]{x509TrustManager}, null);
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient okHttp = new OkHttpClient.Builder()
.sslSocketFactory(sslContext.getSocketFactory(), x509TrustManager)
.addInterceptor(interceptor)
.hostnameVerifier((h, s) -> true)
.build();
return new Retrofit.Builder()
.baseUrl(Refund_Base_Url)
.client(okHttp)
.addCallAdapterFactory(RxJava3CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
} catch (Exception e) {
LogUtil.e("RefundSSL", "Error: " + e.getMessage());
e.printStackTrace();
// Provide fallback Retrofit to avoid crash, but no SSL
return new Retrofit.Builder()
.baseUrl(Refund_Base_Url)
.client(new OkHttpClient())
.addCallAdapterFactory(RxJava3CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
} }
}
@Provides @Provides
@Singleton @Singleton

View File

@ -1627,4 +1627,26 @@ public class SystemParamsOperation {
SystemParamsSettings params = getSystemParamsSettings(); SystemParamsSettings params = getSystemParamsSettings();
return params.getCertFilePath(); return params.getCertFilePath();
} }
public void setCertClientFilePath(String path) {
SystemParamsSettings params = getSystemParamsSettings();
params.setCertClientFilePath(path);
saveSystemParamsSettings(params);
}
public String getCertClientFilePath(){
SystemParamsSettings params = getSystemParamsSettings();
return params.getCertClientFilePath();
}
public void setCertificatePassword(String value) {
SystemParamsSettings params = getSystemParamsSettings();
params.setCertificatePassword(value);
saveSystemParamsSettings(params);
}
public String getCertificatePassword(){
SystemParamsSettings params = getSystemParamsSettings();
return params.getCertificatePassword();
}
} }

View File

@ -243,8 +243,10 @@ public class SystemParamsSettings implements Serializable {
private boolean qrPartialRefundEnable = false; private boolean qrPartialRefundEnable = false;
private boolean qrDecimalEnable = false; private boolean qrDecimalEnable = false;
private boolean qrRefundEnable = false; private boolean qrRefundEnable = true;
private String certFilePath = ""; private String certFilePath = "";
private String certClientFilePath = "";
private String certificatePassword = "";
public boolean isQrPartialRefundEnable(){ public boolean isQrPartialRefundEnable(){
return qrPartialRefundEnable; return qrPartialRefundEnable;
@ -980,6 +982,22 @@ public class SystemParamsSettings implements Serializable {
return certFilePath; return certFilePath;
} }
public String getCertClientFilePath() {
return certClientFilePath;
}
public void setCertClientFilePath(String path){
this.certClientFilePath = path;
}
public void setCertificatePassword(String certificatePassword) {
this.certificatePassword = certificatePassword;
}
public String getCertificatePassword() {
return certificatePassword;
}
/* // 流水号起始 /* // 流水号起始
private String serialNum = Configs.getInstance().SERIAL_NUM(); private String serialNum = Configs.getInstance().SERIAL_NUM();
// 批次号起始 // 批次号起始