Skip to content

Commit

Permalink
Merge pull request #571 from gini/BAC-893-Add-data-we-add-to-jpeg-exi…
Browse files Browse the repository at this point in the history
…f-also-to-request-headers

Bac 893 add data we add to jpeg exif also to request headers
  • Loading branch information
danicretu authored Sep 13, 2024
2 parents f7cd080 + 4729aaf commit 645c446
Show file tree
Hide file tree
Showing 11 changed files with 201 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -267,5 +267,7 @@ class TransferSummaryIntegrationTest {
override fun getSource(): Document.Source = Document.Source.newSource("androidTest")

override fun isReviewable(): Boolean = false

override fun generateUploadMetadata(context: Context?): String = ""
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,11 @@ import net.gini.android.bank.sdk.error.AmountParsingException
import net.gini.android.bank.sdk.pay.getBusinessIntent
import net.gini.android.bank.sdk.pay.getRequestId
import net.gini.android.bank.sdk.util.parseAmountToBackendFormat
import net.gini.android.capture.*
import net.gini.android.capture.Amount
import net.gini.android.capture.AsyncCallback
import net.gini.android.capture.Document
import net.gini.android.capture.GiniCapture
import net.gini.android.capture.ImportedFileValidationException
import net.gini.android.capture.onboarding.view.ImageOnboardingIllustrationAdapter
import net.gini.android.capture.onboarding.view.OnboardingIllustrationAdapter
import net.gini.android.capture.requirements.GiniCaptureRequirements
Expand Down Expand Up @@ -61,6 +65,8 @@ object GiniBank {
private var captureConfiguration: CaptureConfiguration? = null
private var giniApi: GiniBankAPI? = null

internal const val USER_COMMENT_GINI_BANK_VERSION = "GiniBankVer"

/**
* Bottom navigation bar adapters. Could be changed to custom ones.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package net.gini.android.bank.sdk.capture

import net.gini.android.bank.sdk.BuildConfig
import net.gini.android.bank.sdk.GiniBank
import net.gini.android.bank.sdk.capture.skonto.SkontoNavigationBarBottomAdapter
import net.gini.android.capture.DocumentImportEnabledFileTypes
import net.gini.android.capture.EntryPoint
Expand Down Expand Up @@ -233,6 +235,7 @@ internal fun GiniCapture.Builder.applyConfiguration(configuration: CaptureConfig
.setBottomNavigationBarEnabled(configuration.bottomNavigationBarEnabled)
.setEntryPoint(configuration.entryPoint)
.setAllowScreenshots(configuration.allowScreenshots)
.addCustomUploadMetadata(GiniBank.USER_COMMENT_GINI_BANK_VERSION, BuildConfig.VERSION_NAME)
.apply {
configuration.eventTracker?.let { setEventTracker(it) }
configuration.errorLoggerListener?.let { setCustomErrorLoggerListener(it) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -262,5 +262,7 @@ class TransferSummaryIntegrationTest {
override fun getSource(): Document.Source = Document.Source.newSource("androidTest")

override fun isReviewable(): Boolean = false

override fun generateUploadMetadata(context: Context?): String = ""
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package net.gini.android.capture.network

import android.content.Context
import android.text.TextUtils
import androidx.annotation.VisibleForTesting
import androidx.annotation.XmlRes
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
Expand Down Expand Up @@ -57,10 +58,14 @@ import net.gini.android.bank.api.models.Configuration as BankConfiguration
* [GiniCapture.Builder.setGiniCaptureNetworkService] when creating a
* [GiniCapture] instance.
*/
class GiniCaptureDefaultNetworkService(
class GiniCaptureDefaultNetworkService

@VisibleForTesting
internal constructor(
internal val giniBankApi: GiniBankAPI,
private val documentMetadata: DocumentMetadata?,
coroutineContext: CoroutineContext = Dispatchers.Main
private val context: Context,
coroutineContext: CoroutineContext = Dispatchers.Main,
) : GiniCaptureNetworkService {

private val coroutineScope = CoroutineScope(coroutineContext)
Expand Down Expand Up @@ -212,12 +217,18 @@ class GiniCaptureDefaultNetworkService(
return@launchCancellable
}

val uploadMetadata = document.generateUploadMetadata(context)

val partialDocumentResource = giniBankApi.documentManager.createPartialDocument(
document = documentData,
contentType = document.mimeType,
filename = null,
documentType = null,
documentMetadata
documentMetadata?.copy()?.apply {
setUploadMetadata(uploadMetadata)
} ?: DocumentMetadata().apply {
setUploadMetadata(uploadMetadata)
}
)

when (partialDocumentResource) {
Expand Down Expand Up @@ -512,7 +523,7 @@ class GiniCaptureDefaultNetworkService(
trustManager?.let { giniApiBuilder.setTrustManager(it) }
giniApiBuilder.setDebuggingEnabled(isDebuggingEnabled)
val giniBankApi = giniApiBuilder.build()
return GiniCaptureDefaultNetworkService(giniBankApi, documentMetadata)
return GiniCaptureDefaultNetworkService(giniBankApi, documentMetadata, mContext)
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package net.gini.android.capture.network

import android.net.Uri
import android.os.Looper
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.google.common.truth.Truth.assertThat
import io.mockk.*
Expand All @@ -13,7 +14,6 @@ import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.Shadows.shadowOf
import java.util.*
import kotlin.collections.LinkedHashMap

/**
* Created by Alpár Szotyori on 25.02.22.
Expand Down Expand Up @@ -56,7 +56,7 @@ class GiniCaptureDefaultNetworkServiceTest {

// Mock DocumentTaskManager returning the mock documents
val documentManager = mockk<BankApiDocumentManager>()
coEvery { documentManager.createPartialDocument(any(), any(), null, null) } returns Resource.Success(partialDocument)
coEvery { documentManager.createPartialDocument(any(), any(), null, null, any()) } returns Resource.Success(partialDocument)
coEvery { documentManager.createCompositeDocument(any<LinkedHashMap<net.gini.android.core.api.models.Document, Int>>(), any()) } returns Resource.Success(compositeDocument)
coEvery { documentManager.pollDocument(any()) } returns Resource.Success(compositeDocument)
coEvery { documentManager.getAllExtractionsWithPolling(any()) } returns Resource.Success(mockk())
Expand All @@ -65,13 +65,14 @@ class GiniCaptureDefaultNetworkServiceTest {
val bankApi = mockk<GiniBankAPI>()
every { bankApi.documentManager } returns documentManager

val networkService = GiniCaptureDefaultNetworkService(bankApi, null)
val networkService = GiniCaptureDefaultNetworkService(bankApi, null, ApplicationProvider.getApplicationContext())

// Mock Gini Capture SDK document
val captureDocument = mockk<Document>()
every { captureDocument.id } returns "id"
every { captureDocument.data } returns byteArrayOf()
every { captureDocument.mimeType } returns "image/jpeg"
every { captureDocument.generateUploadMetadata(ApplicationProvider.getApplicationContext()) } returns ""

// When
networkService.upload(captureDocument, mockk(relaxed = true))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
package net.gini.android.capture;

import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;

import java.util.HashMap;
import java.util.Map;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.util.HashMap;
import java.util.Map;


/**
* This class is the container for transferring documents between the client application and the
Expand Down Expand Up @@ -120,6 +121,12 @@ public interface Document extends Parcelable {
*/
boolean isReviewable();

/**
* Generate metadata to be sent to backend when creating partial document.
*
*/
String generateUploadMetadata(Context context);

/**
* Supported document types.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ public class GiniCapture {
private final EntryPoint entryPoint;
private final boolean allowScreenshots;

private final Map<String, String> mCustomUploadMetadata;


/**
* Retrieve the current instance.
Expand Down Expand Up @@ -345,6 +347,7 @@ private GiniCapture(@NonNull final Builder builder) {
onButtonLoadingIndicatorAdapterInstance = builder.getOnButtonLoadingIndicatorAdapterInstance();
entryPoint = builder.getEntryPoint();
allowScreenshots = builder.getAllowScreenshots();
mCustomUploadMetadata = builder.getCustomUploadMetadata();
}

/**
Expand Down Expand Up @@ -695,6 +698,14 @@ public boolean getAllowScreenshots() {
return allowScreenshots;
}

/**
* Get upload metadata to be added to the HTTP headers
*
* @return the map of custom metadata
*/
@Nullable
public Map<String, String> getCustomUploadMetadata() { return mCustomUploadMetadata; }

public static GiniCaptureFragment createGiniCaptureFragment() {
if (!GiniCapture.hasInstance()) {
throw new IllegalStateException("GiniCapture instance was created. Call GiniCapture.newInstance() before creating the GiniCaptureFragment.");
Expand Down Expand Up @@ -808,6 +819,8 @@ public void onAnalysisScreenEvent(@NotNull final Event<AnalysisScreenEvent> even
private EntryPoint entryPoint = Internal.DEFAULT_ENTRY_POINT;
private boolean allowScreenshots = true;

private Map<String, String> customUploadMetadata;

/**
* Create a new {@link GiniCapture} instance.
*/
Expand Down Expand Up @@ -1344,6 +1357,18 @@ public Builder setAllowScreenshots(boolean allowScreenshots) {
private boolean getAllowScreenshots() {
return allowScreenshots;
}

public Builder addCustomUploadMetadata(String key, String value) {
if (customUploadMetadata == null) {
customUploadMetadata = new HashMap<>();
}
customUploadMetadata.put(key, value);
return this;
}

private Map<String, String> getCustomUploadMetadata() {
return customUploadMetadata;
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,19 @@
import android.net.Uri;
import android.os.Parcel;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import net.gini.android.capture.AsyncCallback;
import net.gini.android.capture.Document;
import net.gini.android.capture.internal.camera.photo.ParcelableMemoryCache;
import net.gini.android.capture.internal.util.DeviceHelper;
import net.gini.android.capture.internal.util.UriReaderAsyncTask;
import net.gini.android.capture.util.IntentHelper;

import java.util.Arrays;
import java.util.UUID;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

/**
* Internal use only.
*
Expand Down Expand Up @@ -219,6 +220,16 @@ public String getParcelableMemoryCacheTag() {
return mParcelableMemoryCacheTag;
}

@Override
public String generateUploadMetadata(Context context) {
return UploadMetadata.INSTANCE
.setSource(mSource.getName())
.setDeviceType(DeviceHelper.getDeviceType(context))
.setDeviceOrientation(DeviceHelper.getDeviceOrientation(context))
.setImportMethod(mImportMethod.name())
.build();
}

@Override
public String toString() {
return "GiniCaptureDocument{"
Expand Down Expand Up @@ -309,6 +320,7 @@ public boolean equals(final Object o) {
if (mImportMethod != that.mImportMethod) {
return false;
}

return mMimeType.equals(that.mMimeType);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package net.gini.android.capture.document

import android.os.Build
import net.gini.android.capture.BuildConfig
import net.gini.android.capture.EntryPoint
import net.gini.android.capture.GiniCapture

internal object UploadMetadata {

private const val USER_COMMENT_PLATFORM = "Platform"
private const val USER_COMMENT_OS_VERSION = "OSVer"
private const val USER_COMMENT_GINI_CAPTURE_VERSION = "GiniCaptureVer"
private const val USER_COMMENT_DEVICE_ORIENTATION = "DeviceOrientation"
private const val USER_COMMENT_DEVICE_TYPE = "DeviceType"
private const val USER_COMMENT_SOURCE = "Source"
private const val USER_COMMENT_IMPORT_METHOD = "ImportMethod"
private const val USER_COMMENT_ENTRY_POINT = "EntryPoint"

private var giniCaptureVersion: String = ""
private var deviceOrientation: String = ""
private var deviceType: String = ""
private var source: String = ""
private var importMethod: String = ""

private fun convertMapToCSV(keyValueMap: Map<String, String>): String {
val csvBuilder = StringBuilder()
var isFirst = true
for ((key, value) in keyValueMap) {
if (!isFirst) {
csvBuilder.append(',')
}
isFirst = false
csvBuilder.append(key)
.append('=')
.append(value)
}
return csvBuilder.toString()
}

fun setDeviceOrientation(deviceOrientation: String): UploadMetadata =
this.also { it.deviceOrientation = deviceOrientation }

fun setDeviceType(deviceType: String): UploadMetadata =
this.also { it.deviceType = deviceType }

fun setSource(source: String): UploadMetadata = this.also { it.source = source }

fun setImportMethod(importMethod: String): UploadMetadata = this.also { it.importMethod = importMethod }

fun build(): String {
val metadataMap = mutableMapOf<String, String>()

metadataMap[USER_COMMENT_PLATFORM] = "Android"
metadataMap[USER_COMMENT_OS_VERSION] = Build.VERSION.RELEASE.toString()
if (giniCaptureVersion.isNotEmpty()) {
metadataMap[USER_COMMENT_GINI_CAPTURE_VERSION] = giniCaptureVersion
}
if (deviceOrientation.isNotEmpty()) {
metadataMap[USER_COMMENT_DEVICE_ORIENTATION] = deviceOrientation
}
if (deviceType.isNotEmpty()) {
metadataMap[USER_COMMENT_DEVICE_TYPE] = deviceType
}
if (source.isNotEmpty()) {
metadataMap[USER_COMMENT_SOURCE] = source
}
if (importMethod.isNotEmpty()) {
metadataMap[USER_COMMENT_IMPORT_METHOD] = importMethod
}
metadataMap[USER_COMMENT_GINI_CAPTURE_VERSION] = BuildConfig.VERSION_NAME.replace(" ", "")

if (GiniCapture.hasInstance()) {
metadataMap[USER_COMMENT_ENTRY_POINT] = entryPointToString(GiniCapture.getInstance().entryPoint)
GiniCapture.getInstance().customUploadMetadata?.forEach {
metadataMap[it.key] = it.value
}
} else {
metadataMap[USER_COMMENT_ENTRY_POINT] = entryPointToString(GiniCapture.Internal.DEFAULT_ENTRY_POINT)
}

return convertMapToCSV(metadataMap)
}

private fun entryPointToString(entryPoint: EntryPoint) = when (entryPoint) {
EntryPoint.FIELD -> "field"
EntryPoint.BUTTON -> "button"
}
}
Loading

0 comments on commit 645c446

Please sign in to comment.