signature send to backend

This commit is contained in:
moon 2026-07-02 13:39:50 +06:30
parent ed304217ec
commit b8bfd5d1a7
7 changed files with 151 additions and 70 deletions

View File

@ -162,6 +162,7 @@ public class MainActivity extends AppCompatActivity implements
// SystemParamsOperation.getInstance().setEReceiptAddress("https://api-tms-uat.kbzbank.com:8443/receipt"); // SystemParamsOperation.getInstance().setEReceiptAddress("https://api-tms-uat.kbzbank.com:8443/receipt");
SystemParamsOperation.getInstance().setTmsAddress("https://sirius-nest.utsmyanmar.com/api/v1"); SystemParamsOperation.getInstance().setTmsAddress("https://sirius-nest.utsmyanmar.com/api/v1");
SystemParamsOperation.getInstance().setEReceiptAddress("https://receipt-nest.utsmyanmar.com"); SystemParamsOperation.getInstance().setEReceiptAddress("https://receipt-nest.utsmyanmar.com");
// SystemParamsOperation.getInstance().setEReceiptAddress("https://receipt-nest.utsmyanmar.com");
PinPad pinPad = MyApplication.getInstance().deviceEngine.getPinPad(); PinPad pinPad = MyApplication.getInstance().deviceEngine.getPinPad();
byte[] encryptedPIK = SystemParamsOperation.getInstance().getPIK(); byte[] encryptedPIK = SystemParamsOperation.getInstance().getPIK();

View File

@ -345,14 +345,14 @@ public class ProcessingFragment extends DataBindingFragment {
handleAfterTransaction(); handleAfterTransaction();
break; break;
case SUCCESS: case SUCCESS:
sharedViewModel.pushReceipt(buildEReceiptCardReceipt(payDetail, true, BaseErrorCode.getCode(payDetail.getTradeAnswerCode()))); // sharedViewModel.pushReceipt(buildEReceiptCardReceipt(payDetail, true, BaseErrorCode.getCode(payDetail.getTradeAnswerCode())));
handleAfterTransaction(); // handleAfterTransaction();
// if(requiresSignature()){ if(requiresSignature()){
// handleAfterTransaction(); handleAfterTransaction();
// }else{ }else{
// sharedViewModel.pushReceipt(buildEReceiptCardReceipt(payDetail, true, BaseErrorCode.getCode(payDetail.getTradeAnswerCode()))); sharedViewModel.pushReceipt(buildEReceiptCardReceipt(payDetail, true, BaseErrorCode.getCode(payDetail.getTradeAnswerCode())));
// handleAfterTransaction(); handleAfterTransaction();
// } }
break; break;
case OFFLINE_SUCCESS: case OFFLINE_SUCCESS:
if(SystemParamsOperation.getInstance().getDemoStatus()) { if(SystemParamsOperation.getInstance().getDemoStatus()) {

View File

@ -142,13 +142,13 @@ public class SignatureFragment extends DataBindingFragment {
payDetail.setESignBlob(blob); payDetail.setESignBlob(blob);
sharedViewModel.payDetail.setValue(payDetail); sharedViewModel.payDetail.setValue(payDetail);
sharedViewModel.updateESignBlob(payDetail.voucherNo, blob); sharedViewModel.updateESignBlob(payDetail.voucherNo, blob);
// EReceiptCardRequest request = EReceiptHelper.buildEReceiptCardReceipt( EReceiptCardRequest request = EReceiptHelper.buildEReceiptCardReceipt(
// requireContext(), requireContext(),
// payDetail, payDetail,
// true, true,
// BaseErrorCode.getCode(payDetail.getTradeAnswerCode()), BaseErrorCode.getCode(payDetail.getTradeAnswerCode()),
// null); null);
// sharedViewModel.pushReceiptWithImage(request, blob); sharedViewModel.pushReceiptWithImage(request, blob);
} }
public class ClickEvent { public class ClickEvent {

View File

@ -7,6 +7,7 @@ import android.util.Log;
import android.widget.ListView; import android.widget.ListView;
import dagger.hilt.android.lifecycle.HiltViewModel; import dagger.hilt.android.lifecycle.HiltViewModel;
import androidx.lifecycle.LiveData; import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel; import androidx.lifecycle.ViewModel;
@ -196,12 +197,13 @@ public class SharedViewModel extends ViewModel {
} }
public void setEmvTrans(boolean status) { public void setEmvTrans(boolean status) {
isEmv.setValue(status); isEmv.setValue(status);
} }
public SingleLiveEvent<Boolean> isEmvTrans() { return isEmv;} public SingleLiveEvent<Boolean> isEmvTrans() {
return isEmv;
}
private PayDetail getPayDetail() { private PayDetail getPayDetail() {
return mPayDetail; return mPayDetail;
@ -231,8 +233,14 @@ public class SharedViewModel extends ViewModel {
return amount; return amount;
} }
public void setPrintReceiptMsg(String msg) { this.printReceiptMsg.setValue(msg);} public void setPrintReceiptMsg(String msg) {
public void postPrintReceiptMsg(String msg) { this.printReceiptMsg.postValue(msg);} this.printReceiptMsg.setValue(msg);
}
public void postPrintReceiptMsg(String msg) {
this.printReceiptMsg.postValue(msg);
}
public void setPrintStatus(PrintStatus printStatus) { public void setPrintStatus(PrintStatus printStatus) {
// this.printStatus.postValue(printStatus); // this.printStatus.postValue(printStatus);
if (Looper.myLooper() == Looper.getMainLooper()) { if (Looper.myLooper() == Looper.getMainLooper()) {
@ -242,36 +250,67 @@ public class SharedViewModel extends ViewModel {
} }
} }
public void postPrintStatus(PrintStatus printStatus) { this.printStatus.postValue(printStatus); }
public SingleLiveEvent<PrintStatus> getPrintStatus() { return this.printStatus; } public void postPrintStatus(PrintStatus printStatus) {
this.printStatus.postValue(printStatus);
}
public void setIsFallback(boolean status) { isFallback.setValue(status);} public SingleLiveEvent<PrintStatus> getPrintStatus() {
return this.printStatus;
}
public SingleLiveEvent<Boolean> getIsFallback() { return isFallback;} public void setIsFallback(boolean status) {
isFallback.setValue(status);
}
public void setIsCardAppBlock(boolean status) { isCardAppBlock.setValue(status);} public SingleLiveEvent<Boolean> getIsFallback() {
return isFallback;
}
public SingleLiveEvent<Boolean> getIsCardAppBlock() {return isCardAppBlock;} public void setIsCardAppBlock(boolean status) {
isCardAppBlock.setValue(status);
}
public void setIsSeePhone(boolean status) { isSeePhone.setValue(status);} public SingleLiveEvent<Boolean> getIsCardAppBlock() {
return isCardAppBlock;
}
public SingleLiveEvent<Boolean> getIsSeePhone() { return isSeePhone;} public void setIsSeePhone(boolean status) {
isSeePhone.setValue(status);
}
public void setIsContactlessRestricted(boolean status) { isContactlessRestricted.setValue(status);} public SingleLiveEvent<Boolean> getIsSeePhone() {
return isSeePhone;
}
public SingleLiveEvent<Boolean> getIsContactlessRestricted() {return isContactlessRestricted;} public void setIsContactlessRestricted(boolean status) {
isContactlessRestricted.setValue(status);
}
public void setCardDataExist(boolean exist) { _isCardDataExist.setValue(exist);} public SingleLiveEvent<Boolean> getIsContactlessRestricted() {
return isContactlessRestricted;
}
public SingleLiveEvent<Boolean> getCardDataExist() { return _isCardDataExist; } public void setCardDataExist(boolean exist) {
_isCardDataExist.setValue(exist);
}
public void setAmountExist(boolean exist) { _isAmountExist.setValue(exist);} public SingleLiveEvent<Boolean> getCardDataExist() {
return _isCardDataExist;
}
public SingleLiveEvent<Boolean> getAmountExist() { return _isAmountExist; } public void setAmountExist(boolean exist) {
_isAmountExist.setValue(exist);
}
public SingleLiveEvent<Boolean> getAmountExist() {
return _isAmountExist;
}
public MutableLiveData<Boolean> getManualEntryStatus() { return _manualEntryStatus;} public MutableLiveData<Boolean> getManualEntryStatus() {
return _manualEntryStatus;
}
public void setManualEntryStatus(boolean status) { public void setManualEntryStatus(boolean status) {
_manualEntryStatus.setValue(status); _manualEntryStatus.setValue(status);
@ -289,11 +328,18 @@ public class SharedViewModel extends ViewModel {
return _successFragmentMsg; return _successFragmentMsg;
} }
public void set_currencyText(String msg) { this._currencyText.setValue(msg);} public void set_currencyText(String msg) {
this._currencyText.setValue(msg);
}
public SingleLiveEvent<String> get_currencyText() { return _currencyText; } public SingleLiveEvent<String> get_currencyText() {
return _currencyText;
}
public void set_successFragmentMsg(String msg) {
this._successFragmentMsg.setValue(msg);
}
public void set_successFragmentMsg(String msg) { this._successFragmentMsg.setValue(msg);}
public SingleLiveEvent<TransMenu> getTransMenu() { public SingleLiveEvent<TransMenu> getTransMenu() {
return _transMenu; return _transMenu;
} }
@ -331,10 +377,10 @@ public class SharedViewModel extends ViewModel {
@Override @Override
public void onSuccess() { public void onSuccess() {
if(isMerchantCopy) { if (isMerchantCopy) {
if(!SystemParamsOperation.getInstance().getDemoStatus()) { if (!SystemParamsOperation.getInstance().getDemoStatus()) {
if(SystemParamsOperation.getInstance().getPrintISOStatus()) { if (SystemParamsOperation.getInstance().getPrintISOStatus()) {
PrintXReceipt.getInstance().printSmileISoReceipt(payDetail.getValue()); PrintXReceipt.getInstance().printSmileISoReceipt(payDetail.getValue());
} }
} }
@ -348,7 +394,7 @@ public class SharedViewModel extends ViewModel {
@Override @Override
public void onFailure() { public void onFailure() {
LogUtil.d(TAG,"Print Status Result Failure!"); LogUtil.d(TAG, "Print Status Result Failure!");
printXStatus.postValue(PrintStatus.EMPTY_PAPER_ROLL); printXStatus.postValue(PrintStatus.EMPTY_PAPER_ROLL);
printReceiptButtons.postValue(0); printReceiptButtons.postValue(0);
} }
@ -356,36 +402,34 @@ public class SharedViewModel extends ViewModel {
} }
public void startPrintReceipt(boolean isFirstPrint) { public void startPrintReceipt(boolean isFirstPrint) {
/* /*
* First Print is Merchant Copy.. * First Print is Merchant Copy..
* */ * */
if(payDetail.getValue() != null) { if (payDetail.getValue() != null) {
setPayDetail(payDetail.getValue()); setPayDetail(payDetail.getValue());
} }
LogUtil.d(TAG,"PayDetail trade Answer Code :"+getPayDetail().getTradeAnswerCode()); LogUtil.d(TAG, "PayDetail trade Answer Code :" + getPayDetail().getTradeAnswerCode());
LogUtil.d(TAG,"PayDetail trade Answer Code :"+payDetail.getValue().getTradeAnswerCode()); LogUtil.d(TAG, "PayDetail trade Answer Code :" + payDetail.getValue().getTradeAnswerCode());
PrintXReceipt.getInstance().printSmileReceipt(getPayDetail(), isFirstPrint, new PrintXStatus() { PrintXReceipt.getInstance().printSmileReceipt(getPayDetail(), isFirstPrint, new PrintXStatus() {
@Override @Override
public void onSuccess() { public void onSuccess() {
if(isFirstPrint) { if (isFirstPrint) {
if(!SystemParamsOperation.getInstance().getDemoStatus()) { if (!SystemParamsOperation.getInstance().getDemoStatus()) {
if(SystemParamsOperation.getInstance().getPrintISOStatus()) { if (SystemParamsOperation.getInstance().getPrintISOStatus()) {
PrintXReceipt.getInstance().printSmileISoReceipt(getPayDetail()); PrintXReceipt.getInstance().printSmileISoReceipt(getPayDetail());
} }
} }
postPrintStatus(PrintStatus.FIRST_PRINT_DONE); postPrintStatus(PrintStatus.FIRST_PRINT_DONE);
if(isEcr.getValue() != null && if (isEcr.getValue() != null &&
isEcr.getValue() && isEcr.getValue() &&
SystemParamsOperation.getInstance().isAutoPrintCustomerCopy()) { SystemParamsOperation.getInstance().isAutoPrintCustomerCopy()) {
printReceiptButtons.postValue(8); printReceiptButtons.postValue(8);
@ -400,7 +444,7 @@ public class SharedViewModel extends ViewModel {
@Override @Override
public void onFailure() { public void onFailure() {
LogUtil.d(TAG,"Print Status Result Failure!"); LogUtil.d(TAG, "Print Status Result Failure!");
if (isFirstPrint) { if (isFirstPrint) {
setPrintStatus(PrintStatus.EMPTY_PAPER_ROLL_FIRST); setPrintStatus(PrintStatus.EMPTY_PAPER_ROLL_FIRST);
} else { } else {
@ -412,10 +456,9 @@ public class SharedViewModel extends ViewModel {
} }
@SuppressWarnings("ConstantConditions") @SuppressWarnings("ConstantConditions")
public void startPrintProcess() { public void startPrintProcess() {
LogUtil.d(TAG,"Print status :"+getPrintStatus().getValue()); LogUtil.d(TAG, "Print status :" + getPrintStatus().getValue());
switch (getPrintStatus().getValue()) { switch (getPrintStatus().getValue()) {
case FIRST_PRINT: case FIRST_PRINT:
@ -439,8 +482,8 @@ public class SharedViewModel extends ViewModel {
} }
public void startPrintSettlement(PrintXStatus printXStatus) { public void startPrintSettlement(PrintXStatus printXStatus) {
if(payDetail.getValue() == null) return; if (payDetail.getValue() == null) return;
if(payDetail.getValue().getTransactionType() == TransactionsType.SETTLEMENT.value) { if (payDetail.getValue().getTransactionType() == TransactionsType.SETTLEMENT.value) {
startPrintProcessSettlement(printXStatus); startPrintProcessSettlement(printXStatus);
} else { } else {
startPrintProcessQRSettlement(printXStatus); startPrintProcessQRSettlement(printXStatus);
@ -449,16 +492,15 @@ public class SharedViewModel extends ViewModel {
public void startPrintProcessSettlement(PrintXStatus printXStatus) { public void startPrintProcessSettlement(PrintXStatus printXStatus) {
if(payDetail.getValue() == null) return; if (payDetail.getValue() == null) return;
PrintXReceipt.getInstance().printSmileSettlementReport(payDetail.getValue(),printXStatus); PrintXReceipt.getInstance().printSmileSettlementReport(payDetail.getValue(), printXStatus);
} }
private void startPrintProcessQRSettlement(PrintXStatus printXStatus) { private void startPrintProcessQRSettlement(PrintXStatus printXStatus) {
if (payDetail.getValue() == null && payDetails.getValue() == null) return;
if(payDetail.getValue() == null && payDetails.getValue() == null) return;
PrintXReceipt.getInstance().printQRSettlementReport(payDetail.getValue(), QRSettleData.convertFromPayDetail(payDetails.getValue()), printXStatus); PrintXReceipt.getInstance().printQRSettlementReport(payDetail.getValue(), QRSettleData.convertFromPayDetail(payDetails.getValue()), printXStatus);
} }
@ -469,7 +511,6 @@ public class SharedViewModel extends ViewModel {
} }
public LiveData<PayDetail> getReversalTransaction(String voucherNo) { public LiveData<PayDetail> getReversalTransaction(String voucherNo) {
return repository.getReversalTransaction(voucherNo); return repository.getReversalTransaction(voucherNo);
} }
@ -482,7 +523,7 @@ public class SharedViewModel extends ViewModel {
return repository.getAllReversalTransactions(); return repository.getAllReversalTransactions();
} }
public void updatePayDetail(PayDetail payDetail){ public void updatePayDetail(PayDetail payDetail) {
repository.updatePayDetail(payDetail); repository.updatePayDetail(payDetail);
} }
@ -490,10 +531,12 @@ public class SharedViewModel extends ViewModel {
repository.updateESignBlob(voucherNo, blob); repository.updateESignBlob(voucherNo, blob);
} }
public void insertPayDetail(PayDetail payDetail) { repository.insertPayDetail(payDetail); } public void insertPayDetail(PayDetail payDetail) {
repository.insertPayDetail(payDetail);
}
public void enableCardStatusIcon(boolean tapCard,boolean tapDevice,boolean insertCard, boolean swipeCard) { public void enableCardStatusIcon(boolean tapCard, boolean tapDevice, boolean insertCard, boolean swipeCard) {
tapCardStatus.setValue(tapCard ? 1 : 0); tapCardStatus.setValue(tapCard ? 1 : 0);
tapDeviceStatus.setValue(tapDevice ? 1 : 0); tapDeviceStatus.setValue(tapDevice ? 1 : 0);
insertCardStatus.setValue(insertCard ? 1 : 0); insertCardStatus.setValue(insertCard ? 1 : 0);
@ -502,14 +545,14 @@ public class SharedViewModel extends ViewModel {
@SuppressLint("CheckResult") @SuppressLint("CheckResult")
public void pushReceipt(Object body){ public void pushReceipt(Object body) {
Log.d("push receipt", new Gson().toJson(body)); Log.d("push receipt", new Gson().toJson(body));
repository.sendReceipt(body) repository.sendReceipt(body)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe( .subscribe(
response -> { response -> {
Log.d("E-Receipt", "Success =>"+ response.getMessage()); Log.d("E-Receipt", "Success =>" + response.getMessage());
postToastMsg("E-Receipt saved successfully"); postToastMsg("E-Receipt saved successfully");
}, },
error -> { error -> {
@ -569,7 +612,7 @@ public class SharedViewModel extends ViewModel {
} }
public void printTerminalHostConfigs(){ public void printTerminalHostConfigs() {
PrintXReceipt.getInstance().printTerminalHostConfig(new PrintXStatus() { PrintXReceipt.getInstance().printTerminalHostConfig(new PrintXStatus() {
@Override @Override
public void onSuccess() { public void onSuccess() {

View File

@ -9,6 +9,7 @@
<domain includeSubdomains="true">api-uat.kbzpay.com</domain> <domain includeSubdomains="true">api-uat.kbzpay.com</domain>
<domain includeSubdomains="true">sirius-nest.utsmyanmar.com</domain> <domain includeSubdomains="true">sirius-nest.utsmyanmar.com</domain>
<domain includeSubdomains="true">192.168.10.105</domain> <domain includeSubdomains="true">192.168.10.105</domain>
<domain includeSubdomains="true">192.168.10.104</domain>
</domain-config> </domain-config>
<domain-config cleartextTrafficPermitted="true"> <domain-config cleartextTrafficPermitted="true">

View File

@ -44,8 +44,10 @@ import com.utsmyanmar.paylibs.model.PayDetail;
import com.utsmyanmar.paylibs.utils.LogUtil; import com.utsmyanmar.paylibs.utils.LogUtil;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.TreeMap;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Provider; import javax.inject.Provider;
@ -137,10 +139,9 @@ public class Repository {
public Observable<EReceiptResponse> sendReceiptWithImage(EReceiptCardRequest request, byte[] imageBytes) { public Observable<EReceiptResponse> sendReceiptWithImage(EReceiptCardRequest request, byte[] imageBytes) {
String apiSecret = BuildConfig.ERECEIPT_SECRET; String apiSecret = BuildConfig.ERECEIPT_SECRET;
String timestamp = String.valueOf(System.currentTimeMillis()); String timestamp = String.valueOf(System.currentTimeMillis());
request.setDE115(null); String bodyString = buildMultipartSignaturePayload(request);
String bodyString = new Gson().toJson(request);
String dataToHash = bodyString + apiSecret + timestamp; String dataToHash = bodyString + apiSecret + timestamp;
LogUtil.d("HTTP", dataToHash); // LogUtil.d("HTTP", dataToHash);
String apiKey = EReceiptHelper.sha256(dataToHash); String apiKey = EReceiptHelper.sha256(dataToHash);
Map<String, RequestBody> fields = buildFormFields(request); Map<String, RequestBody> fields = buildFormFields(request);
@ -153,6 +154,40 @@ public class Repository {
return eReceiptApiService.sendReceiptMultipart(timestamp, apiKey, fields, imagePart); return eReceiptApiService.sendReceiptMultipart(timestamp, apiKey, fields, imagePart);
} }
private String buildMultipartSignaturePayload(EReceiptCardRequest request) {
Map<String, String> flatBody = new LinkedHashMap<>();
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, "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());
return new Gson().toJson(new TreeMap<>(flatBody));
}
private void putIfNotEmpty(Map<String, String> map, String key, String value) {
if (value != null && !value.trim().isEmpty()) {
map.put(key, value);
}
}
private Map<String, RequestBody> buildFormFields(EReceiptCardRequest request) { private Map<String, RequestBody> buildFormFields(EReceiptCardRequest request) {
Map<String, RequestBody> map = new HashMap<>(); Map<String, RequestBody> map = new HashMap<>();
putField(map, "DE2", request.getDE2()); putField(map, "DE2", request.getDE2());

View File

@ -46,6 +46,7 @@ public class SystemParamsSettings implements Serializable {
// private String ereceiptAddress = "https://api-tms-uat.kbzbank.com:8443/receipt"; // private String ereceiptAddress = "https://api-tms-uat.kbzbank.com:8443/receipt";
private String tmsAddress = "https://sirius-nest.utsmyanmar.com/api/v1"; private String tmsAddress = "https://sirius-nest.utsmyanmar.com/api/v1";
private String ereceiptAddress = "https://receipt-nest.utsmyanmar.com"; private String ereceiptAddress = "https://receipt-nest.utsmyanmar.com";
// private String ereceiptAddress = "http://192.168.10.104:3003";
private String binValues = ""; private String binValues = "";
private String restrictedBinValues = ""; private String restrictedBinValues = "";