Skip to content

Commit

Permalink
Merge pull request #53 from verygoodsecurity/stage
Browse files Browse the repository at this point in the history
Release VGSCollect v1.3.1 Bouncer-adapter 1.0.1
  • Loading branch information
Dmytro Kos authored Nov 30, 2020
2 parents 75dac83 + 2874f46 commit 201f5a9
Show file tree
Hide file tree
Showing 84 changed files with 2,148 additions and 1,217 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/local.properties
.DS_Store
/build
/docs

.gradle
.idea
Expand Down
5 changes: 4 additions & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ android {
buildToolsVersion "29.0.3"
defaultConfig {
applicationId "com.verygoodsecurity.demoapp"
minSdkVersion 21
minSdkVersion 19
targetSdkVersion 30
versionCode 1
versionName "1.0"
Expand Down Expand Up @@ -76,6 +76,9 @@ dependencies {

implementation project(":vgscollect")
implementation project(":vgscollect-cardio")
// implementation project(":vgscollect-bouncer")

implementation 'com.google.android.gms:play-services-auth:19.0.0'

implementation 'androidx.core:core-ktx:1.3.1'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ package com.verygoodsecurity.demoapp
import android.app.Application
import android.os.StrictMode
import android.view.View
import com.google.android.gms.security.ProviderInstaller

class DemoApplication: Application() {
val leakedViews = mutableListOf<View>()

override fun onCreate() {
super.onCreate()
ProviderInstaller.installIfNeeded(getApplicationContext());
enabledStrictMode()
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package com.verygoodsecurity.demoapp.activity_case

import android.content.Intent
import android.graphics.Color
import android.graphics.Rect
import android.graphics.drawable.Drawable
import android.os.Bundle
import android.util.Log
import android.view.*
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import com.verygoodsecurity.api.cardio.ScanActivity
Expand All @@ -28,7 +30,6 @@ import com.verygoodsecurity.vgscollect.view.card.icon.CardIconAdapter
import com.verygoodsecurity.vgscollect.view.card.validation.payment.ChecksumAlgorithm
import com.verygoodsecurity.vgscollect.view.card.validation.rules.PaymentCardNumberRule
import com.verygoodsecurity.vgscollect.view.card.validation.rules.PersonNameRule
import com.verygoodsecurity.vgscollect.view.date.DatePickerMode
import kotlinx.android.synthetic.main.activity_collect_demo.*

class VGSCollectActivity: AppCompatActivity(), VgsCollectResponseListener, View.OnClickListener {
Expand Down Expand Up @@ -62,14 +63,14 @@ class VGSCollectActivity: AppCompatActivity(), VgsCollectResponseListener, View.

val staticData = mutableMapOf<String, String>()
staticData["static_data"] = "static custom data"
// vgsForm.setCustomData(staticData)
vgsForm.setCustomData(staticData)
}

private fun setupCardExpDateField() {
vgsForm.bindView(cardExpDateField)
cardExpDateField?.setOnFieldStateChangeListener(object : OnFieldStateChangeListener {
override fun onStateChange(state: FieldState) {
if(!state.isEmpty && !state.isValid && !state.hasFocus) {
if (!state.isEmpty && !state.isValid && !state.hasFocus) {
cardExpDateFieldLay?.setError("fill it please")
} else {
cardExpDateFieldLay?.setError(null)
Expand All @@ -90,7 +91,7 @@ class VGSCollectActivity: AppCompatActivity(), VgsCollectResponseListener, View.
vgsForm.bindView(cardHolderField)
cardHolderField?.setOnFieldStateChangeListener(object : OnFieldStateChangeListener {
override fun onStateChange(state: FieldState) {
if(!state.isEmpty && !state.isValid && !state.hasFocus) {
if (!state.isEmpty && !state.isValid && !state.hasFocus) {
cardHolderFieldLay?.setError("fill it please")
} else {
cardHolderFieldLay?.setError(null)
Expand All @@ -103,7 +104,7 @@ class VGSCollectActivity: AppCompatActivity(), VgsCollectResponseListener, View.
vgsForm.bindView(cardCVCField)
cardCVCField?.setOnFieldStateChangeListener(object : OnFieldStateChangeListener {
override fun onStateChange(state: FieldState) {
if(!state.isEmpty && !state.isValid && !state.hasFocus) {
if (!state.isEmpty && !state.isValid && !state.hasFocus) {
cardCVCFieldLay?.setError("fill it please")
} else {
cardCVCFieldLay?.setError(null)
Expand Down Expand Up @@ -166,7 +167,7 @@ class VGSCollectActivity: AppCompatActivity(), VgsCollectResponseListener, View.

cardNumberField.setCardIconAdapter(object : CardIconAdapter(this) {
override fun getIcon(cardType: CardType, name: String?, resId: Int, r: Rect): Drawable {
return if(cardType == CardType.VISA) {
return if (cardType == CardType.VISA) {
getDrawable(R.drawable.ic_visa_light)
} else {
super.getIcon(cardType, name, resId, r)
Expand All @@ -181,7 +182,7 @@ class VGSCollectActivity: AppCompatActivity(), VgsCollectResponseListener, View.
bin: String,
mask: String
): String {
return when(cardType) {
return when (cardType) {
CardType.UNKNOWN -> {
if (bin == "7771") {
"# # # #"
Expand Down Expand Up @@ -212,12 +213,20 @@ class VGSCollectActivity: AppCompatActivity(), VgsCollectResponseListener, View.
val bndl = intent?.extras

vault_id = bndl?.getString(StartActivity.VAULT_ID, "")?:""
path = bndl?.getString(StartActivity.PATH,"/")?:""
path = bndl?.getString(StartActivity.PATH, "/")?:""

val envId = bndl?.getInt(StartActivity.ENVIROMENT, 0)?:0
env = Environment.values()[envId]

vgsForm = VGSCollect(this, vault_id, env)
vgsForm = VGSCollect.Builder(this, vault_id)
.setEnvironment(env)
.setHostname("collect-android-testing.verygoodsecurity.io/test")
.create()

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
val cacheSize = 10 * 1024 * 1024 // 10MB
vgsForm.getFileProvider().resize(cacheSize)
}
}

override fun onCreateOptionsMenu(menu: Menu): Boolean {
Expand All @@ -236,24 +245,18 @@ class VGSCollectActivity: AppCompatActivity(), VgsCollectResponseListener, View.
}

private fun scanCard() {
val bndl = with(Bundle()) {
val scanSettings = hashMapOf<String?, Int>().apply {
this[cardNumberField?.getFieldName()] = ScanActivity.CARD_NUMBER
this[cardCVCField?.getFieldName()] = ScanActivity.CARD_CVC
this[cardHolderField?.getFieldName()] = ScanActivity.CARD_HOLDER
this[cardExpDateField?.getFieldName()] = ScanActivity.CARD_EXP_DATE
}
putSerializable(ScanActivity.SCAN_CONFIGURATION, scanSettings)
putInt(ScanActivity.EXTRA_GUIDE_COLOR, Color.WHITE)
putBoolean(ScanActivity.EXTRA_REQUIRE_POSTAL_CODE, true)
putBoolean(ScanActivity.EXTRA_SUPPRESS_MANUAL_ENTRY, false)
putBoolean(ScanActivity.EXTRA_SUPPRESS_CONFIRMATION, false)
putString(ScanActivity.EXTRA_LANGUAGE_OR_LOCALE, "en")
putString(ScanActivity.EXTRA_SCAN_INSTRUCTIONS, "Scanning payment card")
this
val intent = Intent(this, ScanActivity::class.java)

val scanSettings = hashMapOf<String?, Int>().apply {
this[cardNumberField?.getFieldName()] = ScanActivity.CARD_NUMBER
this[cardCVCField?.getFieldName()] = ScanActivity.CARD_CVC
this[cardHolderField?.getFieldName()] = ScanActivity.CARD_HOLDER
this[cardExpDateField?.getFieldName()] = ScanActivity.CARD_EXP_DATE
}

ScanActivity.scan(this, USER_SCAN_REQUEST_CODE, bndl)
intent.putExtra(ScanActivity.SCAN_CONFIGURATION, scanSettings)

startActivityForResult(intent, USER_SCAN_REQUEST_CODE)
}

private fun getOnFieldStateChangeListener(): OnFieldStateChangeListener {
Expand Down Expand Up @@ -287,6 +290,11 @@ class VGSCollectActivity: AppCompatActivity(), VgsCollectResponseListener, View.
}

override fun onDestroy() {
vgsForm.unbindView(cardNumberField)
vgsForm.unbindView(cardCVCField)
vgsForm.unbindView(cardExpDateField)
vgsForm.unbindView(cardHolderField)

vgsForm.onDestroy()
super.onDestroy()
}
Expand All @@ -310,12 +318,12 @@ class VGSCollectActivity: AppCompatActivity(), VgsCollectResponseListener, View.
setStateLoading(false)

when (response) {
is VGSResponse.SuccessResponse -> responseContainerView.text = response.toString()
is VGSResponse.SuccessResponse -> responseContainerView.text = "Code: ${response.successCode}"
is VGSResponse.ErrorResponse -> responseContainerView.text = response.toString()
}
}

private fun setStateLoading(state:Boolean) {
private fun setStateLoading(state: Boolean) {
if(state) {
progressBar?.visibility = View.VISIBLE
submitBtn?.isEnabled = false
Expand All @@ -327,16 +335,16 @@ class VGSCollectActivity: AppCompatActivity(), VgsCollectResponseListener, View.
}
}

private fun setEnabledResponseHeader(isEnabled:Boolean) {
private fun setEnabledResponseHeader(isEnabled: Boolean) {
if(isEnabled) {
attachBtn.setTextColor(ContextCompat.getColor(this,
R.color.state_active
))
attachBtn.setTextColor(
ContextCompat.getColor(this, R.color.state_active)
)
} else {
responseContainerView.text = ""
attachBtn.setTextColor(ContextCompat.getColor(this,
R.color.state_unactive
))
attachBtn.setTextColor(
ContextCompat.getColor(this, R.color.state_unactive)
)
}
}

Expand All @@ -360,8 +368,8 @@ class VGSCollectActivity: AppCompatActivity(), VgsCollectResponseListener, View.
val request: VGSRequest = VGSRequest.VGSRequestBuilder()
.setMethod(HTTPMethod.POST)
.setPath(path)
// .setCustomHeader(headers)
// .setCustomData(customData)
.setCustomHeader(headers)
.setCustomData(customData)
.build()

vgsForm.asyncSubmit(request)
Expand Down
6 changes: 5 additions & 1 deletion app/src/main/res/layout/activity_collect_demo.xml
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,9 @@
android:id="@+id/cardNumberField"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:fieldName="card_data.cardNumber"
app:fieldName="cardNumber"
style="@style/AppTheme.PaymentField"
app:text="4111-1111-1111-1111"
app:numberDivider="-"
app:validationRule="acceptUnknown"
app:fontFamily="@font/robotomono_light"
Expand Down Expand Up @@ -166,6 +167,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
style="@style/AppTheme.PaymentField"
app:text="John G"
android:nextFocusDown="@+id/cardExpDateField"
app:imeOptions="actionNext"
app:fontFamily="@font/robotomono_light"
Expand Down Expand Up @@ -197,6 +199,7 @@
android:nextFocusDown="@+id/cardCVCField"
app:imeOptions="actionNext"
app:inputType="date"
app:text="09/2025"
app:fontFamily="@font/robotomono_light"
app:datePickerModes="input"
app:outputPattern="yyyy-MM-dd'T'HH:mm:ss.SSSSSSS"
Expand All @@ -217,6 +220,7 @@
android:layout_height="match_parent"
style="@style/AppTheme.PaymentField"
app:fieldName="card_data.cardCvc"
app:text="123"
app:fontFamily="@font/robotomono_light"
app:imeOptions="actionDone"/>
</com.verygoodsecurity.vgscollect.widget.VGSTextInputLayout>
Expand Down
6 changes: 3 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
buildscript {
ext.kotlin_version = '1.4.10'
ext.kotlin_version = '1.4.20'
ext.dokka_version = '1.4.0-rc'

repositories {
Expand All @@ -8,7 +8,7 @@ buildscript {
}

dependencies {
classpath 'com.android.tools.build:gradle:4.0.1'
classpath 'com.android.tools.build:gradle:4.1.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"

classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.5'
Expand All @@ -18,7 +18,7 @@ buildscript {
}

ext {
mockito_version = '3.5.0'
mockito_version = '3.6.0'
android_support_libraries = '1.2.0'
}

Expand Down
5 changes: 3 additions & 2 deletions gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#Thu Oct 22 13:07:50 EEST 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip
2 changes: 1 addition & 1 deletion settings.gradle
Original file line number Diff line number Diff line change
@@ -1 +1 @@
include ':app', ':vgscollect', ':vgscollect-cardio'
include ':app', ':vgscollect', ':vgscollect-cardio', ':vgscollect-bouncer'
72 changes: 72 additions & 0 deletions vgscollect-bouncer/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# VGSCollect-Bouncer

Module based on [Bouncer](https://github.com/getbouncer/cardscan-android). It allows to secure integrate scanner with [VGSCollect](https://github.com/verygoodsecurity/vgs-collect-android)

Table of contents
=================

<!--ts-->
* [Dependencies](#dependencies)
* [Integration](#integration)
* [Add the SDK to your project](#add-the-sdk-to-your-project)
* [Usage](#usage)
<!--te-->

## Dependencies

| Dependency | Version |
| :--- | :---: |
| Min SDK | 21 |
| androidx.appcompat:appcompat | 1.2.1 |
| androidx.core:core-ktx | 1.2.1 |

## Integration
For integration you need to install the [Android Studio](http://developer.android.com/sdk/index.html) and a [JDK](http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html) on your machine.

#### Add the SDK to your project
To use the SDK in project you just simply need to add the following line of dependency in your module `gradle.gradle` file:
```
dependencies {
implementation 'com.verygoodsecurity:vgscollect:1.2.5’ //required version 1.2.5 or above
implementation 'com.verygoodsecurity.api:adapter-bouncer:<latest_version>’
}
```

## Usage

**Important**: VGSCollect should be configured too. Check [here](https://www.verygoodsecurity.com/docs/vgs-collect/android-sdk#step-2-configure-your-app) how to do it.

Before scanning you have to setup which information you need to retrieve and final destination VGS secure field:
```
HashMap<String, Integer> scanSettings = new HashMap<>();
scanSettings.put(cardNumberField.getFieldName(), ScanActivity.CARD_NUMBER);
scanSettings.put(cardCvcield.getFieldName(), ScanActivity.CARD_CVC);
scanSettings.put(cardHolderField.getFieldName(), ScanActivity.CARD_HOLDER);
scanSettings.put(cardExpDateField.getFieldName(), ScanActivity.CARD_EXP_DATE);
```

To start scanning you need to attach a Map with settings to Intent and start ScanActivity.
```
public void scanCard() {
HashMap<String, Integer> scanSettings = new HashMap<>();
String numberKey = cardNumberField.getFieldName();
scanSettings.put(numberKey, ScanActivity.CARD_NUMBER);
Intent intent = new Intent(this, ScanActivity.class);
intent.putExtra(ScanActivity.SCAN_CONFIGURATION, scanSettings);
intent.putString(ScanActivity.API_KEY, "<bouncer-api-key>")
startActivityForResult(intent, USER_SCAN_REQUEST_CODE);
}
```

Also very important to call [VGSCollect](https://github.com/verygoodsecurity/vgs-collect-android) **onActivityResult** method inside Activity onActivityResult callback:
```
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
vgsForm.onActivityResult(requestCode, resultCode, data);
}
```
Loading

0 comments on commit 201f5a9

Please sign in to comment.