Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

F253333: SAQ-A Native Components #105

Merged
merged 27 commits into from
Feb 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
6a62f37
Us1762585 - iOS Refactor Native components (#81)
abaeza-wp Jan 5, 2024
589b1f6
US1782181: change Android bridge GenerateSessionsConfig to use panId,…
Jan 3, 2024
e43747e
US1782181: update Android emulator boot timeout to cater for longer b…
Jan 5, 2024
59748ce
US1782181: patch Boost pod.spec while issue is being fixed
Jan 8, 2024
441e163
US1762588 - [iOS] React Native Demo Components Refactor and Props (#86)
abaeza-wp Jan 15, 2024
3c5056e
US1762599 - [Android] React Native Demo Components Refactor and Props…
jmensahWP Jan 16, 2024
e3246a4
Us1762585 - iOS Refactor Native components (#81)
abaeza-wp Jan 5, 2024
2b41cb5
US1782181: change app to display error in a div rather as an alert
Jan 8, 2024
55f7ce5
US1762599: add support for fontSize, placeholderColor & borderColor
jmensahWP Jan 10, 2024
d3964d8
US1762599: update textColor support; add support for font; update uni…
jmensahWP Jan 11, 2024
686099e
US1762599: run format task
jmensahWP Jan 11, 2024
50bfd3c
US1762588: Use paddingHorizontal in demo components
abaeza-wp Jan 9, 2024
8122d8b
US1762588: rebuild pod files to point to remote AccessCheckoutSDK
abaeza-wp Jan 10, 2024
119b026
US1762588: Clean imports
abaeza-wp Jan 11, 2024
2d894bc
US1764971: Create useAccessCheckout Custom hook
abaeza-wp Jan 12, 2024
9f45362
US1764971: Clean up
abaeza-wp Jan 12, 2024
da7549b
US1764971: Re-build lib files
abaeza-wp Jan 15, 2024
6e5d266
US1764971: Re-build dependency files to fix an error caused when inst…
abaeza-wp Jan 15, 2024
d0c1e27
US1764971: expose useCvcOnlyConfig and useCardConfig to provide bette…
abaeza-wp Jan 15, 2024
c7ea7b2
US1764971: Fix prettier
abaeza-wp Jan 22, 2024
57a4e6a
US1764971: rebuild lib files
abaeza-wp Jan 22, 2024
d75a377
US1764971: Differentiate between props interface and config classes a…
abaeza-wp Jan 22, 2024
2e96438
US1764971: Differentiate between props interface and config classes a…
abaeza-wp Jan 22, 2024
3a3256b
Us1833001: [Android] Add font support (#96)
abaeza-wp Jan 23, 2024
c95a272
US1764780 - Within the README under the access-checkout-react-native-…
ochalet-wp Jan 23, 2024
cf6f590
F253333: Export AccessCheckoutTextInput and props (#104)
abaeza-wp Feb 5, 2024
a0b369e
Merge branch 'master' into F253333-saq-a
abaeza-wp Feb 8, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions access-checkout-react-native-sdk/.prettierrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,5 @@
"tabWidth": 2,
"trailingComma": "es5",
"useTabs": false,
"arrowParens": "avoid",
"bracketSameLine": true
"printWidth": 120
}
13 changes: 11 additions & 2 deletions access-checkout-react-native-sdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,27 @@ Create your own uniquely styled and branded checkout form by integrating our Rea
This SDK is the first step to integrate with our Access Worldpay APIs into a React Native app.
It is designed to simplify the integration of the following functionality in your checkout form:
- validating the format of the card details entered by a customer
- generating a session (short-lived token representing a customer's card details)
- generating a session (short-lived token representing a customer's card details)

## Documentation

You can find the detailed documentation explaining how to integrate the SDK and use a session to take a payment starting with the [React Native section](https://developer.worldpay.com/docs/access-worldpay/checkout/react-native) of the [Access Worldpay documentation](https://developer.worldpay.com).
You can find the detailed documentation explaining how to integrate the SDK and use a session to take a payment starting with the [React Native section](https://developer.worldpay.com/docs/access-worldpay/checkout/react-native) of the [Access Worldpay Checkout documentation](https://developer.worldpay.com).

## Compatibility

- `React Native 0.70.0` and above
- `React 18.1.0` and above
- `Cocoapods` only for iOS dependencies

## SAQ-A Compliance

To support SAQ-A compliance when using our React Native SDK, we have created a new component called AccessCheckoutTextInput:
It has been designed so that it does not expose any methods or properties to retrieve the text entered by the end user to ensure our merchants applications do not have direct access to card details and are SAQ-A compliant.

## AccessCheckoutTextInput

You can find detailed documentation about our new component [AccessCheckoutTextInput](https://developer.worldpay.com/docs/access-worldpay/checkout/react-native/optional-configuration) within the [React Native section](https://developer.worldpay.com/docs/access-worldpay/checkout/react-native) of the [Access Worldpay Checkout documentation](https://developer.worldpay.com).

## How to install

Refer to [Get our SDK](https://developer.worldpay.com/docs/access-worldpay/checkout/react-native#get-our-sdk) in the React Native section of the [Access Worldpay documentation](https://developer.worldpay.com)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ dependencies {
testImplementation 'junit:junit:4.13.2'
testImplementation 'org.assertj:assertj-core:3.21.0'
testImplementation 'org.robolectric:robolectric:4.4'
testImplementation 'org.mockito:mockito-core:5.8.0'


instrumentedTestsImplementation 'androidx.test:core:1.4.0'
instrumentedTestsImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,18 @@ package com.worldpay.access.checkout.reactnative.session
import android.content.Context
import androidx.test.core.app.ActivityScenario
import androidx.test.platform.app.InstrumentationRegistry
import com.github.tomakehurst.wiremock.client.WireMock.*
import com.github.tomakehurst.wiremock.client.WireMock.equalTo
import com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor
import com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo
import com.github.tomakehurst.wiremock.client.WireMock.verify
import com.worldpay.access.checkout.reactnative.services.AccessServicesRootStub
import com.worldpay.access.checkout.reactnative.services.MockServer
import com.worldpay.access.checkout.reactnative.services.MockServer.startStubServices
import com.worldpay.access.checkout.reactnative.services.MockServer.stopStubServices
import com.worldpay.access.checkout.reactnative.services.SessionsStub
import com.worldpay.access.checkout.reactnative.session.SessionsTestFixture.Companion.CARD
import com.worldpay.access.checkout.reactnative.session.SessionsTestFixture.Companion.CVC
import com.worldpay.access.checkout.reactnative.session.SessionsTestFixture.Companion.sessionsTextFixture
import com.worldpay.access.checkout.reactnative.utils.TestFixture.Companion.CARD
import com.worldpay.access.checkout.reactnative.utils.TestFixture.Companion.CVC
import com.worldpay.access.checkout.reactnative.utils.TestFixture.Companion.testFixture
import org.awaitility.Awaitility.await
import org.junit.After
import org.junit.Before
Expand All @@ -20,11 +23,11 @@ import java.util.concurrent.TimeUnit.MILLISECONDS


class SessionsInstrumentedTests {
private val timeOutInMs = 5000L
private val timeOutInMs = 500000L

@Before
fun setup() {
sessionsTextFixture().clear()
testFixture().clear()

val context: Context = InstrumentationRegistry.getInstrumentation().context
startStubServices(context, MockServer.PORT)
Expand All @@ -41,11 +44,10 @@ class SessionsInstrumentedTests {
@Test
fun testShouldBeAbleToGenerateACardSession() {
SessionsStub.stubSessionsCardSuccess("my-session")
sessionsTextFixture().pan("4444333322221111")
testFixture().pan("4444333322221111")
.expiryDate("12/34")
.cvc("123")
.sessionsTypes(listOf(CARD))
.reactNativeSdkVersion("1.0.0")

val scenario = ActivityScenario.launch(SessionsInstrumentedTestsActivity::class.java)

Expand All @@ -58,11 +60,10 @@ class SessionsInstrumentedTests {
SessionsStub.stubSessionsCardSuccess("my-session")
SessionsStub.stubSessionsPaymentsCvcSuccess("my-other-session")

sessionsTextFixture().pan("4444333322221111")
testFixture().pan("4444333322221111")
.expiryDate("12/34")
.cvc("123")
.sessionsTypes(listOf(CARD, CVC))
.reactNativeSdkVersion("1.0.0")

val scenario = ActivityScenario.launch(SessionsInstrumentedTestsActivity::class.java)

Expand All @@ -77,10 +78,8 @@ class SessionsInstrumentedTests {
fun testShouldBeAbleToGenerateACvcOnlySession() {
SessionsStub.stubSessionsPaymentsCvcSuccess("my-other-session")

sessionsTextFixture()
.cvc("123")
testFixture().cvc("123")
.sessionsTypes(listOf(CVC))
.reactNativeSdkVersion("1.0.0")

val scenario = ActivityScenario.launch(SessionsInstrumentedTestsActivity::class.java)

Expand All @@ -99,38 +98,22 @@ class SessionsInstrumentedTests {
SessionsStub.stubSessionsCardSuccess("my-session")
SessionsStub.stubSessionsPaymentsCvcFailure(errorName, message)

sessionsTextFixture()
.pan("4444333322221111")
testFixture().pan("4444333322221111")
.expiryDate("12/34")
.cvc("123")
.sessionsTypes(listOf(CARD, CVC))
.reactNativeSdkVersion("1.0.0")

val scenario = ActivityScenario.launch(SessionsInstrumentedTestsActivity::class.java)

assertExceptionIs(scenario, expectedException)
}

@Test
fun testShouldBeAbleToGiveErrorWhenSessionsTypeContainsCvcAndANullCvcIsPassed() {
val exception = RuntimeException("Expected cvcValue to be provided but was not")

sessionsTextFixture()
.cvc(null)
.sessionsTypes(listOf(CVC))
.reactNativeSdkVersion("1.0.0")

val scenario = ActivityScenario.launch(SessionsInstrumentedTestsActivity::class.java)

assertExceptionIs(scenario, exception)
}

@Test
fun testShouldSetNativeSdkWpSdkHeaderWithAccessCheckoutReactNativeVersion() {
SessionsStub.stubSessionsCardSuccess("my-session")
SessionsStub.stubSessionsPaymentsCvcSuccess("my-other-session")

sessionsTextFixture().pan("4444333322221111")
testFixture().pan("4444333322221111")
.expiryDate("12/34")
.cvc("123")
.sessionsTypes(listOf(CARD, CVC))
Expand All @@ -147,7 +130,7 @@ class SessionsInstrumentedTests {
verify(
postRequestedFor(urlEqualTo("/sessions/payments/cvc"))
.withHeader("X-WP-SDK", equalTo("access-checkout-react-native/1.2.3"))
);
)
}

private fun assertSessionsAre(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,14 @@ import com.worldpay.access.checkout.reactnative.services.CardBrandsStub.Companio
import com.worldpay.access.checkout.reactnative.services.MockServer
import com.worldpay.access.checkout.reactnative.services.MockServer.startStubServices
import com.worldpay.access.checkout.reactnative.services.MockServer.stopStubServices
import com.worldpay.access.checkout.reactnative.validation.CardValidationTestFixture.Companion.validationTestFixture
import com.worldpay.access.checkout.reactnative.utils.TestFixture
import com.worldpay.access.checkout.reactnative.utils.TestFixture.Companion.testFixture
import org.awaitility.Awaitility.await
import org.junit.*
import org.junit.After
import org.junit.AfterClass
import org.junit.Before
import org.junit.BeforeClass
import org.junit.Test
import java.util.concurrent.CopyOnWriteArrayList
import java.util.concurrent.TimeUnit.MILLISECONDS

Expand All @@ -38,13 +43,7 @@ class CardValidationInstrumentedTests {

@Before
fun setUp() {
validationTestFixture()
.clear()
.panId(CardValidationInstrumentedTestsActivity.panId)
.expiryDateId(CardValidationInstrumentedTestsActivity.expiryDateId)
.cvcId(CardValidationInstrumentedTestsActivity.cvcId)

CardValidationInstrumentedTestsActivity.clearActions()
TestFixture().clear()
}

@After
Expand All @@ -55,7 +54,7 @@ class CardValidationInstrumentedTests {
@Test
fun shouldRaiseEventWhenPanBecomesValid() {
startActivity().use { scenario ->
CardValidationInstrumentedTestsActivity.run { activity ->
scenario.onActivity { activity ->
activity.setPan("4444333322221111")
}

Expand All @@ -71,7 +70,7 @@ class CardValidationInstrumentedTests {
@Test
fun shouldRaiseEventWhenPanBecomesInvalid() {
startActivity().use { scenario ->
CardValidationInstrumentedTestsActivity.run { activity ->
scenario.onActivity { activity ->
activity.setPan("4444333322221111")
activity.setPan("4")
}
Expand All @@ -92,7 +91,7 @@ class CardValidationInstrumentedTests {
@Test
fun shouldRaiseEventWhenExpiryDateBecomesValid() {
startActivity().use { scenario ->
CardValidationInstrumentedTestsActivity.run { activity ->
scenario.onActivity { activity ->
activity.setExpiryDate("12/30")
}

Expand All @@ -108,7 +107,7 @@ class CardValidationInstrumentedTests {
@Test
fun shouldRaiseEventWhenExpiryDateBecomesInvalid() {
startActivity().use { scenario ->
CardValidationInstrumentedTestsActivity.run { activity ->
scenario.onActivity { activity ->
activity.setExpiryDate("12/30")
activity.setExpiryDate("12/3")
}
Expand All @@ -129,7 +128,7 @@ class CardValidationInstrumentedTests {
@Test
fun shouldRaiseEventWhenCvcBecomesValid() {
startActivity().use { scenario ->
CardValidationInstrumentedTestsActivity.run { activity ->
scenario.onActivity { activity ->
activity.setCvc("123")
}

Expand All @@ -145,7 +144,7 @@ class CardValidationInstrumentedTests {
@Test
fun shouldRaiseEventWhenCvcBecomesInvalid() {
startActivity().use { scenario ->
CardValidationInstrumentedTestsActivity.run { activity ->
scenario.onActivity { activity ->
activity.setCvc("123")
activity.setCvc("12")
}
Expand All @@ -166,7 +165,7 @@ class CardValidationInstrumentedTests {
@Test
fun shouldRaiseEventWhenAllFieldsBecomeValid() {
startActivity().use { scenario ->
CardValidationInstrumentedTestsActivity.run { activity ->
scenario.onActivity { activity ->
activity.setPan("4444333322221111")
activity.setExpiryDate("12/30")
activity.setCvc("123")
Expand All @@ -184,7 +183,7 @@ class CardValidationInstrumentedTests {
@Test
fun shouldRaiseEventWhenRecognisingCardBrand() {
startActivityWithCardBrandRules().use { scenario ->
CardValidationInstrumentedTestsActivity.run { activity ->
scenario.onActivity { activity ->
activity.setPan("4")
}

Expand All @@ -211,10 +210,10 @@ class CardValidationInstrumentedTests {

@Test
fun shouldRaiseAnInvalidPanEventWhenCardBrandIsNotAcceptedByMerchant() {
validationTestFixture().acceptedCardBrands(listOf("jcb"))
testFixture().acceptedCardBrands(listOf("jcb"))

startActivityWithCardBrandRules().use { scenario ->
CardValidationInstrumentedTestsActivity.run { activity ->
scenario.onActivity { activity ->
activity.setPan("4")
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ import com.worldpay.access.checkout.reactnative.react.EventMock
import com.worldpay.access.checkout.reactnative.services.MockServer
import com.worldpay.access.checkout.reactnative.services.MockServer.startStubServices
import com.worldpay.access.checkout.reactnative.services.MockServer.stopStubServices
import com.worldpay.access.checkout.reactnative.validation.CvcOnlyValidationTestFixture.Companion.cvcOnlyValidationTestFixture
import org.awaitility.Awaitility.await
import org.junit.*
import org.junit.After
import org.junit.AfterClass
import org.junit.BeforeClass
import org.junit.Test
import java.util.concurrent.CopyOnWriteArrayList
import java.util.concurrent.TimeUnit.MILLISECONDS

Expand All @@ -34,15 +36,6 @@ class CvcOnlyValidationInstrumentedTests {
}


@Before
fun setUp() {
cvcOnlyValidationTestFixture()
.clear()
.cvcId(CvcOnlyValidationInstrumentedTestsActivity.cvcId)

CvcOnlyValidationInstrumentedTestsActivity.clearActions()
}

@After
fun tearDown() {
WireMock.reset()
Expand All @@ -51,7 +44,7 @@ class CvcOnlyValidationInstrumentedTests {
@Test
fun shouldRaiseEventWhenCvcBecomesValid() {
startActivity().use { scenario ->
CvcOnlyValidationInstrumentedTestsActivity.run { activity ->
scenario.onActivity { activity ->
activity.setCvc("123")
}

Expand All @@ -67,7 +60,7 @@ class CvcOnlyValidationInstrumentedTests {
@Test
fun shouldRaiseEventWhenCvcBecomesInvalid() {
startActivity().use { scenario ->
CvcOnlyValidationInstrumentedTestsActivity.run { activity ->
scenario.onActivity { activity ->
activity.setCvc("123")
activity.setCvc("12")
}
Expand All @@ -88,7 +81,7 @@ class CvcOnlyValidationInstrumentedTests {
@Test
fun shouldRaiseEventWhenAllFieldsBecomeValid() {
startActivity().use { scenario ->
CvcOnlyValidationInstrumentedTestsActivity.run { activity ->
scenario.onActivity { activity ->
activity.setCvc("123")
}

Expand Down
Loading
Loading