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 e061114..647932a 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 @@ -11,6 +11,7 @@ import androidx.annotation.Nullable; import com.github.gcacace.signaturepad.views.SignaturePad; import com.utsmm.kbz.util.helper.EReceiptHelper; import com.utsmyanmar.baselib.fragment.DataBindingFragment; +import com.utsmyanmar.baselib.network.model.e_receipt.EReceiptCardRequest; import com.utsmyanmar.baselib.util.DataBindingConfig; import com.utsmm.kbz.BR; import com.utsmm.kbz.R; @@ -141,14 +142,13 @@ public class SignatureFragment extends DataBindingFragment { payDetail.setESignBlob(blob); sharedViewModel.payDetail.setValue(payDetail); sharedViewModel.updateESignBlob(payDetail.voucherNo, blob); - sharedViewModel.pushReceipt(EReceiptHelper.buildEReceiptCardReceipt( + EReceiptCardRequest request = EReceiptHelper.buildEReceiptCardReceipt( requireContext(), payDetail, true, BaseErrorCode.getCode(payDetail.getTradeAnswerCode()), - blob) - ); - + null); + sharedViewModel.pushReceiptWithImage(request, blob); } public class ClickEvent { diff --git a/app/src/main/java/com/utsmm/kbz/ui/core_viewmodel/SharedViewModel.java b/app/src/main/java/com/utsmm/kbz/ui/core_viewmodel/SharedViewModel.java index 5509804..b42883c 100644 --- a/app/src/main/java/com/utsmm/kbz/ui/core_viewmodel/SharedViewModel.java +++ b/app/src/main/java/com/utsmm/kbz/ui/core_viewmodel/SharedViewModel.java @@ -12,6 +12,7 @@ import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.ViewModel; import com.google.gson.Gson; +import com.utsmyanmar.baselib.network.model.e_receipt.EReceiptCardRequest; import com.utsmyanmar.baselib.network.model.e_receipt.EReceiptResponse; import com.utsmyanmar.baselib.network.model.sirius.SiriusRequest; import com.utsmyanmar.baselib.network.model.sirius.SiriusResponse; @@ -535,6 +536,38 @@ public class SharedViewModel extends ViewModel { ); } + @SuppressLint("CheckResult") + public void pushReceiptWithImage(EReceiptCardRequest request, byte[] imageBytes) { + Log.d("push receipt", new Gson().toJson(request)); + repository.sendReceiptWithImage(request, imageBytes) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe( + response -> { + Log.d("E-Receipt", "Success =>" + response.getMessage()); + postToastMsg("E-Receipt saved successfully"); + }, + error -> { + if (error instanceof HttpException) { + HttpException httpEx = (HttpException) error; + try { + String errorJson = httpEx.response().errorBody().string(); + Log.e("E-Receipt", "Raw error JSON => " + errorJson); + EReceiptResponse res = new Gson().fromJson(errorJson, EReceiptResponse.class); + Log.e("E-Receipt", "Parsed Error => " + res.getMessage()); + postToastMsg("E-Receipt could not save!"); + } catch (Exception e) { + e.printStackTrace(); + postToastMsg("E-Receipt could not save!"); + } + } else { + Log.e("E-Receipt", "Unexpected error => " + error.getMessage()); + postToastMsg("E-Receipt could not save!"); + } + } + ); + } + public void printTerminalHostConfigs(){ PrintXReceipt.getInstance().printTerminalHostConfig(new PrintXStatus() { 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 3683475..35e7cb8 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 @@ -67,7 +67,9 @@ public class EReceiptHelper { request.setDE14(PrintUtils.getInstance().getFormatExpDate(payDetail.getEXPDate())); request.setDE43(formatDE43(cardHolderName)); request.setDE48(payDetail.getAID()); - request.setDE115(signature != null ? Base64.encodeToString(signature, Base64.NO_WRAP) : ""); + if (signature != null) { + request.setDE115(Base64.encodeToString(signature, Base64.NO_WRAP)); + } return request; } @@ -132,6 +134,6 @@ public class EReceiptHelper { return value.substring(0, 40); } - return String.format("%-40s", value); // right pad with space + return String.format("%-40s", value).trim(); } } diff --git a/app/src/main/res/xml/network_security_config.xml b/app/src/main/res/xml/network_security_config.xml index 1cf6114..c258417 100644 --- a/app/src/main/res/xml/network_security_config.xml +++ b/app/src/main/res/xml/network_security_config.xml @@ -8,6 +8,7 @@ api.kbzpay.com api-uat.kbzpay.com sirius-nest.utsmyanmar.com + 192.168.10.105 diff --git a/baselib/src/main/java/com/utsmyanmar/baselib/db/dao/PayDetailDao.java b/baselib/src/main/java/com/utsmyanmar/baselib/db/dao/PayDetailDao.java index baac73f..b97c196 100644 --- a/baselib/src/main/java/com/utsmyanmar/baselib/db/dao/PayDetailDao.java +++ b/baselib/src/main/java/com/utsmyanmar/baselib/db/dao/PayDetailDao.java @@ -80,7 +80,7 @@ public interface PayDetailDao { // 6 = PRE AUTH CANCEL, 7= PRE_AUTH_COMPLETE , 5 = PRE AUTH // @Query(("SELECT * FROM paydetail WHERE transactionType = 1 AND isCanceled = 1 OR transactionType = 2 AND isCanceled = 0 OR transactionType = 18 AND isCanceled = 0 AND batchNo IN(:batchNo)")) // @Query(("SELECT * FROM paydetail WHERE transactionType = 1 AND isCanceled = 1 OR transactionType = 5 AND isCanceled = 1 OR transactionType = 7 AND isCanceled = 1 OR transactionType = 8 OR transactionType = 6 OR transactionType = 10 OR transactionType = 2 AND isCanceled = 0 OR transactionType = 18 AND isCanceled = 0 OR transactionType = 20 AND isCanceled = 0 OR transactionType = 34 AND isCanceled = 1 AND batchNo IN(:batchNo)")) - @Query(("SELECT * FROM paydetail WHERE transactionType = 1 AND isCanceled = 1 OR transactionType = 5 AND isCanceled = 1 OR transactionType = 7 AND isCanceled = 1 OR transactionType = 8 OR transactionType = 6 OR transactionType = 10 OR transactionType = 2 AND isCanceled = 0 OR transactionType = 18 AND isCanceled = 0 OR transactionType = 20 OR transactionType = 34 AND isCanceled = 1 AND batchNo IN(:batchNo)")) + @Query(("SELECT * FROM paydetail WHERE transactionType = 1 AND isCanceled = 1 OR transactionType = 5 AND isCanceled = 1 OR transactionType = 7 AND isCanceled = 1 OR transactionType = 8 OR transactionType = 6 OR transactionType = 10 OR transactionType = 2 AND isCanceled = 0 OR transactionType = 18 AND isCanceled = 0 OR transactionType = 34 AND isCanceled = 1 AND batchNo IN(:batchNo)")) LiveData> getDeleteTrans(String batchNo); @Query("SELECT * FROM paydetail WHERE transactionType = 5 AND isCanceled = 0") diff --git a/baselib/src/main/java/com/utsmyanmar/baselib/di/NetworkModule.java b/baselib/src/main/java/com/utsmyanmar/baselib/di/NetworkModule.java index b1da0ea..c390606 100644 --- a/baselib/src/main/java/com/utsmyanmar/baselib/di/NetworkModule.java +++ b/baselib/src/main/java/com/utsmyanmar/baselib/di/NetworkModule.java @@ -415,7 +415,9 @@ public Retrofit provideKPayRefundRetrofit(@ApplicationContext Context context) { @Singleton public EReceiptApiService provideEReceiptApiService(){ - HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(); + HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor( + message -> LogUtil.d("HTTP", message) + ); interceptor.setLevel(HttpLoggingInterceptor.Level.BODY); OkHttpClient client = new OkHttpClient.Builder() diff --git a/baselib/src/main/java/com/utsmyanmar/baselib/network/EReceiptApiService.java b/baselib/src/main/java/com/utsmyanmar/baselib/network/EReceiptApiService.java index b85e6c2..899fde4 100644 --- a/baselib/src/main/java/com/utsmyanmar/baselib/network/EReceiptApiService.java +++ b/baselib/src/main/java/com/utsmyanmar/baselib/network/EReceiptApiService.java @@ -1,13 +1,16 @@ package com.utsmyanmar.baselib.network; - -import com.google.gson.JsonElement; import com.utsmyanmar.baselib.network.model.e_receipt.EReceiptResponse; - +import java.util.Map; import io.reactivex.rxjava3.core.Observable; +import okhttp3.MultipartBody; +import okhttp3.RequestBody; import retrofit2.http.Body; import retrofit2.http.Header; +import retrofit2.http.Multipart; import retrofit2.http.POST; +import retrofit2.http.Part; +import retrofit2.http.PartMap; public interface EReceiptApiService { @@ -17,4 +20,13 @@ public interface EReceiptApiService { @Header("x-api-key") String apiKey, @Body Object body ); + + @Multipart + @POST("transaction") + Observable sendReceiptMultipart( + @Header("x-timestamp") String timestamp, + @Header("x-api-key") String apiKey, + @PartMap Map fields, + @Part MultipartBody.Part de115Image + ); } 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 9f0afda..4bb9148 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 @@ -165,6 +165,7 @@ public class EReceiptCardRequest { public void setDE43(String DE43){ this.DE43 = DE43; } + public String getDE48(){ return DE48; } public void setDE48(String DE48){ this.DE48 = DE48; } 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 85ac014..613d569 100644 --- a/baselib/src/main/java/com/utsmyanmar/baselib/repo/Repository.java +++ b/baselib/src/main/java/com/utsmyanmar/baselib/repo/Repository.java @@ -17,6 +17,7 @@ import com.utsmyanmar.baselib.network.KPayApiService; import com.utsmyanmar.baselib.network.KPayRefundApiService; import com.utsmyanmar.baselib.network.SiriusApiService; import com.utsmyanmar.baselib.network.model.DemoQRRequest; +import com.utsmyanmar.baselib.network.model.e_receipt.EReceiptCardRequest; import com.utsmyanmar.baselib.network.model.DemoQRResponse; import com.utsmyanmar.baselib.network.model.DemoQRReturnRequest; import com.utsmyanmar.baselib.network.model.DemoQRReturnResponse; @@ -42,12 +43,17 @@ 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.List; - +import java.util.Map; import javax.inject.Inject; import javax.inject.Provider; +import okhttp3.MediaType; +import okhttp3.MultipartBody; +import okhttp3.RequestBody; + import io.reactivex.rxjava3.core.Completable; import io.reactivex.rxjava3.core.Flowable; import io.reactivex.rxjava3.core.Maybe; @@ -128,6 +134,58 @@ public class Repository { return eReceiptApiService.sendReceipt(timestamp, signature, body); } + public Observable sendReceiptWithImage(EReceiptCardRequest request, byte[] imageBytes) { + String apiSecret = BuildConfig.ERECEIPT_SECRET; + String timestamp = String.valueOf(System.currentTimeMillis()); + request.setDE115(null); + String bodyString = new Gson().toJson(request); + String dataToHash = bodyString + apiSecret + timestamp; + LogUtil.d("HTTP", dataToHash); + String apiKey = EReceiptHelper.sha256(dataToHash); + + Map fields = buildFormFields(request); + MultipartBody.Part imagePart = null; + if (imageBytes != null) { + RequestBody imageBody = RequestBody.create(MediaType.parse("image/png"), imageBytes); + imagePart = MultipartBody.Part.createFormData("DE115", "signature.png", imageBody); + } + + return eReceiptApiService.sendReceiptMultipart(timestamp, apiKey, fields, imagePart); + } + + private Map buildFormFields(EReceiptCardRequest request) { + Map map = new HashMap<>(); + putField(map, "DE2", request.getDE2()); + putField(map, "DE3", request.getDE3()); + putField(map, "DE4", request.getDE4()); + putField(map, "DE7", request.getDE7()); + putField(map, "DE11", request.getDE11()); + putField(map, "DE14", request.getDE14()); + putField(map, "DE22", request.getDE22()); + putField(map, "DE37", request.getDE37()); + putField(map, "DE38", request.getDE38()); + putField(map, "DE39", request.getDE39()); + putField(map, "DE41", request.getDE41()); + putField(map, "DE42", request.getDE42()); + putField(map, "DE43", request.getDE43()); + putField(map, "DE48", request.getDE48()); + putField(map, "DE49", request.getDE49()); + putField(map, "DE55", request.getDE55()); + putField(map, "appId", request.getAppId()); + putField(map, "batchNumber", request.getBatchNumber()); + putField(map, "cardLabel", request.getCardLabel()); + putField(map, "description", request.getDescription()); + putField(map, "invoiceNumber", request.getInvoiceNumber()); + putField(map, "serial", request.getSerial()); + return map; + } + + private void putField(Map map, String key, String value) { + if (value != null && !value.isEmpty()) { + map.put(key, RequestBody.create(MediaType.parse("text/plain"), value)); + } + } + public void insertPayDetail(PayDetail payDetail){ payDetailDao.insert(payDetail);} public Completable insertPay(PayDetail payDetail) { return payDetailDao.insertPay(payDetail); }