diff --git a/.version b/.version
index f30dde0..4be2c72 100644
--- a/.version
+++ b/.version
@@ -1 +1 @@
-6.4.5
\ No newline at end of file
+6.5.0
\ No newline at end of file
diff --git a/.version_code b/.version_code
index 491be1b..1fea86b 100644
--- a/.version_code
+++ b/.version_code
@@ -1 +1 @@
-6040500
\ No newline at end of file
+6050000
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5655ba1..c41ac00 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,11 @@
### NEXT_VERSION_DESCRIPTION_BEGIN
### NEXT_VERSION_DESCRIPTION_END
+## [6.5.0] (16-03-2022)
+
+- Hide ThreatMetrix into mSdk
+- Update documentation
+
## [6.4.5] (06-12-2021)
- Add confirmation in tokenize
diff --git a/MIGRATION.md b/MIGRATION.md
index 602b899..da8d000 100644
--- a/MIGRATION.md
+++ b/MIGRATION.md
@@ -1,6 +1,9 @@
# Migration guide
### Table of Contents
+[6.4.5 -> 6.5.0](##6---6)
+- Удалить библиотеку ThreatMetrix-Android-SDK-.aar, теперь она встроена в само SDK.
+
[6.0.0 -> 6.0.2](##6---6)
- Убрать зависимость `implementation ("ru.yoomoney.sdk.auth:auth:$yoo_sdk_auth_version")` - теперь она подтягивается автоматически
@@ -74,7 +77,8 @@ dependencies {
}
```
-### **Подключить `ThreatMetrix Android SDK 6.2-97
+### **Подключить `ThreatMetrix Android SDK 6.2-97.aar`**
+
> Если вы не использовали платежный метод “ЮMoney”, и не подключали sdk авторизации, то этот блок можно пропустить.
Попросите у менеджера по подключению библиотеку `ThreatMetrix Android SDK 6.2-97.aar`. Создайте папку libs в модуле где подключаете sdk и добавьте туда файл `ThreatMetrix Android SDK 6.2-97.aar`. В build.gradle того же модуля в dependencies добавьте:
diff --git a/README.md b/README.md
index 606d7af..e6c91a9 100644
--- a/README.md
+++ b/README.md
@@ -1,78 +1,73 @@
-# YooMoney for Business Payments SDK (YooKassaPayments)
+# YooMoney Payments SDK
[![Platform](https://img.shields.io/badge/Support-SDK%2021+-brightgreen.svg)](https://img.shields.io/badge/Support-SDK%2021+-brightgreen.svg)
[![GitHub tag](https://img.shields.io/github/v/tag/yoomoney/yookassa-android-sdk.svg?sort=semver)](https://img.shields.io/github/v/tag/yoomoney/yookassa-android-sdk.svg?sort=semver)
[![License](https://img.shields.io/github/license/yoomoney/yookassa-android-sdk.svg)](https://img.shields.io/github/license/yoomoney/yookassa-android-sdk.svg)
-This library allows implementing payment acceptance into mobile apps on Android.
-It works as an extension to the YooMoney API.
+This SDK allows processing payments using a payment token. It **works as an addition to the [YooMoney API](https://yookassa.ru/developers/payments/sdk-tokens)**.
-The mobile SDK contains ready-made payment interfaces (the payment form and everything related to it).
+The general payment process in the app is as follows:
+- You start the process of [tokenization in the SDK](#tokenization);
+- The user selects the payment method and enters the required data;
+- The SDK exchanges this data for a payment token (`payment_token`) and returns it to you;
+- After you receive `payment_token`, create a payment using the [API method](https://yookassa.ru/developers/api#create_payment);
+- If necessary, launch the [payment confirmation](#payment-confirmation) process in the SDK using 3DS or SberPay.
-Using the SDK, you can receive tokens for processing payments via bank cards, Google Pay, Sberbank Online, or YooMoney wallets.
+**Tokenization and payment processes diagram:**
-Oldest supported version of android sdk: 21(Android 5).
+![Diagram](assets/images/diagrams/base_flow_diagram_en.png)
-This repository contains the SDK code and an example of an app which integrates it.
-* [Library code](./library)
-* [Code of the demo app which integrates the SDK](./sample)
-* [README на русском](./README_RU.md)
+The SDK includes ready-made payment interfaces (payment form and everything related to it).
+
+Using the SDK, you can receive tokens for processing payments from a bank card, Google Pay, Sberbank, or a YooMoney wallet.
+This repository contains the SDK code and a sample app integrating it.
+* [Library code](./library)
+* [Code of the demo app that integrates the SDK](./sample)
-# Documentation
+# Documentation
-Android Checkout mobile SDK: version $versionName ([changelog](https://github.com/yoomoney/yookassa-android-sdk/blob/master/CHANGELOG.md))
+Android Checkout mobile SDK - version $versionName ([changelog](https://github.com/yoomoney/yookassa-android-sdk/blob/master/CHANGELOG.md))
* [Changelog](#changelog)
* [Migration guide](#migration-guide)
-* [Registering an app for payments via the wallet](#registering-an-app-for-payments-via-the-wallet)
-* [Adding dependencies](#adding-dependencies)
- * [Implementation via Gradle](#implementation-via-Gradle)
- * [Implementing sdk authorization for payments via the wallet](#setting-up-the-app-scheme)
- * [Configuring the app for selling digital products](#configuring-the-app-for-selling-digital-products)
-* [Using the library](#using-the-library)
+* [Connection via Gradle](#connection-via-Gradle)
+* [Integration recommendations](#integration-recommendations)
+ * [App configuration for digital goods sales](#app-configuration-for-digital-goods-sales)
+ * [Recommended compatible versions](#recommended-compatible-versions)
+* [Library usage](#library-usage)
* [Tokenization](#tokenization)
- * [Launching tokenization](#launching-tokenization)
+ * [Launching tokenization via all methods](#launching-tokenization-via-all-methods)
+ * [Launching tokenization via YooMoney wallet](#launching-tokenization-via-YooMoney-wallet)
+ * [Launching tokenization via SberPay](#launching-tokenization-via-SberPay)
+ * [Launching tokenization via a bank card](#launching-tokenization-via-a-bank-card)
+ * [Preparation for launching Google Pay tokenization](#preparation-for-launching-Google-Pay-tokenization)
+ * [Launching Google Pay tokenization](#launching-Google-Pay-tokenization)
* [Launching tokenization for saved bank cards](#launching-tokenization-for-saved-bank-cards)
* [Getting tokenization results](#getting-tokenization-results)
- * [Using the payment token](#using-the-payment-token)
- * [Test parameters and debugging](#test-parameters-and-debugging)
- * [Interface configuration](#interface-configuration)
- * [3DSecure](#3dsecure)
- * [Scanning bank cards](#scanning-bank-cards)
+ * [Payment confirmation](#payment-confirmation)
+ * [SberPay](#sberpay)
+ * [3DSecure](#3dsecure)
+ * [Linked card](#linked-card)
+ * [Recurring payments](#recurring-payments)
+ * [Logging and mock mode configuration](#logging-and-mock-mode-configuration)
+ * [Logging enabling](#logging-enabling)
+ * [Mock mode configuration](#configuring-mock-mode-configuration)
+ * [Interface configuration](#interface-configuration)
+ * [Scanning a bank card](#scanning-a-bank-card)
* [Useful links](#useful-links)
# Changelog
-[Link to the Changelog](https://github.com/yoomoney/yookassa-android-sdk/blob/master/CHANGELOG.md)
+[Link to Changelog](https://github.com/yoomoney/yookassa-android-sdk/blob/master/CHANGELOG.md)
# Migration guide
-[Link to the Migration guide](https://github.com/yoomoney/yookassa-android-sdk/blob/master/MIGRATION.md)
-
-# Registering an app for payments via the wallet
-> If the YooMoney wallet is one of the payment methods, you need to register your app and get `authCenterClientId`.
-If not, you can skip this step.
-
-If you've already registered apps for **oAuth authorization**, then you can find the list of your apps on this page: https://yookassa.ru/oauth/v2/client
-If you haven't registered apps for **oAuth authorization** yet, you need to follow these instructions.
-1. To register a new app, you need to sign in at https://yookassa.ru
-2. After signing in, go to the page for registering apps: https://yookassa.ru/oauth/v2/client
-3. Click on the Create app button and enter values for the following parameters:
- * Name;
- * Description. Optional;
- * Link to the website;
- * Callback URL: any, you can enter the link to the website;
- * Accesses. There are three sections here: `YooMoney API`, `YooMoney wallet`, and `YooMoney account`.
- * Give permission to access user's wallet balance in the `YooMoney wallet` section. To do that, put a check mark next to the **View** field in the**WALLET BALANCE** section;
- * Open the `YooMoney account` section and give permission to access user's phone number, email address, name, and profile picture. To do that, put a check mark next to the **View** field in the **PHONE NUMBER, EMAIL ADDRESS, NAME, AND PROFILE PICTURE** section;
-3. Click on the Register button and finish the registration;
-4. A window with information about the registered app will open. You'll need `authCenterClientId` to launch tokenization, see [(Launching tokenization)](#launching-tokenization);
+[Link to Migration guide](https://github.com/yoomoney/yookassa-android-sdk/blob/master/MIGRATION.md)
-# Adding dependencies
+# Connection via Gradle
-## Implementation via Gradle
-To implement the library, enter dependencies in build.gradle of the module:
+To connect the library, add the dependencies to the build.gradle of the module:
```groovy
repositories {
@@ -80,40 +75,35 @@ repositories {
}
dependencies {
- implementation 'ru.yoomoney.sdk.kassa.payments:yookassa-android-sdk:$versionName'
+ implementation 'ru.yoomoney.sdk.kassa.payments:yookassa-android-sdk:6.5.0'
}
```
-Ask your onboarding manager for the `ThreatMetrix Android SDK 6.2-97.aar` library.
-Create a libs folder in the module where you implement the sdk and add the `ThreatMetrix Android SDK 6.2-97.aar` there. Add the following in build.gradle of the same module in dependencies:
+You also need to connect the kotlin plugin. To do so, add the following block of code to the build.gradle file of the root directory:
+
```groovy
-dependencies {
- implementation fileTree(dir: "libs", include: ["*.aar"])
+buildscript {
+ dependencies {
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.31"
+ }
}
```
-## Setting up the app scheme
-In order for the sdk to work, you need to set up your app's scheme for processing deep links. It's required for payments via sberpay.
-You need to add `resValue "string", "ym_app_scheme", "your_unique_app_shceme"` to your build.gradle file in the android.defaultConfig section
-```
-android {
- defaultConfig {
- resValue "string", "ym_app_scheme", "your_unique_app_shceme"
- }
+In app, add the module to the build.gradle file:
+
+```groovy
+plugin {
+ id 'kotlin-android'
}
+
```
-Or add a row similar to the following example to your strings.xml:
-```
-
- your_unique_app_shceme
-
-```
-Where your_unique_app_shceme is a unique name of your app; if you already process deep links in your app, you can use your app's working scheme.
-If you haven't processed deep links in the project before, you can create a unique scheme made of Latin letters for your app.
-## Configuring the app for selling digital products
-If your app is used for selling digital products, you need to remove Google Pay from the list of payment methods.
-To do that, add the following code to AndroidManifest:
+# Integration recommendations
+
+## App configuration for digital goods sales
+
+If your app sells digital goods, you need to exclude Google Pay from the list of payment methods.
+To do so, add the following code to AndroidManifest:
```xml
```
-# Using the library
-The `ru.yoomoney.sdk.kassa.payments.Checkout` class is used for everything involved in working with the library
+## Recommended compatible versions
+
+Minimum supported Android SDK version: 21 (Android 5.0).
+
+For the library to work correctly, you should use the following:
+- Kotlin version 1.4.32;
+- targetSdkVersion 31;
+- Gradle version 7.0.+.
+
+# Library usage
## Tokenization
-### Launching tokenization
+The tokenization process is the exchange of payment data for a payment token (`payment_token`). This token is then used for creating a payment [via the API method](https://yookassa.ru/developers/api#create_payment)
+
+The `Checkout.createTokenizeIntent()` method is used for starting the tokenization process. The method returns `Intent` which should be launched in `startActivityForResult()`. After that, the process will be controlled by the SDK.
+The created payment token can be obtained in `onActivityResult()`
-The `Checkout.createTokenizeIntent()` method is used to launch the tokenization process. This method returns `Intent` which should be launched in startActivityForResult(). After that, control over the process will be transferred to the SDK.
-You can get a ready-made payment token in `onActivityResult()` (see [Getting tokenization results](#getting-tokenization-results))
+Mandatory method parameters:
+- context (Context) - context of the app;
+- paymentParameters (PaymentParameters) - parameters of the payment.
-Input parameters of the method:
-* context (Context): app's context;
-* paymentParameters (PaymentParameters): payment parameters;
-* testParameters (TestParameters): parameters for debugging, see [Test parameters and debugging](#test-parameters-and-debugging);
-* uiParameters (UiParameters): interface settings, see [Interface configuration](#interface-configuration).
+Optional method parameters:
+- testParameters (TestParameters) - parameters for the test mode - enable logging/use mock data (see [Logging and mock mode configuration](#logging-and-mock-mode-configuration));
+- uiParameters (UiParameters) - interface configuration (see [Interface configuration](#interface-configuration))
`PaymentParameters` fields:
-Required parameters:
-* amount (Amount): product price. Available payment methods can change depending on this parameter;
-* title (String): product name;
-* subtitle (String): product description;
-* clientApplicationKey (String): key for client apps from the YooMoney Merchant Profile ([Settings section—API keys](https://yookassa.ru/my/api-keys-settings)).;
-* shopId (String): store's ID in YooMoney.
-* savePaymentMethod (SavePaymentMethod): configuration for saving payment methods. Saved payment methods can be used for processing recurring payments.
-* authCenterClientId (String): app's ID for sdk authorization `ru.yoomoney.sdk.auth`, see [Registering an app for payments via the wallet](#registering-an-app-for-payments-via-the-wallet).
-
-Optional parameters:
-* paymentMethodTypes (Set of PaymentMethodType): restrictions on payment methods. If you leave the field empty or enter null in it,
-the library will use all available payment methods;
-* gatewayId (String): gatewayId for the store;
-* customReturnUrl (String): url of the page (only https supported) where you need to return after completing 3ds. It should only be used if a custom Activity is used for 3ds url. If Checkout.createConfirmationIntent() or Checkout.create3dsIntent() is used, don't specify this parameter;
-* userPhoneNumber (String): user's phone number. It's used for autofilling fields for payments via SberPay. Supported format: "+7XXXXXXXXXX".
-* googlePayParameters (GooglePayParameters): settings for payments via Google Pay.
-
-Fields of the `Amount` class:
-* value (BigDecimal): amount;
-* currency (Currency): currency.
-
-Values of `SavePaymentMethod`:
-* ON: Save the payment methods for processing recurring payments. Only payment methods which support saving will be available to users. A notification that the payment method will be saved will be displayed on the contract screen.
-* OFF: Don't save the payment method.
-* USER_SELECTS: User selects if the payment method should be used or not. If a method can be used, a switch will appear on the contract screen.
-
-Values of `PaymentMethodType`:
-* YOO_MONEY: the payment was made via the YooMoney wallet;
-* BANK_CARD: the payment was made via a bank card;
-* SBERBANK: the payment was made via Sberbank (text message invoicing or SberPay);
-* GOOGLE_PAY: the payment was made via Google Pay.
+Mandatory:
+- amount (Amount) - cost of goods. Accepted payment methods may vary depending on this setting. This option will be displayed on the screen of the selected payment method in the process of tokenization via the selected payment method;
+- title (String) - product name. This option will be displayed on the screen of the selected payment method in the process of tokenization via the selected payment method;
+- subtitle (String) - product description. This option will be displayed on the screen of the selected payment method in the process of tokenization via the selected payment method;
+- clientApplicationKey (String) - key for client apps from the YooMoney Merchant Profile ([Settings section — API Keys](https://yookassa.ru/my/api-keys-settings));
+- shopId (String) - ID of the store in YooMoney ([Organization section](https://yookassa.ru/my/company/organization) - copy shopId from the required store);
+- savePaymentMethod (SavePaymentMethod) - settings for saving the payment method. Saved payment methods can be used for recurring payments, (see [Recurring payments](#recurring-payments)).
+
+Optional:
+- paymentMethodTypes (Set of PaymentMethodType) - restrictions on payment methods. If you leave the field empty or specify null in it, the library will use all available payment methods, (see [Launching tokenization via all methods](#launching-tokenization-via-all-methods));
+- gatewayId (String) - gatewayId for the store, (see [Launching Google Pay tokenization](#launch-tokenization-Google-Pay));
+- customReturnUrl (String) - url of the page (only https is supported) that the user should be returned to after completing 3ds. Must be used only when own Activity for the 3ds url is used, (see [3DSecure](#3dsecure));
+- userPhoneNumber (String) - user's phone number for payments via SberPay, (see [Launching tokenization via SberPay](#launching-tokenization-via-SberPay));
+- googlePayParameters (GooglePayParameters) - settings for payments via Google Pay, (see [Launching Google Pay tokenization](#launch-tokenization-Google-Pay));
+- authCenterClientId (String) - unique ID of the app for tokenization via YooMoney. (See [Launching tokenization via YooMoney wallet](#launching-tokenization-via-YooMoney-wallet))
+
+`Amount` class fields:
+- value (BigDecimal) - amount;
+- currency (Currency) - currency.
+
+`SavePaymentMethod` values:
+- ON - Save the payment method for recurring payments. Only payment methods that support saving will be available to the user. During the first payment, a notification stating that the payment method will be saved will appear on the screen of the selected payment method.
+- OFF - Do not save the payment method.
+- USER_SELECTS - The user chooses whether or not to save the payment method. If the method can be saved, a toggle will appear on the selected payment method screen.
+ You can read more about recurring payments in the [Recurring payments](#recurring-payments) section.
+
+`PaymentMethodType` values:
+- YOO_MONEY - payment was made from a YooMoney wallet;
+- BANK_CARD - payment was made from a bank card;
+- SBERBANK - payment was made via Sberbank (text message invoicing or SberPay);
+- GOOGLE_PAY - payment was made via Google Pay.
Fields of the `GooglePayParameters` class:
-* allowedCardNetworks (Set of GooglePayCardNetwork): payment systems which can be used for payments via Google Pay.
+- allowedCardNetworks (Set of GooglePayCardNetwork) - payment systems that allow for payments via Google Pay.
+
+`GooglePayCardNetwork` values:
+- AMEX
+- DISCOVER
+- JCB
+- MASTERCARD
+- VISA
+- INTERAC
+- OTHER
+
+### Launching tokenization via all methods
+
+To launch tokenization via all available payment methods, call the `createTokenizeIntent` method with the specified `PaymentParameters` object that contains the set of all payment methods, or do not include this set.
+
+**Option 1**:
+
+
+ Kotlin
+
+ ```kotlin
+ class MyActivity : AppCompatActivity() {
+
+ fun startTokenize() {
+ val paymentParameters = PaymentParameters(
+ amount = Amount(BigDecimal.TEN, Currency.getInstance("RUB")),
+ title = "Product name",
+ subtitle = "Product description",
+ clientApplicationKey = "live_thisKeyIsNotReal", // key for client apps from the YooMoney Merchant Profile
+ shopId = "12345", // ID of the store in the YooMoney system
+ savePaymentMethod = SavePaymentMethod.OFF, // flag of the disabled option to save payment methods,
+ paymentMethodTypes = setOf(PaymentMethodType.YOO_MONEY, PaymentMethodType.BANK_CARD, PaymentMethodType.SBERBANK, PaymentMethodType.GOOGLE_PAY), // the full list of available payment methods has been provided
+ gatewayId = "gatewayId", // gatewayId of the store for Google Pay payments (required if payment methods include Google Pay)
+ customReturnUrl = "https://custom.redirect.url", // url of the page (only https is supported) that the user should be returned to after completing 3ds.
+ userPhoneNumber = "+79041234567", // user's phone number for autofilling the user phone number field in SberPay. Supported data format: "+7XXXXXXXXXX"
+ authCenterClientId = "example_authCenterClientId" // ID received upon registering the app on the https://yookassa.ru website
+ )
+ val intent = createTokenizeIntent(this, paymentParameters)
+ startActivityForResult(intent, REQUEST_CODE_TOKENIZE)
+ }
+ }
+ ```
+
+
+
+ Java
+
+ ```java
+ class MyActivity extends AppCompatActivity {
+
+ void startTokenize() {
+ Set paymentMethodTypes = new HashSet(){{
+ add(PaymentMethodType.SBERBANK); // selected payment method - SberPay
+ add(PaymentMethodType.YOO_MONEY); // selected payment method - YooMoney
+ add(PaymentMethodType.BANK_CARD); // selected payment method - Bank card
+ add(PaymentMethodType.GOOGLE_PAY); // selected payment method - Google Pay
+ }};
+ PaymentParameters paymentParameters = new PaymentParameters(
+ new Amount(BigDecimal.TEN, Currency.getInstance("RUB")),
+ "Product name",
+ "Product description",
+ "live_thisKeyIsNotReal", // key for client apps from the YooMoney Merchant Profile
+ "12345", // ID of the store in the YooMoney system
+ SavePaymentMethod.OFF, // flag of the disabled option to save payment methods
+ paymentMethodTypes, // the full list of available payment methods has been provided
+ "gatewayId", // gatewayId of the store for Google Pay payments (required if payment methods include Google Pay)
+ "https://custom.redirect.url", // url of the page (only https is supported) that the user should be returned to after completing 3ds. Must be used only when own Activity for the 3ds url is used.
+ userPhoneNumber = "+79041234567", // user's phone number for autofilling the user phone number field in SberPay. Supported data format: "+7XXXXXXXXXX"
+ null, // settings for tokenization via GooglePay,
+ "example_authCenterClientId" // ID received upon registering the app on the https://yookassa.ru website
+ );
+ Intent intent = Checkout.createTokenizeIntent(this, paymentParameters);
+ startActivityForResult(intent, REQUEST_CODE_TOKENIZE);
+ }
+ }
+ ```
+
+
+**Option 2**:
+
+
+ Kotlin
+
+```kotlin
+class MyActivity : AppCompatActivity() {
+
+ fun startTokenize() {
+ val paymentParameters = PaymentParameters(
+ amount = Amount(BigDecimal.TEN, Currency.getInstance("RUB")),
+ title = "Product name",
+ subtitle = "Product Description",
+ clientApplicationKey = "live_thisKeyIsNotReal", // key for client apps from the YooMoney Merchant Profile (https://yookassa.ru/my/api-keys-settings)
+ shopId = "12345", // ID of the store in the YooMoney system
+ savePaymentMethod = SavePaymentMethod.OFF, // flag of the disabled option to save payment methods,
+ authCenterClientId = "example_authCenterClientId", // ID received upon registering the app on the https://yookassa.ru website
+ gatewayId = "gatewayId", // gatewayId of the store for Google Pay payments (required if payment methods include Google Pay)
+ customReturnUrl = "https://custom.redirect.url", // url of the page (only https is supported) that the user should be returned to after completing 3ds. Must be used only when own Activity for the 3ds url is used.
+ userPhoneNumber = "+79041234567", // user's phone number for autofilling the user phone number field in SberPay. Supported data format: "+7XXXXXXXXXX"
+ )
+ val intent = createTokenizeIntent(this, paymentParameters)
+ startActivityForResult(intent, REQUEST_CODE_TOKENIZE)
+ }
+ }
+ ```
+
+
+
+ Java
+
+ ```java
+ class MyActivity extends AppCompatActivity {
+
+ void startTokenize() {
+ PaymentParameters paymentParameters = new PaymentParameters(
+ new Amount(BigDecimal.TEN, Currency.getInstance("RUB")),
+ "Product name",
+ "Product Description",
+ "live_thisKeyIsNotReal", // key for client apps from the YooMoney Merchant Profile
+ "12345", // ID of the store in the YooMoney system
+ SavePaymentMethod.OFF, // flag of the disabled option to save payment methods
+ null, // the full list of available payment methods has been provided
+ "gatewayId", // gatewayId of the store for Google Pay payments (required if payment methods include Google Pay)
+ "https://custom.redirect.url", // url of the page (only https is supported) that the user should be returned to after completing 3ds. Must be used only when own Activity for the 3ds url is used.
+ "+79041234567", // user's phone number for autofilling the user phone number field in SberPay. Supported data format: "+7XXXXXXXXXX".
+ null, // settings for tokenization via GooglePay,
+ "example_authCenterClientId" // ID received upon registering the app on the https://yookassa.ru website
+ );
+ Intent intent = Checkout.createTokenizeIntent(this, paymentParameters);
+ startActivityForResult(intent, REQUEST_CODE_TOKENIZE);
+ }
+ }
+ ```
+
+
+**Processed results of the tokenization process are contained in the** [Get tokenization results](#get-tokenization-results) **section**
+
+
+### Launching tokenization via YooMoney wallet
+
+> If the payment methods include the YooMoney wallet, you will need to register the app and obtain `authCenterClientId`.
+In other cases, this step can be skipped.
+
+If you have already registered an app for **oAuth-authorization**, you can find the list of your apps at https://yookassa.ru/oauth/v2/client
+If you have not yet registered an app for **oAuth-authorization**, follow the instructions below.
+1. To register a new app, sign in at https://yookassa.ru
+2. After signing in, navigate to the app registration page - https://yookassa.ru/oauth/v2/client
+3. Click the Create app button and set the values for the parameters:
+ * Name;
+ * Description (optional);
+ * Link to website;
+ * Callback URL (any value; you can specify the link to the website);
+ * Accesses. This includes three sections: `YooMoney API`, `YooMoney wallet`, `YooMoney profile`.
+ * In the `YooMoney wallet` section, give permission to view the balance of the user's wallet. To do so, check the box next to the **View** field in the **WALLET BALANCE** section;
+ * Open the `YooMoney profile` section and give permission to view the user's phone number, email, name, and avatar. To do so, check the box next to the **View** field in the **USER PHONE NUMBER, EMAIL, NAME, AND AVATAR** section;
+3. Click or tap the "Register" button and complete the registration;
+4. Information about the registered app will appear in the opened window. You will need `authCenterClientId` to launch tokenization;
+
+
+Kotlin
+
+```kotlin
+class MyActivity : AppCompatActivity() {
+
+ fun startYooMoneyTokenize() {
+ val paymentParameters = PaymentParameters(
+ amount = Amount(BigDecimal.TEN, Currency.getInstance("RUB")),
+ title = "Product name",
+ subtitle = "Product Description",
+ clientApplicationKey = "live_thisKeyIsNotReal", // key for client apps from the YooMoney Merchant Profile (https://yookassa.ru/my/api-keys-settings)
+ shopId = "12345", // ID of the store in the YooMoney system
+ savePaymentMethod = SavePaymentMethod.OFF, // flag of the disabled option to save payment methods,
+ paymentMethodTypes = setOf(PaymentMethodType.YOO_MONEY), // selected payment method: YooMoney wallet
+ authCenterClientId = "example_authCenterClientId" // ID received upon registering the app on the https://yookassa.ru website
+ )
+ val intent = createTokenizeIntent(this, paymentParameters)
+ startActivityForResult(intent, REQUEST_CODE_TOKENIZE)
+ }
+}
+```
+
+
+
+ Java
+
+ ```java
+ class MyActivity extends AppCompatActivity {
+
+ void startYooMoneyTokenize() {
+ Set paymentMethodTypes = new HashSet<>();
+ PaymentParameters paymentParameters = new PaymentParameters(
+ new Amount(BigDecimal.TEN, Currency.getInstance("RUB")),
+ "Product name",
+ "Product description",
+ "live_thisKeyIsNotReal", // key for client apps from the YooMoney Merchant Profile (https://yookassa.ru/my/api-keys-settings)
+ "12345", // ID of the store in the YooMoney system
+ SavePaymentMethod.OFF, // flag of the disabled option to save payment methods
+ paymentMethodTypes.add(PaymentMethodType.YOO_MONEY), // selected payment method: YooMoney wallet,
+ null, // gatewayId of the store for Google Pay payments (required if payment methods include Google Pay)
+ null, // url of the page (only https is supported) that the user should be returned to after completing 3ds. Must be used only when own Activity for the 3ds url is used.
+ null, // user's phone number for autofilling the user phone number field in SberPay. Supported data format: "+7XXXXXXXXXX"
+ null, // settings for tokenization via GooglePay,
+ "example_authCenterClientId" // authCenterClientId: ID received upon registering the app on the https://yookassa.ru website
+ );
+ Intent intent = Checkout.createTokenizeIntent(this, paymentParameters);
+ startActivityForResult(intent, REQUEST_CODE_TOKENIZE);
+ }
+ }
+ ```
+
+
+**Processed results of the tokenization process are contained in the** [Get tokenization results](#get-tokenization-results) **section**
+
+
+### Launching tokenization via SberPay
+
+Payments via SberPay allow for two user scenarios:
+- Payment via the Sberbank Online mobile app;
+- Payment by phone number (without the Sberbank Online mobile app);
+
+To provide the option of paying via the Sberbank Online mobile app to your users, specify the unique scheme from your app's deep link.
+The unique deep link scheme is what you specify as the scheme in your deep links. For example, in the `exampleapp://some.path` deep link, `exampleapp` is the scheme of your app.
+
+To add a unique deep link scheme, insert the `resValue "string", "ym_app_scheme", "exampleapp"` line to the android.defaultConfig block in your build.gradle file
+```
+android {
+ defaultConfig {
+ resValue "string", "ym_app_scheme", "exampleapp"
+ }
+}
+```
+Or insert a line like this to your strings.xml:
+```
+
+ exampleapp
+
+```
+Where `exampleapp` is your app's unique deep link scheme (substitute this example for your scheme).
+If you are already processing some deep links in your app, you can use the ready-made scheme of your app.
+If you have not processed deep links in the projec beforet, you can create a unique scheme for your app (it must consist of Latin characters).
+
+**Launching tokenization via SberPay looks like this.**
+
+
+ Kotlin
+
+```kotlin
+class MyActivity: Activity() {
+
+ private fun startSberPayTokenize() {
+ val paymentParameters = PaymentParameters(
+ amount = Amount(BigDecimal.valueOf(10.0), Currency.getInstance("RUB")),
+ title = "Product name",
+ subtitle = "Product Description",
+ clientApplicationKey = "live_thisKeyIsNotReal", // key for client apps from the YooMoney Merchant Profile (https://yookassa.ru/my/api-keys-settings)
+ shopId = "12345", // ID of the store in the YooMoney system
+ savePaymentMethod = SavePaymentMethod.OFF, // flag of the disabled option to save payment methods
+ paymentMethodTypes = setOf(PaymentMethodType.SBERBANK), // selected payment method: SberPay
+ userPhoneNumber = "+79041234567", // user's phone number for autofilling the user phone number field in SberPay. Supported data format: "+7XXXXXXXXXX"
+ )
+ val intent = createTokenizeIntent(this, paymentParameters)
+ startActivityForResult(intent, REQUEST_CODE_TOKENIZE)
+ }
+}
+```
+
-Values of `GooglePayCardNetwork`:
-* AMEX
-* DISCOVER
-* JCB
-* MASTERCARD
-* VISA
-* INTERAC
-* OTHER
+
+ Java
```java
-class MyActivity extends AppCompatActivity {
+public class MyActivity extends Activity {
+
+ private void startSberPayTokenize() {
+ Set paymentMethodTypes = new HashSet(){{
+ add(PaymentMethodType.SBERBANK); // selected payment method: SberPay
+ }};
+ paymentMethodTypes.add(PaymentMethodType.SBERBANK);
+ PaymentParameters paymentParameters = new PaymentParameters(
+ new Amount(BigDecimal.valueOf(10.0), Currency.getInstance("RUB")),
+ "Product name",
+ "Product Description",
+ "live_thisKeyIsNotReal", // key for client apps from the YooMoney Merchant Profile (https://yookassa.ru/my/api-keys-settings)
+ "12345", // ID of the store in the YooMoney system
+ SavePaymentMethod.OFF, // flag of the disabled option to save payment methods
+ paymentMethodTypes, // selected payment method: SberPay,
+ null, // gateway of the store for Google Pay payments (required if payment methods include Google Pay)
+ null, // url of the page (only https is supported) that the user should be returned to after completing 3ds. Must be used only when own Activity for the 3ds url is used.
+ "+79041234567" // user's phone number for autofilling the user phone number field in SberPay. Supported data format: "+7XXXXXXXXXX"
+ );
+ Intent intent = Checkout.createTokenizeIntent(this, paymentParameters);
+ startActivityForResult(intent, REQUEST_CODE_TOKENIZE);
+ }
+}
+```
+
- ...
+**Processed results of the tokenization process are contained in the** [Get tokenization results](#get-tokenization-results) **section**
- void timeToStartCheckout() {
+
+### Launching tokenization via a bank card
+
+To launch tokenization via just a bank card, specify `setOf(PaymentMethodType.BANK_CARD)` in `PaymentParameters`:
+
+
+ Kotlin
+
+```kotlin
+class MyActivity : AppCompatActivity() {
+
+ fun startBankCardTokenize() {
+ val paymentParameters = PaymentParameters(
+ amount = Amount(BigDecimal.TEN, Currency.getInstance("RUB")),
+ title = "Product name",
+ subtitle = "Product description",
+ clientApplicationKey = "live_thisKeyIsNotReal", // key for client apps from the YooMoney Merchant Profile (https://yookassa.ru/my/api-keys-settings)
+ shopId = "12345", // ID of the store in the YooMoney system
+ savePaymentMethod = SavePaymentMethod.OFF, // flag of the disabled option to save payment methods,
+ paymentMethodTypes = setOf(PaymentMethodType.BANK_CARD) // selected payment method: bank card
+ )
+ val intent = createTokenizeIntent(this, paymentParameters)
+ startActivityForResult(intent, REQUEST_CODE_TOKENIZE)
+ }
+}
+```
+
+
+
+ Java
+
+```java
+class MyActivity extends AppCompatActivity {
+
+ void startBankCardTokenize() {
+ Set paymentMethodTypes = new HashSet<>();
PaymentParameters paymentParameters = new PaymentParameters(
new Amount(BigDecimal.TEN, Currency.getInstance("RUB")),
"Product name",
"Product description",
- "live_AAAAAAAAAAAAAAAAAAAA",
- "12345",
- SavePaymentMethod.OFF
+ "live_thisKeyIsNotReal", // key for client apps from the YooMoney Merchant Profile (https://yookassa.ru/my/api-keys-settings)
+ "12345", // ID of the store in the YooMoney system
+ SavePaymentMethod.OFF, // flag of the disabled option to save payment methods
+ paymentMethodTypes.add(PaymentMethodType.BANK_CARD) // selected payment method: bank card
);
Intent intent = Checkout.createTokenizeIntent(this, paymentParameters);
startActivityForResult(intent, REQUEST_CODE_TOKENIZE);
}
}
```
+
+
+**Processed results of the tokenization process are contained in the** [Get tokenization results](#get-tokenization-results) **section**
+
+
+### Preparation for launching Google Pay tokenization
+
+Before launching Google Pay tokenization, you need to prepare the app and complete integration with the Google Pay API.
+
+#### Preparing the Google Play Console
+
+For payments via Google Pay to work properly in the production environment, make sure that:
+- You have a developer account in the developer console: https://play.google.com/console
+- An app has been created in the developer console;
+- Your app is signed with a release key and uploaded to the developer console;
+
+#### Preparing a profile in the Google Pay Business Console
+
+Once you've completed the steps in the [Preparing the Google Play Console](#preparing-the-hoogle-play-console) section, set up your profile in the Google Pay Business Console:
+- Visit the site: https://pay.google.com/business/console;
+- Fill in all the information required for a company profile;
+- After filling out the company profile, send it for verification by the Google Pay Business Console team;
+- Wait until the company profile is verified by the Google Pay Business Console team.
+
+#### Integrating the app with the Google Pay API
+
+If you've completed all of the steps listed above, start integrating the Google Pay API:
+- Visit the Google Pay Business Console website: https://pay.google.com/business/console;
+- Navigate to the Google Pay API tab;
+- Find the "Integration with your Android app" block;
+- Find your app that you want to complete integration for in this block and click "Manage". If your app is not listed, follow the instructions in the [Preparing the Google Play Console](#preparing-the-hoogle-play-console) section;
+- In the following window, select the type of integration through the gateway;
+- Upload screenshots of the purchase process. The process of creating these screenshots is detailed in the [Preparing screenshots of the purchase process for the Google Pay API](#preparing-screenshots-of-the-purchase-process-for-Google-Pay-API) section;
+- Send the form for review.
+- After integration is verified and confirmed, the release-ready app will start working with payments via Google Pay.
+- If integration was rejected, make corrections in accordance with the comments and resubmit the form.
+
+#### Preparing screenshots of the purchase process for the Google Pay API
+
+To fill out the form in the [Integrating the app with the Google Pay API](#Integrating-the-app-with-the-Google-Pay-API) section, you will need screenshots of the payment process.
+That includes screenshots of several steps, with examples shown below.
+> Sample screenshots below are provided as examples, do not use them when filling out the form. You ill need to create similar screenshots from your app.
+
+| Product screen | Screen with payment methods | Screen for payment via Google Pay | Successful payment screen |
+| ------------- | ----- | ----- | ----- |
+| ![Product screen](assets/images/pay-flow-examples/1_2_item_selection_pre_purchase_screen.png) | ![Product screen](assets/images/pay-flow-examples/3_payment_method_screen.png) | ![Product screen](assets/images/pay-flow-examples/4_google_pay_api_payment_screen.png) | ![Product screen](assets/images/pay-flow-examples/5_post_purchase_screen.png) |
+
+We propose using the sdk mock mode to take screenshots of the entire payment process. This is the mode where the sdk doesn't make any real requests to the server using previously prepared data instead.
+- To do so, launch tokenization with all the payment methods you're planning to use.
+- For the `testParameters` parameter, specify `googlePayTestEnvironment = true` and `mockConfiguration = MockConfiguration()`
+
+`googlePayTestEnvironment` is responsible for the environment that Google Pay will work in.
+- If you specify `googlePayTestEnvironment = true`, a test environment will be used (you can find out more at https://developers.google.com/pay/api/android/guides/test-and-deploy/integration-checklist)
+- If you specify `googlePayTestEnvironment = false`, or don't specify the parameter at all, the production environment will be used.
+> **Please note** if you specify `googlePayTestEnvironment = true`, then tokenization in the sdk itself will not work.
+
+Below are examples of code with the launch of tokenization for taking screenshots of the payment process via Google Pay
+
+
+ Kotlin
+
+```kotlin
+class MyActivity: Activity() {
+
+ private fun startSberPayTokenize() {
+ val paymentParameters = PaymentParameters(
+ amount = Amount(BigDecimal.valueOf(10.0), Currency.getInstance("RUB")),
+ title = "Product name",
+ subtitle = "Product Description",
+ clientApplicationKey = "live_thisKeyIsNotReal", // key for client apps from the YooMoney Merchant Profile (https://yookassa.ru/my/api-keys-settings)
+ shopId = "12345", // ID of the store in the YooMoney system
+ savePaymentMethod = SavePaymentMethod.OFF, // flag of the disabled option to save payment methods
+ authCenterClientId = "example_authCenterClientId" // ID received upon registering the app on the https://yookassa.ru website
+ )
+ val intent = createTokenizeIntent(
+ context = this,
+ paymentParameters = paymentParameters,
+ testParameters = TestParameters(
+ showLogs = true,// showLogs - enable/disable display of SDK logs
+ googlePayTestEnvironment = true,// googlePayTestEnvironment - what type of environment should be used for Google Pay, test or production. Learn more at https://developers.google.com/pay/api/android/guides/test-and-deploy/integration-checklist
+ mockConfiguration = MockConfiguration()//Enabling mock mode
+ )
+ )
+ startActivityForResult(intent, REQUEST_CODE_TOKENIZE)
+ }
+}
+```
+
-### Launching tokenization for saved bank cards
+
+ Java
-This tokenization method is used in case there's a bank card linked to the store and its csc needs to be requested from the user again.
-Otherwise, the standard tokenization procedure should be followed (see [Launching tokenization](#launching-tokenization)).
+```java
+class MyActivity extends AppCompatActivity {
-The `Checkout.createSavedCardTokenizeIntent()` method is used to launch the tokenization process with a payment ID. This method returns `Intent` which should be launched in startActivityForResult().
-You can get a ready-made payment token in `onActivityResult()` (see [Getting tokenization results](#getting-tokenization-results))
+ private void startTokenize() {
+ TestParameters testParameters = new TestParameters(
+ true, // showLogs - enable/disable display of SDK logs
+ true, // googlePayTestEnvironment - what type of environment should be used for Google Pay, test or production. Learn more at https://developers.google.com/pay/api/android/guides/test-and-deploy/integration-checklist
+ new MockConfiguration() // Enabling mock mode
+ );
+ PaymentParameters paymentParameters = new PaymentParameters(
+ new Amount(BigDecimal.TEN, Currency.getInstance("RUB")),
+ "Product name",
+ "Product Description",
+ "live_thisKeyIsNotReal", // key for client apps from the YooMoney Merchant Profile
+ "12345", // ID of the store in the YooMoney system
+ SavePaymentMethod.OFF, // flag of the disabled option to save payment methods
+ null, // the full list of available payment methods has been provided
+ "gatewayId", // gatewayId of the store for Google Pay payments (required if payment methods include Google Pay)
+ "https://custom.redirect.url", // url of the page (only https is supported) that the user should be returned to after completing 3ds. Must be used only when own Activity for the 3ds url is used.
+ "+79041234567", // user's phone number for autofilling the user phone number field in SberPay. Supported data format: "+7XXXXXXXXXX".
+ null, // settings for tokenization via GooglePay,
+ "example_authCenterClientId" // ID received upon registering the app on the https://yookassa.ru website
+ );
+ Intent intent = Checkout.createTokenizeIntent(this, paymentParameters, testParameters);
+ startActivityForResult(intent, REQUEST_CODE_TOKENIZE);
+ }
+}
+```
+
-Input parameters of the method:
-* context (Context): app's context;
-* savedBankCardPaymentParameters (SavedBankCardPaymentParameters): parameters of a payment with a saved bank card;
-* testParameters (TestParameters): parameters for debugging, see [Test parameters and debugging](#test-parameters-and-debugging);
-* uiParameters (UiParameters): interface settings, see [Interface configuration](#interface-configuration).
+**Processed results of the tokenization process are contained in the** [Get tokenization results](#get-tokenization-results) **section**
-Fields of `SavedBankCardPaymentParameters`:
-* amount (Amount): product price. Available payment methods can change depending on this parameter;
-* title (String): product name;
-* subtitle (String): product description;
-* clientApplicationKey (String): store's token received in YooMoney;
-* shopId (String): store's ID in YooMoney;
-* paymentId (String): payment ID.
-* savePaymentMethod (SavePaymentMethod): configuration for saving payment methods. Saved payment methods can be used for processing recurring payments.
+### Launching Google Pay tokenization
-Fields of the `Amount` class:
-* value (BigDecimal): amount;
-* currency (Currency): currency.
+>If you're integrating Google Pay for the first time, make sure all the conditions from the [Preparation for launching Google Pay tokenization](#preparation-for-launching-Google-Pay-tokenization)) section are met
-Values of `SavePaymentMethod`:
-* ON: Save the payment methods for processing recurring payments. Only payment methods which support saving will be available to users. A notification that the payment method will be saved will be displayed on the contract screen.
-* OFF: Don't save the payment method.
-* USER_SELECTS: User selects if the payment method should be used or not. If a method can be used, a switch will appear on the contract screen.
+To launch tokenization via Google Pay, specify the `PaymentMethodType.GOOGLE_PAY` value in `paymentMethodTypes`
+
+
+ Kotlin
+
+```kotlin
+class MyActivity: Activity() {
+
+ private fun startGooglePayTokenize() {
+ val paymentParameters = PaymentParameters(
+ amount = Amount(BigDecimal.valueOf(10.0), Currency.getInstance("RUB")),
+ title = "Product name",
+ subtitle = "Product description",
+ clientApplicationKey = "live_thisKeyIsNotReal", // key for client apps from the YooMoney Merchant Profile (https://yookassa.ru/my/api-keys-settings)
+ shopId = "12345", // ID of the store in the YooMoney system
+ savePaymentMethod = SavePaymentMethod.OFF, // flag of the disabled option to save payment methods
+ paymentMethodTypes = setOf(PaymentMethodType.GOOGLE_PAY) // selected payment method: Google Pay
+ )
+ val intent = createTokenizeIntent(context = this, paymentParameters = paymentParameters)
+ startActivityForResult(intent, REQUEST_CODE_TOKENIZE)
+ }
+}
+```
+
+
+
+ Java
```java
class MyActivity extends AppCompatActivity {
- ...
+ void startGooglePayTokenize() {
+ Set paymentMethodTypes = new HashSet<>();
+ PaymentParameters paymentParameters = new PaymentParameters(
+ new Amount(BigDecimal.TEN, Currency.getInstance("RUB")),
+ "Product name",
+ "Product description",
+ "live_thisKeyIsNotReal", // key for client apps from the YooMoney Merchant Profile (https://yookassa.ru/my/api-keys-settings)
+ "12345", // ID of the store in the YooMoney system
+ SavePaymentMethod.OFF, // flag of the disabled option to save payment methods
+ paymentMethodTypes.add(PaymentMethodType.GOOGLE_PAY) // selected payment method: Google Pay
+ );
+ Intent intent = Checkout.createTokenizeIntent(this, paymentParameters);
+ startActivityForResult(intent, REQUEST_CODE_TOKENIZE);
+ }
+}
+```
+
+
+**Processed results of the tokenization process are contained in the** [Get tokenization results](#get-tokenization-results) **section**
+
- void timeToStartCheckout() {
+> Payments via Google Pay only work with a release-ready app with the release app package, signed with a release key.
+
In other cases, tokenization via Google Pay will not work.
+
+### Launching tokenization for saved bank cards
+
+This tokenization method is used when a bank card is linked to the store (see [Linked card](#linked-card)) and you need to re-request its CSC from the user.
+In other cases, the standard tokenization mechanism should be used (see [Launching tokenization](#tokenization)).
+
+To start the tokenization process with a payment ID, use the `Checkout.createSavedCardTokenizeIntent()` method. The method returns an `Intent` which should be launched in `startActivityForResult()`.
+The created payment token can be obtained in `onActivityResult()` (see [Getting tokenization results](#getting-tokenization-results))
+
+Mandatory method parameters:
+- context (Context) - context of the app;
+- savedBankCardPaymentParameters (SavedBankCardPaymentParameters) - parameters of the payment via a saved bank card.
+
+Optional method parameters:
+- testParameters (TestParameters) - parameters for the test mode - enable logging/use mock data (see [Logging and mock mode configuration](#logging-and-mock-mode-configuration));
+- uiParameters (UiParameters) - interface configuration (see [Interface configuration](#interface-configuration)).
+
+`SavedBankCardPaymentParameters` fields:
+
+Mandatory:
+- amount (Amount) - cost of goods. Accepted payment methods may vary depending on this setting;
+- title (String) - product name;
+- subtitle (String) - product description;
+- clientApplicationKey (String) - key for client apps from the YooMoney Merchant Profile ([Settings section — API Keys](https://yookassa.ru/my/api-keys-settings));
+- shopId (String) - ID of the store in YooMoney ([Organization section](https://yookassa.ru/my/company/organization) - copy shopId from the required store);
+- paymentMethodId (String) - payment ID;
+- savePaymentMethod (SavePaymentMethod) - settings for saving the payment method. Saved payment methods can be used for recurring payments, (see [Recurring payments](#recurring-payments)).
+
+Optional:
+- gatewayId (String) - gatewayId for the store, (see [Launching Google Pay tokenization](#launch-tokenization-Google-Pay)).
+
+`Amount` class fields:
+* value (BigDecimal) - amount;
+* currency (Currency) - currency.
+
+`SavePaymentMethod` values:
+* ON - Save the payment method for recurring payments. Only payment methods that support saving will be available to the user. During the first payment, a notification stating that the payment method will be saved will appear on the screen of the selected payment method.
+* OFF - Do not save the payment method.
+- USER_SELECTS - The user chooses whether to save the payment method or not. If the method can be saved, a toggle will appear on the selected payment method screen.
+ You can read more about recurring payments in the [Recurring payments](#recurring-payments) section.
+
+
+ Kotlin
+
+```kotlin
+class MyActivity : AppCompatActivity() {
+
+ fun startSavedCardTokenize() {
+ val parameters = SavedBankCardPaymentParameters(
+ amount = Amount(BigDecimal.TEN, Currency.getInstance("RUB")),
+ title = "Product name",
+ subtitle = "Product description",
+ clientApplicationKey = "live_thisKeyIsNotReal", // key for client apps from the YooMoney Merchant Profile
+ shopId = "12345", // ID of the store in the YooMoney system
+ paymentMethodId = "paymentMethodIdExample", // unique payment ID
+ savePaymentMethod = SavePaymentMethod.OFF
+ )
+ val intent = createSavedCardTokenizeIntent(this, parameters)
+ startActivityForResult(intent, REQUEST_CODE_TOKENIZE)
+ }
+}
+```
+
+
+
+ Java
+
+```java
+class MyActivity extends AppCompatActivity {
+
+ void startSavedCardTokenize() {
SavedBankCardPaymentParameters parameters = new SavedBankCardPaymentParameters(
new Amount(BigDecimal.TEN, Currency.getInstance("RUB")),
"Product name",
"Product description",
- "live_AAAAAAAAAAAAAAAAAAAA",
- "12345",
- "paymentId",
- SavePaymentMethod.OFF
+ "live_thisKeyIsNotReal", // key for client apps from the YooMoney Merchant Profile
+ "12345", // ID of the store in the YooMoney system
+ "paymentMethodIdExample", // unique payment ID
+ SavePaymentMethod.OFF // flag of the disabled option to save payment methods
);
Intent intent = Checkout.createSavedCardTokenizeIntent(this, parameters);
startActivityForResult(intent, REQUEST_CODE_TOKENIZE);
}
}
```
+
+
+**Processed results of the tokenization process are contained in the** [Get tokenization results](#get-tokenization-results) **section**
+
### Getting tokenization results
-Tokenization result will be returned in `onActivityResult()`.
-Possible result types:
-* Activity.RESULT_OK: tokenization completed successfully;
-* Activity.RESULT_CANCELED: user has canceled tokenization;
+The results of the `Checkout.createTokenizeIntent` method can be processed in the `onActivityResult()` method.
+
+Possible types of results:
+* Activity.RESULT_OK - tokenization was successful;
+* Activity.RESULT_CANCELED - tokenization canceled by user;
-In case of a successful tokenization, the SDK will return a token and the type of the payment tool using which it was received.
-Use the `Checkout.createTokenizationResult()` method to receive the token.
+In case of successful tokenization, mSDK will return the `TokenizationResult` entity that contains the token and the type of payment tool used to receive it.
+Use the `Checkout.createTokenizationResult()` method to get the token.
-`Checkout.createTokenizationResult()` accepts `Intent` received in `onActivityResult()` in case of a successful tokenization as input. It returns TokenizationResult which consists of:
-* paymentToken (String): payment token, see [Using the payment token](#using-the-payment-token);
-* paymentMethodType (PaymentMethodType): type of the payment method.
+`TokenizationResult` stores:
+* paymentToken (String) - payment token;
+* paymentMethodType (PaymentMethodType) - payment method type.
-Values of `PaymentMethodType`:
-* YOO_MONEY: the payment was made via the YooMoney wallet;
-* BANK_CARD: the payment was made via a bank card;
-* SBERBANK: the payment was made via Sberbank (text message invoicing or SberPay);
-* GOOGLE_PAY: the payment was made via Google Pay.
+`PaymentMethodType` values:
+* YOO_MONEY - payment was made from a YooMoney wallet;
+* BANK_CARD - payment was made from a bank card;
+* SBERBANK - payment was made via Sberbank (text message invoicing or SberPay);
+* GOOGLE_PAY - payment was made via Google Pay.
+
+
+ Kotlin
+
+```kotlin
+class MainActivity : AppCompatActivity() {
+
+ override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+ super.onActivityResult(requestCode, resultCode, data)
+
+ if (requestCode == REQUEST_CODE_TOKENIZE) {
+ when (resultCode) {
+ RESULT_OK -> {
+ // successful tokenization
+ val result = data?.let { createTokenizationResult(it) }
+ }
+ RESULT_CANCELED -> {
+ // user canceled tokenization
+ }
+ }
+ }
+ }
+}
+```
+
+
+
+ Java
```java
public final class MainActivity extends AppCompatActivity {
- ...
-
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
@@ -303,138 +866,507 @@ public final class MainActivity extends AppCompatActivity {
}
}
```
+
-### Using the payment token
-You need to ask your YooMoney manager for permission to process payments using the token.
-A token can only be used once, it's valid for 1 hour. If you haven't created a payment within one hour, you'll need to request a new token.
+## Payment confirmation
-The payment token contains information about the [payment confirmation scenario](https://yookassa.ru/developers/payments/payment-process#user-confirmation).
-Once you receive the payment token, you'll be able to [create a payment](https://yookassa.ru/developers/api#create_payment), enter the payment token in the `payment_token` parameter.
-If the payment is processed with authentication via 3-D Secure, use `confirmation_url` receive in the [Payment](https://yookassa.ru/developers/api#payment_object) object.
-Use `confirmation_url` to run 3-D Secure, see [3DSecure](#3DSecure).
+If necessary, the system may request a payment confirmation process, where the user confirms the transaction via third-party services.
+There are two types of payment confirmation: 3Dsecure (for payments via bank card and Google Pay) and push notifications or App2App script (for payments via SberPay).
-You can also get [information about the payment](https://yookassa.ru/developers/api#get_payment)
+### SberPay
-### Test parameters and debugging
+To confirm a payment made via SberPay, you must:
+1. call the Checkout.createConfirmationIntent() method;
+2. process the received result in the onActivityResult method in Activity;
-You can add the `TestParameters` object when calling `Checkout.createTokenizeIntent()` to debug tokenization.
+Input parameters for `Checkout.createConfirmationIntent()`:
-Fields of the `TestParameters:` class
-* showLogs (Boolean): display SDK logs. All logs start with the 'YooKassa.SDK' tag
-* googlePayTestEnvironment (Boolean): use Google Pay's test environment: all transactions processed via Google Pay will use `WalletConstants.ENVIRONMENT_TEST`. Please note that if you try paying with googlePayTestEnvironment=true, you'll get a tokenization error. To learn more, see https://developers.google.com/pay/api/android/guides/test-and-deploy/integration-checklist#about-the-test-environment.
-* mockConfiguration (MockConfiguration): use a mock configuration. If this parameter is present, the SDK will work in offline mode and generate a test token. You won't be able to use this token for payments.
+Mandatory method parameters:
+- context (Context) - context of the app;
+- confirmationUrl (String) - URL for proceeding to 3DS;
+- paymentMethodType (PaymentMethodType) - selected type of payment method (the one that was received in the `createTokenizationResult()` method, (see [Getting tokenization results](#getting-tokenization-results)).
-`MockConfiguration`
-The library has a test mode where you can see how SDK works with different input data.
-This mode doesn't require Internet access. Received token can't be used for payments.
+Optional method parameters:
+- testParameters (TestParameters) - parameters for the test mode - enable logging/use mock data (see [Logging and mock mode configuration](#logging-and-mock-mode-configuration));
+- colorScheme (ColorScheme) - color scheme, (see [Interface configuration](#interface-configuration)).
-Fields of the `MockConfiguration` class:
-* completeWithError (Boolean): tokenization always returns an error;
-* paymentAuthPassed (Boolean): user is always authorized;
-* linkedCardsCount (Int): number of cards linked to user's wallet;
-* serviceFee (Amount): commission displayed in the contract;
+Possible types of results of 3DSecure initiation:
-```java
-class MyActivity extends AppCompatActivity {
+- Activity.RESULT_OK - indicates that the 3ds process is complete, but does not guarantee that it was successful. After receiving the result, we recommended requesting the payment status;
+- Activity.RESULT_CANCELED - 3ds authentication was canceled (for example, the user tapped the "back" button during the process);
+- Checkout.RESULT_ERROR - 3ds authentication failed.
- ...
+**Launching 3ds and getting the results**
- void timeToStartCheckout() {
- PaymentParameters paymentParameters = new PaymentParameters(...);
- TestParameters testParameters = new TestParameters(true, true,
- new MockConfiguration(false, true, 5, new Amount(BigDecimal.TEN, Currency.getInstance("RUB"))));
- Intent intent = Checkout.createTokenizeIntent(this, paymentParameters, testParameters);
- startActivityForResult(intent, REQUEST_CODE_TOKENIZE);
- }
-}
-```
+
+ Kotlin
-### Interface configuration
+```kotlin
+class MyActivity : AppCompatActivity() {
-You can use the`UiParameters` object for configuring the SDK interface. You can configure interface colors and if the YooMoney logo is displayed or hidden.
+ fun startConfirmSberPay() {
+ val intent = createConfirmationIntent(this, "your_app_scheme://invoicing/sberpay", PaymentMethodType.SBERBANK)
+ startActivityForResult(intent, REQUEST_CODE_CONFIRM)
+ }
-Fields of the `UiParameters` class:
-* showLogo (Boolean): show/hide the YooMoney logo on the screen with payment methods.
-* colorScheme (ColorScheme): color scheme.
+ override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+ if (requestCode == REQUEST_CODE_CONFIRM) {
+ when (resultCode) {
+ RESULT_OK -> return // 3ds process completed, no guarantee of success
+ RESULT_CANCELED -> return // The 3ds screen was closed
+ Checkout.RESULT_ERROR -> {
+ // An error occurred during 3ds (no connection or another reason)
+ // More information can be found in data
+ // data.getIntExtra(Checkout.EXTRA_ERROR_CODE) - error code from WebViewClient.ERROR_* or Checkout.ERROR_NOT_HTTPS_URL
+ // data.getStringExtra(Checkout.EXTRA_ERROR_DESCRIPTION) - error description (may be missing)
+ // data.getStringExtra(Checkout.EXTRA_ERROR_FAILING_URL) - url where the error occurred (may be missing)
+ }
+ }
+ }
+ }
+}
+```
+
-Fields of the `ColorScheme` class:
-* primaryColor (ColorInt): main color of the app. This color will be used for buttons, switches, input fields, etc.
-We don't recommend choosing very bright colors (they won't be seen with a white backgroung) or red (it'll interfere with the color of error messages).
+
+ Java
```java
class MyActivity extends AppCompatActivity {
- ...
+ void startConfirmSberPay() {
+ Intent intent = Checkout.createConfirmationIntent(this, "your_app_scheme://invoicing/sberpay", PaymentMethodType.SBERBANK);
+ startActivityForResult(intent, REQUEST_CODE_CONFIRM);
+ }
- void timeToStartCheckout() {
- PaymentParameters paymentParameters = new PaymentParameters(...);
- UiParameters uiParameters = new UiParameters(true, new ColorScheme(Color.rgb(0, 114, 245)));
- Intent intent = Checkout.createTokenizeIntent(this, paymentParameters, new TestParameters(), uiParameters);
- startActivityForResult(intent, REQUEST_CODE_TOKENIZE);
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (requestCode == REQUEST_CODE_CONFIRM) {
+ switch (resultCode) {
+ case RESULT_OK:
+ // 3ds process completed
+ // No guarantee of success
+ break;
+ case RESULT_CANCELED:
+ // The 3ds screen was closed
+ break;
+ case Checkout.RESULT_ERROR:
+ // An error occurred during 3ds (no connection or another reason)
+ // More information can be found in data
+ // data.getIntExtra(Checkout.EXTRA_ERROR_CODE) - error code from WebViewClient.ERROR_* or Checkout.ERROR_NOT_HTTPS_URL
+ // data.getStringExtra(Checkout.EXTRA_ERROR_DESCRIPTION) - error description (may be missing)
+ // data.getStringExtra(Checkout.EXTRA_ERROR_FAILING_URL) - url where the error occurred (may be missing)
+ break;
+ }
+ }
}
}
```
+
-## 3DSecure
+### 3DSecure
-The SDK contains an Activity for processing 3DS to simplify the integration of payments via bank cards.
-Don't specify PaymentParameters.customReturnUrl when calling Checkout.createTokenizeIntent(), if you use this Activity.
+To conduct 3DSecure for a payment made via a bank card, you can use Activity provided by the mSdk library:
+1. during the tokenization process, don't specify the `customReturnUrl` parameter in the `createTokenizeIntent` method (see [Launching tokenization via a bank card](#launching-tokenization-via-a-bank-card));
+2. call the Checkout.createConfirmationIntent() method;
+3. process the received result in the onActivityResult method in Activity;
Input parameters for `Checkout.createConfirmationIntent()`:
-* context (Context): context for creating `Intent`;
-* url (String): URL for redirect to 3DS.
-* paymentMethodType (PaymentMethodType): selected payment method type.
-* colorScheme (ColorScheme): color scheme.
-You can receive 3ds results in `onActivityResult()`
+Mandatory method parameters:
+- context (Context) - context of the app;
+- confirmationUrl (String) - URL for proceeding to 3DS;
+- paymentMethodType (PaymentMethodType) - selected type of payment method (the one that was received in the `createTokenizationResult()` method, (see [Getting tokenization results](#getting-tokenization-results)).
+
+Optional method parameters:
+- testParameters (TestParameters) - parameters for the test mode - enable logging/use mock data (see [Logging and mock mode configuration](#logging-and-mock-mode-configuration));
+- colorScheme (ColorScheme) - color scheme, (see [Interface configuration](#interface-configuration)).
+
+Possible types of results of 3DSecure initiation:
+
+- Activity.RESULT_OK - indicates that the 3ds process is complete, but does not guarantee that it was successful. After receiving the result, we recommended requesting the payment status;
+- Activity.RESULT_CANCELED - 3ds authentication was canceled (for example, the user tapped the "back" button during the process);
+- Checkout.RESULT_ERROR - 3ds authentication failed.
+
+**Launching 3ds and getting the results**
+
+
+ Kotlin
+
+```kotlin
+class MyActivity : AppCompatActivity() {
+
+ fun start3DSecure() {
+ val intent = createConfirmationIntent(this, "https://3dsurl.com/", PaymentMethodType.BANK_CARD)
+ startActivityForResult(intent, REQUEST_CODE_CONFIRM)
+ }
+
+ override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+ if (requestCode == REQUEST_CODE_CONFIRM) {
+ when (resultCode) {
+ RESULT_OK -> return // 3ds process completed, no guarantee of success
+ RESULT_CANCELED -> return // The 3ds screen was closed
+ Checkout.RESULT_ERROR -> {
+ // An error occurred during 3ds (no connection or another reason)
+ // More information can be found in data
+ // data.getIntExtra(Checkout.EXTRA_ERROR_CODE) - error code from WebViewClient.ERROR_* or Checkout.ERROR_NOT_HTTPS_URL
+ // data.getStringExtra(Checkout.EXTRA_ERROR_DESCRIPTION) - error description (may be missing)
+ // data.getStringExtra(Checkout.EXTRA_ERROR_FAILING_URL) - url where the error occurred (may be missing)
+ }
+ }
+ }
+ }
+}
+```
+
-Possible result types:
-* Activity.RESULT_OK: notifies that the 3ds process is finished but doesn't guarantee that it was successful. We recommend requesting the payment status after receiving the result;
-* Activity.RESULT_CANCELED: 3ds process has been canceled (for example, if the user tapped the "back" button during the process);
-* Checkout.RESULT_ERROR: couldn't complete 3ds.
+
+ Java
-**Launching 3ds and getting results**
```java
class MyActivity extends AppCompatActivity {
- void timeToStart3DS() {
- Intent intent = Checkout.createConfirmationIntent(
- this,
- "https://3dsurl.com/",
- PaymentMethodType.BANK_CARD
- );
- startActivityForResult(intent, 1);
+ void start3DSecure() {
+ Intent intent = Checkout.createConfirmationIntent(this, "https://3dsurl.com/", PaymentMethodType.BANK_CARD);
+ startActivityForResult(intent, REQUEST_CODE_CONFIRM);
}
-
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- if (requestCode == 1) {
+ if (requestCode == REQUEST_CODE_CONFIRM) {
switch (resultCode) {
case RESULT_OK:
- // 3ds process finished
+ // 3ds process completed
+ // No guarantee of success
break;
case RESULT_CANCELED:
- // 3ds screen has been closed
+ // The 3ds screen was closed
break;
case Checkout.RESULT_ERROR:
- // an error occurred during 3ds (for example, no connection)
- // you can learn more in data
- // data.getIntExtra(Checkout.EXTRA_ERROR_CODE): error code from WebViewClient.ERROR_* or Checkout.ERROR_NOT_HTTPS_URL
- // data.getStringExtra(Checkout.EXTRA_ERROR_DESCRIPTION): error description (it can be empty)
- // data.getStringExtra(Checkout.EXTRA_ERROR_FAILING_URL): url where the error occurred (it can be empty)
+ // An error occurred during 3ds (no connection or another reason)
+ // More information can be found in data
+ // data.getIntExtra(Checkout.EXTRA_ERROR_CODE) - error code from WebViewClient.ERROR_* or Checkout.ERROR_NOT_HTTPS_URL
+ // data.getStringExtra(Checkout.EXTRA_ERROR_DESCRIPTION) - error description (may be missing)
+ // data.getStringExtra(Checkout.EXTRA_ERROR_FAILING_URL) - url where the error occurred (may be missing)
break;
}
}
}
}
```
+
+
+## Linked card
+
+Specify the optional parameter `customerId` in the method for tokenization (see [Launching tokenization via a bank card](#launching-tokenization-via-a-bank-card)) so that after the tokenization with a bank card, this bank card would be successfully linked and displayed in the list of payment methods available to the user. The card is linked only when the user consents to its linking.
+- customerId (String) - unique ID of the customer in your system, such as email addres or phone number. Limit by length: no more than 200 characters.
+ **Make sure the customerId corresponds to the user who wants to make a purchase. For example, use two-factor authentication. If you specify an incorrect ID, the user will be able to select other people's bank cards for payment.**
+
+Therefore, the method for carrying out the tokenization of a bank card with the subsequent linking of this bank card is as follows:
+
+
+ Kotlin
+
+```kotlin
+class MyActivity : AppCompatActivity() {
+
+ fun startLinkedBankCardTokenize() {
+ val paymentParameters = PaymentParameters(
+ amount = Amount(BigDecimal.TEN, Currency.getInstance("RUB")),
+ title = "Product name",
+ subtitle = "Product description",
+ clientApplicationKey = "live_thisKeyIsNotReal", // key for client apps from the YooMoney Merchant Profile (https://yookassa.ru/my/api-keys-settings)
+ shopId = "12345", // ID of the store in the YooMoney system
+ savePaymentMethod = SavePaymentMethod.OFF, // flag of the disabled option to save payment methods,
+ paymentMethodTypes = setOf(PaymentMethodType.BANK_CARD), // selected payment method: bank card,
+ customerId = "uniqueCustomerId" // unique ID of the customer in your system
+ )
+ val intent = createTokenizeIntent(this, paymentParameters)
+ startActivityForResult(intent, REQUEST_CODE_TOKENIZE)
+ }
+}
+```
+
+
+
+ Java
+
+```java
+class MyActivity extends AppCompatActivity {
+
+ void startLinkedBankCardTokenize() {
+ Set paymentMethodTypes = new HashSet<>();
+ PaymentParameters paymentParameters = new PaymentParameters(
+ new Amount(BigDecimal.TEN, Currency.getInstance("RUB")),
+ "Product name",
+ "Product description",
+ "live_thisKeyIsNotReal", // key for client apps from the YooMoney Merchant Profile (https://yookassa.ru/my/api-keys-settings)
+ "12345", // ID of the store in the YooMoney system
+ SavePaymentMethod.OFF, // flag of the disabled option to save payment methods
+ paymentMethodTypes.add(PaymentMethodType.BANK_CARD), // selected payment method: bank card
+ "gatewayId", // gatewayId of the store for Google Pay payments (required if payment methods include Google Pay)
+ "https://custom.redirect.url", // url of the page (only https is supported) that the user should be returned to after completing 3ds. Must be used only when own Activity for the 3ds url is used.
+ "+79041234567", // user's phone number for autofilling the user phone number field in SberPay. Supported data format: "+7XXXXXXXXXX"
+ null, // settings for tokenization via GooglePay,
+ "example_authCenterClientId", // ID received upon registering the app on the https://yookassa.ru website
+ "uniqueCustomerId" // unique ID of the customer in your system
+ );
+ Intent intent = Checkout.createTokenizeIntent(this, paymentParameters);
+ startActivityForResult(intent, REQUEST_CODE_TOKENIZE);
+ }
+}
+```
+
+
+You can use the test mode to see how the linked card will look on the screen with the list of payment methods.
+You must set the number of cards in the `linkedCardsCount` parameter of the `MockConfiguration` object and call the `createTokenizeIntent` method. Learn more in the [Logging and mock mode configuration](#logging-and-mock-mode-configuration) section
+
+## Recurring payments
+
+Recurring payments are payments that are repeated in accordance with a specific schedule. Debits for such payments are made automatically after the consent of the user.
+
+You can save some payment methods and use them for recurring payments. In this case, the user needs to confirm only the first payment, and subsequent debits will be unconditional. [You can learn more here](https://yookassa.ru/developers/payments/recurring-payments)
+
+To enable autopayments, specify one of the following values to the `savePaymentMethod` parameter during the [tokenization](#tokenization) process:
+- `SavePaymentMethod.ON` - save the payment method for recurring payments. Only payment methods that support saving will be available to the user. During the first payment, a notification stating that the payment method will be saved will appear on the screen of the selected payment method.
+ ![SavePaymentMethod.ON](assets/images/recurrent-payments/save-payment-method-on.png)
+- `SavePaymentMethod.USER_SELECTS` - the user chooses whether or not to save the payment method. If the method can be saved, a toggle will appear on the selected payment method screen.
+ ![SavePaymentMethod.USER_SELECTS](assets/images/recurrent-payments/save-payment-method-user-selects.png)
+
+
+ Kotlin
+
+```kotlin
+class MyActivity : AppCompatActivity() {
+
+ fun startTokenize() {
+ val paymentParameters = PaymentParameters(
+ amount = Amount(BigDecimal.TEN, Currency.getInstance("RUB")),
+ title = "Product name",
+ subtitle = "Product description",
+ clientApplicationKey = "live_thisKeyIsNotReal", // key for client apps from the YooMoney Merchant Profile (https://yookassa.ru/my/api-keys-settings)
+ shopId = "12345", // ID of the store in the YooMoney system
+ savePaymentMethod = SavePaymentMethod.ON, // flag of the disabled option to save payment methods
+ authCenterClientId = "example_authCenterClientId", // ID received upon registering the app on the https://yookassa.ru website
+ gatewayId = "gatewayId", // gatewayId of the store for Google Pay payments (required if payment methods include Google Pay)
+ customReturnUrl = "https://custom.redirect.url", // url of the page (only https is supported) that the user should be returned to after completing 3ds. Must be used only when own Activity for the 3ds url is used.
+ userPhoneNumber = "+79041234567", // user's phone number for autofilling the user phone number field in SberPay. Supported data format: "+7XXXXXXXXXX".
+ )
+ val intent = createTokenizeIntent(this, paymentParameters)
+ startActivityForResult(intent, REQUEST_CODE_TOKENIZE)
+ }
+}
+```
+
+
+
+ Java
+
+```java
+class MyActivity extends AppCompatActivity {
+
+ void startTokenize() {
+ PaymentParameters paymentParameters = new PaymentParameters(
+ new Amount(BigDecimal.TEN, Currency.getInstance("RUB")),
+ "Product name",
+ "Product description",
+ "live_thisKeyIsNotReal", // key for client apps from the YooMoney Merchant Profile
+ "12345", // ID of the store in the YooMoney system
+ SavePaymentMethod.ON, // flag of the disabled option to save payment methods
+ null, // the full list of available payment methods has been provided
+ "gatewayId", // gatewayId of the store for Google Pay payments (required if payment methods include Google Pay)
+ "https://custom.redirect.url", // url of the page (only https is supported) that the user should be returned to after completing 3ds. Must be used only when own Activity for the 3ds url is used.
+ "+79041234567", // user's phone number for autofilling the user phone number field in SberPay. Supported data format: "+7XXXXXXXXXX"
+ null, // settings for tokenization via GooglePay,
+ "example_authCenterClientId" // ID received upon registering the app on the https://yookassa.ru website
+ );
+ Intent intent = Checkout.createTokenizeIntent(this, paymentParameters);
+ startActivityForResult(intent, REQUEST_CODE_TOKENIZE);
+ }
+}
+```
+
-## Scanning bank cards
+> After receiving the token for a recurring payment, make the payment and [follow the instructions](https://yookassa.ru/developers/payments/recurring-payments#process)
-Create an `Activity` which processes action `ru.yoomoney.sdk.kassa.payments.action.SCAN_BANK_CARD`
+## Logging and mock mode configuration
-***Implementing the activity for scanning***
+#### Logging enabling
+
+You may need to include logs in the sdk for the purposes of debugging. To do that, specify the `showLogs = true` parameter in `TestParameters` when launching tokenization
+
+
+ Kotlin
+
+```kotlin
+class MyActivity : AppCompatActivity() {
+
+ fun startTokenize() {
+ val testParameters = TestParameters(
+ showLogs = true // showLogs - enable/disable display of sdk logs
+ )
+ val intent = createTokenizeIntent(this, paymentParameters, testParameters)
+ startActivityForResult(intent, REQUEST_CODE_TOKENIZE)
+ }
+}
+```
+
+
+
+ Java
+
+```java
+class MyActivity extends AppCompatActivity {
+
+ void startTokenize() {
+ TestParameters testParameters = new TestParameters(
+ true // showLogs - enable/disable display of sdk logs
+ );
+ Intent intent = Checkout.createTokenizeIntent(this, paymentParameters, testParameters);
+ startActivityForResult(intent, REQUEST_CODE_TOKENIZE);
+ }
+}
+```
+
+
+> Please note that the logs will only be displayed in the debug app. Do not specify this flag for the release build of the app.
+
+#### Mock mode configuration
+
+The library has a mock mode which you can use to see what the SDK would look like with various inputs. This mode does not require Internet access. The received token can't be used for payment.
+
+`MockConfiguration` class fields:
+- `completeWithError` (Boolean) - tokenization always returns an error;
+- `paymentAuthPassed` (Boolean) - whether the user is authorized to pay with a wallet or not;
+- `linkedCardsCount` (Int) - number of cards linked to the user's wallet;
+- `serviceFee` (Amount) - commission that will be displayed on the screen of the selected payment method;
+
+To run tokenization in mock mode, specify the `mockConfiguration` parameter in `TestParameters`
+
+
+ Kotlin
+
+```kotlin
+class MyActivity : AppCompatActivity() {
+
+ fun startTokenize() {
+ val testParameters = TestParameters(
+ showLogs = true, // showLogs - enable/disable display of SDK logs
+ googlePayTestEnvironment = true, // googlePayTestEnvironment - what type of environment should be used for Google Pay, test or production. Learn more at https://developers.google.com/pay/api/android/guides/test-and-deploy/integration-checklist
+ mockConfiguration = MockConfiguration(
+ completeWithError = true, // completeWithError - always return an error during tokenization
+ paymentAuthPassed = true, // paymentAuthPassed - whether the user is authorized to pay with a wallet or not
+ linkedCardsCount = 3, // linkedCardsCount - number of cards linked to the user's wallet;
+ serviceFee = Amount(BigDecimal.ONE, Currency.getInstance("RUB")) // serviceFee - commission that will be displayed on the screen of the selected payment method
+ )
+ )
+ val intent = createTokenizeIntent(this, paymentParameters, testParameters)
+ startActivityForResult(intent, REQUEST_CODE_TOKENIZE)
+ }
+}
+```
+
+
+
+ Java
+
+```java
+class MyActivity extends AppCompatActivity {
+
+ void startTokenize() {
+ MockConfiguration mockConfiguration = new MockConfiguration(
+ true, // completeWithError - always return an error during tokenization
+ true, // paymentAuthPassed - whether the user is authorized to pay with a wallet or not
+ 3,// linkedCardsCount - number of cards linked to the user's wallet;
+ new Amount(BigDecimal.ONE, Currency.getInstance("RUB")) // serviceFee - commission that will be displayed on the screen of the selected payment method
+ );
+ TestParameters testParameters = new TestParameters(
+ true, // showLogs - enable/disable display of SDK logs
+ true, // googlePayTestEnvironment - what type of environment should be used for Google Pay, test or production. Learn more at https://developers.google.com/pay/api/android/guides/test-and-deploy/integration-checklist
+ mockConfiguration
+ );
+ Intent intent = Checkout.createTokenizeIntent(this, paymentParameters, testParameters);
+ startActivityForResult(intent, REQUEST_CODE_TOKENIZE);
+ }
+}
+```
+
+
+## Interface configuration
+
+To customize the SDK interface, you can use the `UiParameters` object, namely set the main color of the interface and configure the display of the YooMoney logo on the screen with the list of payment methods (hide or show).
+
+`UiParameters` class fields:
+* showLogo (Boolean) - show or hide the YooMoney logo on the screen with the list of payment methods;
+* colorScheme (ColorScheme) - mSdk color scheme in your app.
+
+`ColorScheme` class fields:
+* primaryColor (ColorInt) - the main color of the app. Buttons, switches, input fields, etc. will be switched to this color.
+ We don't recommend making this color too light if your theme is already designed with light colors, as it won't be visible on a white background, or choose a dark color for a dark theme, since it won't be visible either. We also don't recommend using red as it might mix up with color of error messages.
+
+ | With icon | Without icon |
+ | ------------- |:------------------:|
+ | ![List of payments with icon](assets/images/custom_ui_parameters_examples/1_show_logo_true.png) | ![List of payments without icon](assets/images/custom_ui_parameters_examples/2_show_logo_false.png) |
+
+ | Correct custom color | Incorrect custom color |
+ | ------------- |:------------------:|
+ | ![Correct color](assets/images/custom_ui_parameters_examples/3_good_color_example.png) | ![Incorrect color](assets/images/custom_ui_parameters_examples/4_bad_color_example.png) |
+
+
+ Kotlin
+
+ ```kotlin
+ class MyActivity : AppCompatActivity() {
+
+ fun tokenizeCustomUiParameters() {
+ val paymentParameters = PaymentParameters(...)
+ val uiParameters = UiParameters(
+ showLogo = true,
+ colorScheme = ColorScheme(Color.rgb(0, 114, 245))
+ ) // specify the true flag so that the YooMoney logo is displayed on the screen with the list of payment methods and specify the ColorScheme that contains the custom color
+ val intent = createTokenizeIntent(
+ context = this,
+ paymentParameters = paymentParameters,
+ uiParameters = uiParameters
+ )
+ startActivityForResult(intent, REQUEST_CODE_TOKENIZE)
+ }
+ }
+ ```
+
+
+
+ Java
+
+ ```java
+ class MyActivity extends AppCompatActivity {
+
+ void tokenizeCustomUiParameters() {
+ PaymentParameters paymentParameters = new PaymentParameters(...);
+ UiParameters uiParameters = new UiParameters(true, new ColorScheme(Color.rgb(0, 114, 245))); // specify the true flag so that the YooMoney logo is displayed on the screen with the list of payment methods and specify the ColorScheme that contains the custom color
+ Intent intent = Checkout.createTokenizeIntent(
+ this,
+ paymentParameters,
+ null, // parameters for the test mode - enable logging/use mock data
+ uiParameters
+ );
+ startActivityForResult(intent, REQUEST_CODE_TOKENIZE);
+ }
+ }
+
+ ```
+
+
+## Scanning a bank card
+
+The sdk includes the option to connect a library for scanning bank cards with a camera. If you enable scanning, a special button will appear on the bank card number entry form ![Card scanning icon](assets/images/scan-bank-card/icon-scanner.png):
+
+![Bank card details entry screen](assets/images/scan-bank-card/bank-card-form-with-scan.png)
+
+When the user taps this button, the sdk will launch `intent` to launch `activity` that implements card scanning.
+>Bank card scanning is not implemented in the sdk itself, the scanning is proposed to be implemented in `activity` via a third-party library instead.
+
+To do that, create `activity` that will handle the `ru.yoomoney.sdk.kassa.payments.action.SCAN_BANK_CARD` action, then register this `activity` in `AndroidManifest.xml`, specifying `intent-filter` for the `ru.yoomoney.sdk.kassa.payments.action.SCAN_BANK_CARD` action:
```xml
@@ -445,29 +1377,177 @@ Create an `Activity` which processes action `ru.yoomoney.sdk.kassa.payments.acti
```
-Launch your library for scanning cards in this `Activity`.
-Enter the card number you received using `Intent` as shown in the example below.
-Don't forget to specify `Activity.RESULT_OK` if the card was scanned successfully.
+Now when you tap the card scanning button ![Card scanning icon](assets/images/scan-bank-card/icon-scanner.png), your `activity` will be launched where you will need to implement the card scanning, then complete `activity` and specify the resuls using the `setResult` method.
+
+To do that, before completing `activity`, call the `Checkout.createScanBankCardResult` method and specify the card number and optional month/year parameters, and send it to the `setResult` method. Then call the `finish()` method
+
+
+ Kotlin
-***Returning the result with activity***
+```kotlin
+class ScanBankCardActivity : Activity() {
+
+ private fun onScanningDone(cardNumber: String, expirationMonth: Int, expirationYear: Int) {
+ val result: Intent = Checkout.createScanBankCardResult(cardNumber, expirationMonth, expirationYear)
+ setResult(RESULT_OK, result)
+ finish()
+ }
+}
+```
+
+
+
+ Java
+
+Java:
```java
-public class ScanBankCardActivity extends Activity {
+class ScanBankCardActivity extends Activity {
private void onScanningDone(final String cardNumber, final int expirationMonth, final int expirationYear) {
-
final Intent result = Checkout.createScanBankCardResult(cardNumber, expirationMonth, expirationYear);
-
setResult(Activity.RESULT_OK, result);
-
finish();
+ }
+}
+```
+
+
+#### Example of `activity` implementation for scanning bank card details
+Below you can find the example of bank card data scanning implemented via the third-party library card.io: https://github.com/card-io/card.io-Android-SDK
+You can use any other library or solution that suits you.
+
+
+ Kotlin
+```kotlin
+class ScanBankCardActivity : Activity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ ActivityCompat.requestPermissions(this, arrayOf(permission.CAMERA), REQUEST_CODE)
+ }
+
+ override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults)
+ if (requestCode == REQUEST_CODE) {
+ if (grantResults[0] == PackageManager.PERMISSION_DENIED
+ && !ActivityCompat.shouldShowRequestPermissionRationale(this, permission.CAMERA)
+ ) {
+ Toast.makeText(
+ this,
+ "Give permisson to use the camera in the settings",
+ Toast.LENGTH_SHORT
+ ).show()
+ finish()
+ } else {
+ val scanIntent = Intent(this, CardIOActivity::class.java)
+ scanIntent.putExtra(CardIOActivity.EXTRA_REQUIRE_EXPIRY, true)
+ startActivityForResult(scanIntent, REQUEST_CODE)
+ }
+ }
}
+ override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+ super.onActivityResult(requestCode, resultCode, data)
+ if (requestCode == REQUEST_CODE) {
+ if (data != null && data.hasExtra(CardIOActivity.EXTRA_SCAN_RESULT)) {
+ val scanResult: CreditCard = requireNotNull(data.getParcelableExtra(CardIOActivity.EXTRA_SCAN_RESULT))
+ val cardNumber = scanResult.formattedCardNumber
+ if (scanResult.isExpiryValid && scanResult.redactedCardNumber != null
+ && scanResult.redactedCardNumber.isNotEmpty()
+ ) {
+ val scanBankCardResult = createScanBankCardIntent(
+ cardNumber,
+ scanResult.expiryMonth,
+ scanResult.expiryYear % 100
+ )
+ setResult(RESULT_OK, scanBankCardResult)
+ } else {
+ setResult(RESULT_CANCELED)
+ }
+ } else {
+ setResult(RESULT_CANCELED)
+ }
+ finish()
+ }
+ }
+
+ companion object {
+ const val REQUEST_CODE = 1
+ }
+}
+```
+
+
+
+ Java
+
+```java
+public class ScanBankCardActivity extends AppCompatActivity {
+
+ public static final int REQUEST_CODE = 1;
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ ActivityCompat.requestPermissions(this, new String[]{ CAMERA }, REQUEST_CODE);
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+
+ if (requestCode == REQUEST_CODE) {
+ if (grantResults[0] == PackageManager.PERMISSION_DENIED
+ && !ActivityCompat.shouldShowRequestPermissionRationale(this, CAMERA)
+ ) {
+ Toast.makeText(
+ this,
+ "Give permisson to use the camera in the settings",
+ Toast.LENGTH_SHORT
+ ).show();
+
+ finish();
+ } else {
+ Intent scanIntent = new Intent(this, CardIOActivity.class);
+ scanIntent.putExtra(CardIOActivity.EXTRA_REQUIRE_EXPIRY, true);
+ startActivityForResult(scanIntent, REQUEST_CODE);
+ }
+ }
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ if (requestCode == REQUEST_CODE) {
+ if (data != null && data.hasExtra(CardIOActivity.EXTRA_SCAN_RESULT)) {
+ CreditCard scanResult = data.getParcelableExtra(CardIOActivity.EXTRA_SCAN_RESULT);
+ final String cardNumber = scanResult.getFormattedCardNumber();
+
+ if (scanResult.isExpiryValid() && scanResult.getRedactedCardNumber() != null &&
+ !scanResult.getRedactedCardNumber().isEmpty()) {
+ final Intent scanBankCardResult = Checkout.createScanBankCardIntent(
+ cardNumber,
+ scanResult.expiryMonth,
+ scanResult.expiryYear % 100
+ );
+ setResult(RESULT_OK, scanBankCardResult);
+ } else {
+ setResult(RESULT_CANCELED);
+ }
+ } else {
+ setResult(RESULT_CANCELED);
+ }
+ finish();
+ }
+ }
}
```
+
# Useful links
-* [YooMoney website](https://yookassa.ru/en)
-* [Documentation for mobile SDKs on the YooMoney website](https://yookassa.ru/docs/client-sdks/#mobil-nye-sdk)
-* [Demo app in Google Play](https://play.google.com/store/apps/details?id=ru.yoo.sdk.kassa.payments.example.release)
-* [SDK for iOS](https://github.com/yoomoney/yookassa-payments-swift)
\ No newline at end of file
+* [YooMoney website](https://yookassa.ru)
+* [Mobile SDK documentation on the YooMoney website](https://yookassa.ru/docs/client-sdks/#mobil-nye-sdk)
+* [Google Play demo app](https://play.google.com/store/apps/details?id=ru.yoo.sdk.kassa.payments.example.release)
+* [SDKs for iOS](https://github.com/yoomoney/yookassa-payments-swift)
diff --git a/README_RU.md b/README_RU.md
old mode 100755
new mode 100644
index db1b32c..84fd5a7
--- a/README_RU.md
+++ b/README_RU.md
@@ -4,15 +4,24 @@
[![GitHub tag](https://img.shields.io/github/v/tag/yoomoney/yookassa-android-sdk.svg?sort=semver)](https://img.shields.io/github/v/tag/yoomoney/yookassa-android-sdk.svg?sort=semver)
[![License](https://img.shields.io/github/license/yoomoney/yookassa-android-sdk.svg)](https://img.shields.io/github/license/yoomoney/yookassa-android-sdk.svg)
-Эта библиотека позволяет встроить прием платежей в мобильные приложения на Android.
-Она работает как дополнение к API ЮKassa.
+Данное SDK позволяет проводить платежи с использованием платёжного токена.
+
+Общий процесс оплаты в мобильном приложении выглядит следующим образом:
+1. Вы запускаете процесс [токенизации в SDK](#токенизация);
+ - пользователю отображается список возможных методов оплаты;
+ - пользователь выбирает способ оплаты, вводит необходимые данные;
+ - если данные введены верно и процесс токензизации завершился успешно, то SDK обменивает данные, которые ввел пользователь, на платежный токен `payment_token` и возвращает в ваше приложение этот `payment_token` ([Получить результат токенизации](#получить-результат-токенизации)).
+2. Из данного платежного токена необходимо создать платеж с помощью [метода API](https://yookassa.ru/developers/api#create_payment). Таким образом, **SDK работает как дополнение к [API ЮKassa](https://yookassa.ru/developers/payments/sdk-tokens)**
+3. При необходимости запускаете в SDK процесс [подтверждения платежа](#подтверждение-платежа) с помощью 3DS или SberPay.
+
+**Диаграмма процесса токенизации и проведения платежа:**
+
+![Диаграмма](assets/images/diagrams/base_flow_diagram.png)
В SDK входят готовые платежные интерфейсы (форма оплаты и всё, что с ней связано).
С помощью SDK можно получать токены для проведения оплаты с банковской карты, Google Pay, Сбербанка или из кошелька в ЮMoney.
-Минимально поддерживаемая версия android sdk: 21(Android 5).
-
В этом репозитории лежит код SDK и пример приложения, которое его интегрирует.
* [Код библиотеки](./library)
* [Код демо-приложения, которое интегрирует SDK](./sample)
@@ -24,20 +33,29 @@ Android Checkout mobile SDK - версия $versionName ([changelog](https://git
* [Changelog](#changelog)
* [Migration guide](#migration-guide)
-* [Регистрация приложения для платежей из кошелька](#регистрация-приложения-для-платежей-из-кошелька)
-* [Подключение зависимостей](#подключение-зависимостей)
- * [Подключение через Gradle](#подключение-через-Gradle)
- * [Подключение sdk авторизации для платежей из кошелька](#подключение-sdk-авторизации-для-платежей-из-кошелька)
+* [Подключение через Gradle](#подключение-через-Gradle)
+* [Рекомендации по интеграции](#рекомендации-по-интеграции)
* [Настройка приложения при продаже цифровых товаров](#настройка-приложения-при-продаже-цифровых-товаров)
+ * [Рекомендуемые совместимые версии](#реекомендуемые-совместимые-версии)
* [Использование библиотеки](#использование-библиотеки)
* [Токенизация](#токенизация)
- * [Запуск токенизации](#запуск-токенизации)
+ * [Запуск токенизации всеми методами](#запуск-токенизации-всеми-методами)
+ * [Запуск токенизации кошельком ЮMoney](#запуск-токенизации-кошельком-ЮMoney)
+ * [Запуск токенизации SberPay](#запуск-токенизации-SberPay)
+ * [Запуск токенизации банковской картой](#запуск-токенизации-банковской-картой)
+ * [Подготовка к запуску токенизации Google Pay](#подготовка-к-запуску-токенизации-Google-Pay)
+ * [Запуск токенизации Google Pay](#запуск-токенизации-Google-Pay)
* [Запуск токенизации для сохранённых банковских карт](#запуск-токенизации-для-сохранённых-банковских-карт)
- * [Получение результата токенизации](#получение-результата-токенизации)
- * [Использование платежного токена](#использование-платежного-токена)
- * [Тестовые параметры и отладка](#тестовые-параметры-и-отладка)
- * [Настройка интерфейса](#настройка-интерфейса)
- * [3DSecure](#3dsecure)
+ * [Получить результат токенизации](#получить-результат-токенизации)
+ * [Подтверждение платежа](#подтверждение-платежа)
+ * [SberPay](#sberpay)
+ * [3DSecure](#3dsecure)
+ * [Привязанная карта](#привязанная-карта)
+ * [Рекуррентные платежи](#рекуррентные-платежи)
+ * [Настройка логирования и mock режима](#настройка-логирования-и-mock-режима)
+ * [Настройка интерфейса](#настройка-интерфейса)
+ * [Включение логирования](#включение-логирования)
+ * [Настройка mock режима](#настройка-mock-режима)
* [Сканирование банковской карты](#сканирование-банковской-карты)
* [Полезные ссылки](#полезные-ссылки)
@@ -49,28 +67,8 @@ Android Checkout mobile SDK - версия $versionName ([changelog](https://git
[Ссылка на Migration guide](https://github.com/yoomoney/yookassa-android-sdk/blob/master/MIGRATION.md)
-# Регистрация приложения для платежей из кошелька
-> Если среди платёжных методов есть кошелёк ЮMoney, необходимо зарегистрировать приложение и получить `authCenterClientId`.
-В остальных случаях этот шаг можно пропустить.
-
-Если вы ранее уже регистрировали приложение для **oAuth-авторизации**, то список ваших приложений можно найти на странице https://yookassa.ru/oauth/v2/client
-Если вы ещё не регистрировали приложение для **oAuth-авторизации**, то нужно выполнить следующие инструкции.
-1. Для регистрации нового приложения необходимо авторизоваться на сайте https://yookassa.ru
-2. После авторизации перейдите на страницу регистрации приложения – https://yookassa.ru/oauth/v2/client
-3. Нажмите на кнопку создать приложение и задайте значение параметрам:
- * Название;
- * Описание. По желанию;
- * Ссылка на сайт;
- * Сallback URL – любой, можно указать ссылку на сайт;
- * Доступы. Тут есть три раздела `API ЮKassa`, `Кошелёк ЮMoney`, `Профиль ЮMoney`.
- * В разделе `Кошелёк ЮMoney` выдайте разрешение на чтение баланса кошелька пользователя. Для этого в разделе **БАЛАНС КОШЕЛЬКА** поставьте галку на против поля **Просмотр**;
- * Откройте раздел `Профиль ЮMoney` и выдайте разрешение на чтение телефона, почты, имени и аватара пользователя. Для этого в разделе **ТЕЛЕФОН, ПОЧТА, ИМЯ И АВАТАР ПОЛЬЗОВАТЕЛЯ** поставьте галку на против поля **Просмотр**;
-3. Нажмите на кнопку "Зарегистрировать" и завершите регистрацию;
-4. В открывшемся окне появится информация о зарегистрированном приложении. Вам понадобится `authCenterClientId` для запуска токенизации см. [(Запуск токенизации)](#запуск-токенизации);
-
-# Подключение зависимостей
+# Подключение через Gradle
-## Подключение через Gradle
Для подключения библиотеки пропишите зависимости в build.gradle модуля:
```groovy
@@ -79,38 +77,33 @@ repositories {
}
dependencies {
- implementation 'ru.yoomoney.sdk.kassa.payments:yookassa-android-sdk:$versionName'
+ implementation 'ru.yoomoney.sdk.kassa.payments:yookassa-android-sdk:6.5.0'
}
```
-Попросите у менеджера по подключению библиотеку `ThreatMetrix Android SDK 6.2-97.aar`.
-Создайте папку libs в модуле где подключаете sdk и добавьте туда файл `ThreatMetrix Android SDK 6.2-97.aar`. В build.gradle того же модуля в dependencies добавьте:
+Также необходимо подключить kotlin plugin. Для этого нужно добавить в файл build.gradle root каталога следующий блок кода:
+
```groovy
-dependencies {
- implementation fileTree(dir: "libs", include: ["*.aar"])
+buildscript {
+ dependencies {
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.31"
+ }
}
```
-## Настройка схемы приложениия
-Для работы sdk нужно настроить схему вашего приложения для обработки deeplink. Это необходимо сделать для оплаты через sberpay.
-Нужно добавить в ваш файл build.gradle в блок android.defaultConfig строку `resValue "string", "ym_app_scheme", "your_unique_app_shceme"`
-```
-android {
- defaultConfig {
- resValue "string", "ym_app_scheme", "your_unique_app_shceme"
- }
+В app модуль добавить в файл build.gradle:
+
+```groovy
+plugin {
+ id 'kotlin-android'
}
+
```
-Или добавить в ваш strings.xml строку вида:
-```
-
- your_unique_app_shceme
-
-```
-Где your_unique_app_shceme - это уникальное название вашего приложения, если вы уже обрабатывете deeplink в своём приложении, то можно использовать готовую схему вашего приложения.
-Если ранее в проекте вы не обрабатывали deeplink, можно придумать уникальную схему для вашего приложения, состоящую из латинских букв.
+
+# Рекомендации по интеграции
## Настройка приложения при продаже цифровых товаров
+
Если в вашем приложении продаются цифровые товары, нужно отключить Google Pay из списка платежных опций.
Для этого добавьте в AndroidManifest следующий код:
@@ -120,418 +113,853 @@ android {
tools:node="remove" />
```
-# Использование библиотеки
-Вся работа с библиотекой происходит через обращения к классу `ru.yoomoney.sdk.kassa.payments.Checkout`
+## Рекомендуемые совместимые версии
+
+Минимально поддерживаемая версия Android SDK: 21 (Android 5.0).
+
+Для корректной работы библиотеки следует использовать в приложении:
+- Kotlin версии 1.4.32;
+- targetSdkVersion 31;
+- Версия Gradle 7.0.+.
+
+# Использование библиотеки
## Токенизация
-### Запуск токенизации
+Процесс токенизации — это обмен платёжных данных, на платёжный токен `payment_token`. Далее этот токен, используется для создания платежа [методом API](https://yookassa.ru/developers/api#create_payment)
-Для запуска процесса токенизации используется метод `Checkout.createTokenizeIntent()`. Метод отдаёт `Intent`, который нужно запустить в startActivityForResult(). После этого управление процессом перейдёт в SDK.
-Готовый платёжный токен можно получить в `onActivityResult()` (см. [Получение результата токенизации](#получение-результата-токенизации))
+Для запуска процесса токенизации используется метод `Checkout.createTokenizeIntent()`. Метод отдаёт `Intent`, который нужно запустить в `startActivityForResult()`. После этого управление процессом перейдёт в SDK.
+Готовый платёжный токен можно получить в `onActivityResult()`
-Входные параметры метода:
-* context (Context) - контекст приложения;
-* paymentParameters (PaymentParameters) - параметры платежа;
-* testParameters (TestParameters) - параметры для дебага, см. [Тестовые параметры и отладка](#тестовые-параметры-и-отладка);
-* uiParameters (UiParameters) - настройка интерфейса, см. [Настройка интерфейса](#настройка-интерфейса).
+Обязательные параметры метода:
+- context (Context) - контекст приложения;
+- paymentParameters (PaymentParameters) - параметры платежа.
+
+Опциональные параметры метода:
+- testParameters (TestParameters) - параметры для тестового режима - включить логирование/использовать mock-данные (см. [Настройка логирования и mock режима](#настройка-логирования-и-mock-режима));
+- uiParameters (UiParameters) - настройка интерфейса (см. [Настройка интерфейса](#настройка-интерфейса))
Поля `PaymentParameters`:
Обязательные:
-* amount (Amount) - стоимость товара. Допустимые способы оплаты могут меняться в зависимости от этого параметра;
-* title (String) - название товара;
-* subtitle (String) - описание товара;
-* clientApplicationKey (String) - ключ для клиентских приложений из личного кабинета ЮKassa ([раздел Настройки — Ключи API](https://yookassa.ru/my/api-keys-settings));
-* shopId (String) - идентификатор магазина в ЮKassa;
-* savePaymentMethod (SavePaymentMethod) - настройка сохранения платёжного метода. Сохранённые платёжные методы можно использовать для проведения рекуррентных платежей.
+- amount (Amount) - стоимость товара. Допустимые способы оплаты могут меняться в зависимости от этого параметра. Этот параметр отобразится на экране выбранного способа оплаты при токенизации выбранным способом оплаты;
+- title (String) - название товара. Этот параметр отобразится на экране выбранного способа оплаты при токенизации выбранным способом оплаты;
+- subtitle (String) - описание товара. Этот параметр отобразится на экране выбранного способа оплаты при токенизации выбранным способом оплаты;
+- clientApplicationKey (String) - ключ для клиентских приложений из личного кабинета ЮKassa ([раздел Настройки — Ключи API](https://yookassa.ru/my/api-keys-settings));
+- shopId (String) - идентификатор магазина в ЮKassa ([раздел Организации](https://yookassa.ru/my/company/organization) - скопировать shopId у нужного магазина);
+- savePaymentMethod (SavePaymentMethod) - настройка сохранения платёжного метода. Сохранённые платёжные методы можно использовать для проведения рекуррентных платежей, (см. [Рекуррентные платежи](#рекуррентные-платежи)).
Необязательные:
-* paymentMethodTypes (Set of PaymentMethodType) - ограничения способов оплаты. Если оставить поле пустым или передать в него null;
-библиотека будет использовать все доступные способы оплаты;
-* gatewayId (String) - gatewayId для магазина;
-* customReturnUrl (String) - url страницы (поддерживается только https), на которую надо вернуться после прохождения 3ds. Должен использоваться только при при использовании своего Activity для 3ds url. При использовании Checkout.createConfirmationIntent() или Checkout.create3dsIntent() не задавайте этот параметр;
-* userPhoneNumber (String) - номер телефона пользователя. Используется для автозаполнения поля при оплате через SberPay. Поддерживаемый формат данных: "+7XXXXXXXXXX".
-* googlePayParameters (GooglePayParameters) - настройки для оплаты через Google Pay.
+- paymentMethodTypes (Set of PaymentMethodType) - ограничения способов оплаты. Если оставить поле пустым или передать в него null, библиотека будет использовать все доступные способы оплаты, (см. [Запуск токенизации всеми методами](#запуск-токенизации-всеми-методами));
+- gatewayId (String) - gatewayId для магазина, (см. [Запуск токенизации Google Pay](#запуск-токенизации-Google-Pay));
+- customReturnUrl (String) - url страницы (поддерживается только https), на которую надо вернуться после прохождения 3ds. Должен использоваться только при при использовании своего Activity для 3ds url, (см. [3DSecure](#3dsecure));
+- userPhoneNumber (String) - номер телефона пользователя при оплате через SberPay, (см. [Запуск токенизации SberPay](#запуск-токенизации-SberPay));
+- googlePayParameters (GooglePayParameters) - настройки для оплаты через Google Pay, (см. [Запуск токенизации Google Pay](#запуск-токенизации-Google-Pay));
+- authCenterClientId (String) - уникальный идентификатор приложения для токенизации через ЮMoney. (см. [Запуск токенизации кошельком ЮMoney](#запуск-токенизации-кошельком-ЮMoney))
Поля класса `Amount`:
-* value (BigDecimal) - сумма;
-* currency (Currency) - валюта.
+- value (BigDecimal) - сумма;
+- currency (Currency) - валюта.
Значения `SavePaymentMethod`:
-* ON - Сохранить платёжный метод для проведения рекуррентных платежей. Пользователю будут доступны только способы оплаты, поддерживающие сохранение. На экране контракта будет отображено сообщение о том, что платёжный метод будет сохранён.
-* OFF - Не сохранять платёжный метод.
-* USER_SELECTS - Пользователь выбирает, сохранять платёжный метод или нет. Если метод можно сохранить, на экране контракта появится переключатель.
-
+- ON - Сохранить платёжный метод для проведения рекуррентных платежей. Пользователю будут доступны только способы оплаты, поддерживающие сохранение. При первой оплате на экране выбранного способа оплаты будет отображено сообщение о том, что платёжный метод будет сохранён.
+- OFF - Не сохранять платёжный метод.
+- USER_SELECTS - Пользователь выбирает, сохранять платёжный метод или нет. Если метод можно сохранить, на экране экране выбранного способа оплаты появится переключатель.
+Подробнее про рекуррентные платежи можно прочитать в разделе [Рекуррентные платежи](#рекуррентные-платежи).
+
Значения `PaymentMethodType`:
-* YOO_MONEY - оплата произведена с кошелька ЮMoney;
-* BANK_CARD - оплата произведена с банковской карты;
-* SBERBANK - оплата произведена через Сбербанк (SMS invoicing или SberPay);
-* GOOGLE_PAY - оплата произведена через Google Pay.
+- YOO_MONEY - оплата произведена с кошелька ЮMoney;
+- BANK_CARD - оплата произведена с банковской карты;
+- SBERBANK - оплата произведена через Сбербанк (SMS invoicing или SberPay);
+- GOOGLE_PAY - оплата произведена через Google Pay.
Поля класса `GooglePayParameters`:
-* allowedCardNetworks (Set of GooglePayCardNetwork) - платежные системы, через которые возможна оплата с помощью Google Pay.
+- allowedCardNetworks (Set of GooglePayCardNetwork) - платежные системы, через которые возможна оплата с помощью Google Pay.
Значения `GooglePayCardNetwork`:
-* AMEX
-* DISCOVER
-* JCB
-* MASTERCARD
-* VISA
-* INTERAC
-* OTHER
+- AMEX
+- DISCOVER
+- JCB
+- MASTERCARD
+- VISA
+- INTERAC
+- OTHER
+
+### Запуск токенизации всеми методами
+
+Для того, чтобы запустить токенизацию всеми доступными методами оплаты, необходимо вызвать метод `createTokenizeIntent` и передать в него объект `PaymentParameters`, в котором находится набор всех спобосов оплаты или же не передавать этот набор.
+
+**Вариант 1**:
+
+
+ Kotlin
+
+```kotlin
+class MyActivity : AppCompatActivity() {
+
+ fun startTokenize() {
+ val paymentParameters = PaymentParameters(
+ amount = Amount(BigDecimal.TEN, Currency.getInstance("RUB")),
+ title = "Название товара",
+ subtitle = "Описание товара",
+ clientApplicationKey = "live_thisKeyIsNotReal", // ключ для клиентских приложений из личного кабинета ЮKassa
+ shopId = "12345", // идентификатор магазина ЮKassa
+ savePaymentMethod = SavePaymentMethod.OFF, // флаг выключенного сохранения платежного метода,
+ paymentMethodTypes = setOf(PaymentMethodType.YOO_MONEY, PaymentMethodType.BANK_CARD, PaymentMethodType.SBERBANK, PaymentMethodType.GOOGLE_PAY), // передан весь список доступных методов оплаты
+ gatewayId = "gatewayId", // gatewayId магазина для платежей Google Pay (необходим в случае, если в способах оплаты есть Google Pay)
+ customReturnUrl = "https://custom.redirect.url", // url страницы (поддерживается только https), на которую надо вернуться после прохождения 3ds.
+ userPhoneNumber = "+79041234567", // номер телефона пользователя для автозаполнения поля номера телефона пользователя в SberPay. Поддерживаемый формат данных: "+7XXXXXXXXXX"
+ authCenterClientId = "example_authCenterClientId" // идентификатор, полученный при регистрации приложения на сайте https://yookassa.ru
+ )
+ val intent = createTokenizeIntent(this, paymentParameters)
+ startActivityForResult(intent, REQUEST_CODE_TOKENIZE)
+ }
+}
+```
+
+
+
+ Java
-Java:
```java
class MyActivity extends AppCompatActivity {
- ...
-
- void timeToStartCheckout() {
+ void startTokenize() {
+ Set paymentMethodTypes = new HashSet(){{
+ add(PaymentMethodType.SBERBANK); // выбранный способ оплаты - SberPay
+ add(PaymentMethodType.YOO_MONEY); // выбранный способ оплаты - ЮMoney
+ add(PaymentMethodType.BANK_CARD); // выбранный способ оплаты - Банковская карта
+ add(PaymentMethodType.GOOGLE_PAY); // выбранный способ оплаты - Google Pay
+ }};
PaymentParameters paymentParameters = new PaymentParameters(
new Amount(BigDecimal.TEN, Currency.getInstance("RUB")),
"Название товара",
"Описание товара",
- "live_AAAAAAAAAAAAAAAAAAAA",
- "12345",
- SavePaymentMethod.OFF
+ "live_thisKeyIsNotReal", // ключ для клиентских приложений из личного кабинета ЮKassa
+ "12345", // идентификатор магазина ЮKassa
+ SavePaymentMethod.OFF, // флаг выключенного сохранения платежного метода
+ paymentMethodTypes, // передан весь список доступных методов оплаты
+ "gatewayId", // gatewayId магазина для платежей Google Pay (необходим в случае, если в способах оплаты есть Google Pay)
+ "https://custom.redirect.url", // url страницы (поддерживается только https), на которую надо вернуться после прохождения 3ds. Должен использоваться только при при использовании своего Activity для 3ds url.
+ userPhoneNumber = "+79041234567", // номер телефона пользователя. Используется для автозаполнения поля при оплате через SberPay. Поддерживаемый формат данных: "+7XXXXXXXXXX".
+ null, // настройки для токенизации через GooglePay,
+ "example_authCenterClientId" // идентификатор, полученный при регистрации приложения на сайте https://yookassa.ru
);
Intent intent = Checkout.createTokenizeIntent(this, paymentParameters);
startActivityForResult(intent, REQUEST_CODE_TOKENIZE);
}
}
```
+
+
+**Вариант 2**:
+
+
+ Kotlin
-Kotlin:
```kotlin
class MyActivity : AppCompatActivity() {
- ...
-
- fun timeToStartCheckout() {
+ fun startTokenize() {
val paymentParameters = PaymentParameters(
amount = Amount(BigDecimal.TEN, Currency.getInstance("RUB")),
title = "Название товара",
subtitle = "Описание товара",
- clientApplicationKey = "live_AAAAAAAAAAAAAAAAAAAA",
- shopId = "12345",
- savePaymentMethod = SavePaymentMethod.OFF
+ clientApplicationKey = "live_thisKeyIsNotReal", // ключ для клиентских приложений из личного кабинета ЮKassa (https://yookassa.ru/my/api-keys-settings)
+ shopId = "12345", // идентификатор магазина ЮKassa
+ savePaymentMethod = SavePaymentMethod.OFF, // флаг выключенного сохранения платежного метода,
+ authCenterClientId = "example_authCenterClientId", // идентификатор, полученный при регистрации приложения на сайте https://yookassa.ru
+ gatewayId = "gatewayId", // gatewayId магазина для платежей Google Pay (необходим в случае, если в способах оплаты есть Google Pay)
+ customReturnUrl = "https://custom.redirect.url", // url страницы (поддерживается только https), на которую надо вернуться после прохождения 3ds. Должен использоваться только при при использовании своего Activity для 3ds url.
+ userPhoneNumber = "+79041234567", // номер телефона пользователя. Используется для автозаполнения поля при оплате через SberPay. Поддерживаемый формат данных: "+7XXXXXXXXXX".
)
- val intent = createTokenizeIntent(this, paymentParameters)
+ val intent = Checkout.createTokenizeIntent(this, paymentParameters)
startActivityForResult(intent, REQUEST_CODE_TOKENIZE)
}
}
```
+
-### Запуск токенизации для сохранённых банковских карт
-
-Данный способ токенизации используется в случае, если есть привязанная к магазину карта и необходимо заново запросить у пользователя её csc.
-В остальных случаях следует использовать стандартный механизм токенизации (см. [Запуск токенизации](#запуск-токенизации)).
-
-Для запуска процесса токенизации с платежным идентификатором используется метод `Checkout.createSavedCardTokenizeIntent()`. Метод отдаёт `Intent`, который нужно запустить в startActivityForResult().
-Готовый платёжный токен можно получить в `onActivityResult()` (см. [Получение результата токенизации](#получение-результата-токенизации))
-
-Входные параметры метода:
-* context (Context) - контекст приложения;
-* savedBankCardPaymentParameters (SavedBankCardPaymentParameters) - параметры платежа с сохранённой банковской картой;
-* testParameters (TestParameters) - параметры для дебага, см. [Тестовые параметры и отладка](#тестовые-параметры-и-отладка);
-* uiParameters (UiParameters) - настройка интерфейса, см. [Настройка интерфейса](#настройка-интерфейса).
-
-Поля `SavedBankCardPaymentParameters`:
-
-Обязательные:
-* amount (Amount) - стоимость товара. Допустимые способы оплаты могут меняться в зависимости от этого параметра;
-* title (String) - название товара;
-* subtitle (String) - описание товара;
-* clientApplicationKey (String) - токен магазина, полученный в ЮKassa;
-* shopId (String) - идентификатор магазина в ЮKassa;
-* paymentMethodId (String) - идентификатор платежа;
-* savePaymentMethod (SavePaymentMethod) - настройка сохранения платёжного метода. Сохранённые платёжные методы можно использовать для проведения рекуррентных платежей.
-
-Необязательные:
-* gatewayId (String) - gatewayId для магазина.
-
-Поля класса `Amount`:
-* value (BigDecimal) - сумма;
-* currency (Currency) - валюта.
-
-Значения `SavePaymentMethod`:
-* ON - Сохранить платёжный метод для проведения рекуррентных платежей. Пользователю будут доступны только способы оплаты, поддерживающие сохранение. На экране контракта будет отображено сообщение о том, что платёжный метод будет сохранён.
-* OFF - Не сохранять платёжный метод.
-* USER_SELECTS - Пользователь выбирает, сохранять платёжный метод или нет. Если метод можно сохранить, на экране контракта появится переключатель.
+
+ Java
-Java:
```java
class MyActivity extends AppCompatActivity {
- ...
-
- void timeToStartCheckout() {
- SavedBankCardPaymentParameters parameters = new SavedBankCardPaymentParameters(
+ void startTokenize() {
+ PaymentParameters paymentParameters = new PaymentParameters(
new Amount(BigDecimal.TEN, Currency.getInstance("RUB")),
"Название товара",
"Описание товара",
- "live_AAAAAAAAAAAAAAAAAAAA",
- "12345",
- "paymentId",
- SavePaymentMethod.OFF
+ "live_thisKeyIsNotReal", // ключ для клиентских приложений из личного кабинета ЮKassa
+ "12345", // идентификатор магазина ЮKassa
+ SavePaymentMethod.OFF, // флаг выключенного сохранения платежного метода
+ null, // передан весь список доступных методов оплаты
+ "gatewayId", // gatewayId магазина для платежей Google Pay (необходим в случае, если в способах оплаты есть Google Pay)
+ "https://custom.redirect.url", // url страницы (поддерживается только https), на которую надо вернуться после прохождения 3ds. Должен использоваться только при при использовании своего Activity для 3ds url.
+ "+79041234567", // номер телефона пользователя. Используется для автозаполнения поля при оплате через SberPay. Поддерживаемый формат данных: "+7XXXXXXXXXX".
+ null, // настройки для токенизации через GooglePay,
+ "example_authCenterClientId" // идентификатор, полученный при регистрации приложения на сайте https://yookassa.ru
);
- Intent intent = Checkout.createSavedCardTokenizeIntent(this, parameters);
+ Intent intent = Checkout.createTokenizeIntent(this, paymentParameters);
startActivityForResult(intent, REQUEST_CODE_TOKENIZE);
}
}
```
+
+
+**Обработка результата процесса токенизации находится в разделе** [Получить результат токенизации](#получить-результат-токенизации)
+
+
+### Запуск токенизации кошельком ЮMoney
+
+> Если среди платёжных методов есть кошелёк ЮMoney, необходимо зарегистрировать приложение и получить `authCenterClientId`.
+В остальных случаях этот шаг можно пропустить.
+
+Если вы ранее уже регистрировали приложение для **oAuth-авторизации**, то список ваших приложений можно найти на странице https://yookassa.ru/oauth/v2/client
+Если вы ещё не регистрировали приложение для **oAuth-авторизации**, то нужно выполнить следующие инструкции.
+1. Для регистрации нового приложения необходимо авторизоваться на сайте https://yookassa.ru
+2. После авторизации перейдите на страницу регистрации приложения – https://yookassa.ru/oauth/v2/client
+3. Нажмите на кнопку создать приложение и задайте значение параметрам:
+ * Название;
+ * Описание. По желанию;
+ * Ссылка на сайт;
+ * Сallback URL – любой, можно указать ссылку на сайт;
+ * Доступы. Тут есть три раздела `API ЮKassa`, `Кошелёк ЮMoney`, `Профиль ЮMoney`.
+ * В разделе `Кошелёк ЮMoney` выдайте разрешение на чтение баланса кошелька пользователя. Для этого в разделе **БАЛАНС КОШЕЛЬКА** поставьте галку на против поля **Просмотр**;
+ * Откройте раздел `Профиль ЮMoney` и выдайте разрешение на чтение телефона, почты, имени и аватара пользователя. Для этого в разделе **ТЕЛЕФОН, ПОЧТА, ИМЯ И АВАТАР ПОЛЬЗОВАТЕЛЯ** поставьте галку на против поля **Просмотр**;
+3. Нажмите на кнопку "Зарегистрировать" и завершите регистрацию;
+4. В открывшемся окне появится информация о зарегистрированном приложении. Вам понадобится `authCenterClientId` для запуска токенизации;
+
+
+ Kotlin
-Kotlin:
```kotlin
class MyActivity : AppCompatActivity() {
- ...
-
- fun timeToStartCheckout() {
- val parameters = SavedBankCardPaymentParameters(
+ fun startYooMoneyTokenize() {
+ val paymentParameters = PaymentParameters(
amount = Amount(BigDecimal.TEN, Currency.getInstance("RUB")),
title = "Название товара",
subtitle = "Описание товара",
- clientApplicationKey = "live_AAAAAAAAAAAAAAAAAAAA",
- shopId = "12345",
- paymentMethodId = "paymentId",
- savePaymentMethod = SavePaymentMethod.OFF
+ clientApplicationKey = "live_thisKeyIsNotReal", // ключ для клиентских приложений из личного кабинета ЮKassa (https://yookassa.ru/my/api-keys-settings)
+ shopId = "12345", // идентификатор магазина ЮKassa
+ savePaymentMethod = SavePaymentMethod.OFF, // флаг выключенного сохранения платежного метода,
+ paymentMethodTypes = setOf(PaymentMethodType.YOO_MONEY), // выбранный способ оплаты - кошелек ЮMoney
+ authCenterClientId = "example_authCenterClientId" // идентификатор, полученный при регистрации приложения на сайте https://yookassa.ru
)
- val intent = createSavedCardTokenizeIntent(this, parameters)
+ val intent = createTokenizeIntent(this, paymentParameters)
startActivityForResult(intent, REQUEST_CODE_TOKENIZE)
}
}
```
+
-### Получение результата токенизации
-Результат токенизации будет возвращен в `onActivityResult()`.
+
+ Java
-Возможные типы результата:
-* Activity.RESULT_OK - токенизация прошла успешно;
-* Activity.RESULT_CANCELED - пользователь отменил токенизацию;
+```java
+class MyActivity extends AppCompatActivity {
-В случае успешной токенизации SDK вернёт токен и тип платежного инструмента, с помощью которого он был получен.
-Для получения токена используйте метод `Checkout.createTokenizationResult()`.
+ void startYooMoneyTokenize() {
+ Set paymentMethodTypes = new HashSet<>();
+ PaymentParameters paymentParameters = new PaymentParameters(
+ new Amount(BigDecimal.TEN, Currency.getInstance("RUB")),
+ "Название товара",
+ "Описание товара",
+ "live_thisKeyIsNotReal", // ключ для клиентских приложений из личного кабинета ЮKassa (https://yookassa.ru/my/api-keys-settings)
+ "12345", // идентификатор магазина ЮKassa
+ SavePaymentMethod.OFF, // флаг выключенного сохранения платежного метода
+ paymentMethodTypes.add(PaymentMethodType.YOO_MONEY), // выбранный способ оплаты - кошелек ЮMoney,
+ null, // gateway магазина для платежей Google Pay (необходим в случае, если в способах оплаты есть Google Pay)
+ null, // url страницы (поддерживается только https), на которую надо вернуться после прохождения 3ds. Должен использоваться только при при использовании своего Activity для 3ds url.
+ null, // номер телефона пользователя. Используется для автозаполнения поля при оплате через SberPay. Поддерживаемый формат данных: "+7XXXXXXXXXX".
+ null, // настройки для токенизации через GooglePay,
+ "example_authCenterClientId" // authCenterClientId - идентификатор, полученный при регистрации приложения на сайте https://yookassa.ru
+ );
+ Intent intent = Checkout.createTokenizeIntent(this, paymentParameters);
+ startActivityForResult(intent, REQUEST_CODE_TOKENIZE);
+ }
+}
+```
+
-`Checkout.createTokenizationResult()` принимает на вход `Intent`, полученный в `onActivityResult()` при успешной токенизации. Он возвращает TokenizationResult, который состоит из:
-* paymentToken (String) - платежный токен, см. [Использование платежного токена](#использование-платежного-токена);
-* paymentMethodType (PaymentMethodType) - тип платежного средства.
+**Обработка результата процесса токенизации находится в разделе** [Получить результат токенизации](#получить-результат-токенизации)
-Значения `PaymentMethodType`:
-* YOO_MONEY - оплата произведена с кошелька ЮMoney;
-* BANK_CARD - оплата произведена с банковской карты;
-* SBERBANK - оплата произведена через Сбербанк (SMS invoicing или SberPay);
-* GOOGLE_PAY - оплата произведена через Google Pay.
-Java:
-```java
-public final class MainActivity extends AppCompatActivity {
+### Запуск токенизации SberPay
- ...
+При оплате через SberPay есть два пользовательских сценария:
+- Оплата через мобильное приложение Сбербанк Онлайн;
+- Оплата без мобильного приложения Сбербанк Онлайн, по номеру телефона;
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- super.onActivityResult(requestCode, resultCode, data);
+Для того, что-бы ваши пользователи могли платить с помощью мобильного приложение Сбербанк Онлайн, нужно указать уникальную схему от диплинка вашего приложения.
+Уникальная схема диплинка - это то, что вы указываете в качестве схемы в ваших диплинках. Например в диплинке `exampleapp://some.path`, `exampleapp` - это и есть схема вашего приложения.
- if (requestCode == REQUEST_CODE_TOKENIZE) {
- switch (resultCode) {
- case RESULT_OK:
- // successful tokenization
- TokenizationResult result = Checkout.createTokenizationResult(data);
- ...
- break;
- case RESULT_CANCELED:
- // user canceled tokenization
- ...
- break;
- }
- }
- }
+Для добавления уникальной схемы диплинка нужно добавить в ваш файл build.gradle в блок android.defaultConfig строку `resValue "string", "ym_app_scheme", "exampleapp"`
+```
+android {
+ defaultConfig {
+ resValue "string", "ym_app_scheme", "exampleapp"
+ }
}
```
+Или добавить в ваш strings.xml строку вида:
+```
+
+ exampleapp
+
+```
+Где `exampleapp` - это уникальная схема диплинка вашего приложения. Сюда нужно подставить свою схему.
+Если вы уже обрабатывете какие-то deeplink в своём приложении, то можно использовать готовую схему вашего приложения.
+Если ранее в проекте вы не обрабатывали deeplink, можно придумать уникальную схему для вашего приложения, состоящую из латинских букв.
-Kotlin:
-```kotlin
-class MainActivity : AppCompatActivity() {
-
- ...
+**Запуск токеннизации через SberPay выглядит следующим образом.**
- override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
- super.onActivityResult(requestCode, resultCode, data)
+
+ Kotlin
- if (requestCode == REQUEST_CODE_TOKENIZE) {
- when (resultCode) {
- RESULT_OK -> {
- // successful tokenization
- val result = data?.let { createTokenizationResult(it) }
- }
- RESULT_CANCELED -> {
- // user canceled tokenization
- }
- }
- }
+```kotlin
+class MyActivity: Activity() {
+
+ private fun startSberPayTokenize() {
+ val paymentParameters = PaymentParameters(
+ amount = Amount(BigDecimal.valueOf(10.0), Currency.getInstance("RUB")),
+ title = "Название товара",
+ subtitle = "Описание товара",
+ clientApplicationKey = "live_thisKeyIsNotReal", // ключ для клиентских приложений из личного кабинета ЮKassa (https://yookassa.ru/my/api-keys-settings)
+ shopId = "12345", // идентификатор вашего магазина ЮKassa
+ savePaymentMethod = SavePaymentMethod.OFF, // флаг выключенного сохранения платежного метода
+ paymentMethodTypes = setOf(PaymentMethodType.SBERBANK), // выбранный способ оплаты - SberPay
+ userPhoneNumber = "+79041234567", // номер телефона пользователя. Используется для автозаполнения поля при оплате через SberPay. Поддерживаемый формат данных: "+7XXXXXXXXXX".
+ )
+ val intent = createTokenizeIntent(this, paymentParameters)
+ startActivityForResult(intent, REQUEST_CODE_TOKENIZE)
}
}
```
+
-### Использование платежного токена
-Необходимо получить у менеджера ЮKassa разрешение на проведение платежей с использованием токена.
-Токен одноразовый, срок действия — 1 час. Если не создать платеж в течение часа, токен нужно будет запрашивать заново.
-
-В платежном токене содержатся данные о [сценарии подтверждения](https://yookassa.ru/developers/payments/payment-process#user-confirmation) платежа.
-После получения платежного токена Вы можете [создать платеж](https://yookassa.ru/developers/api#create_payment), в параметре `payment_token` передайте платежный токен.
-Если платеж проводится с аутентификацией по 3-D Secure, используйте `confirmation_url`, который придет в объекте [Платежа](https://yookassa.ru/developers/api#payment_object).
-Используйте `confirmation_url` для запуска 3-D Secure, см. [3DSecure](#3DSecure).
-
-Так же, Вы можете получить [информацию о платеже](https://yookassa.ru/developers/api#get_payment)
-
-### Тестовые параметры и отладка
-
-Для отладки токенизации в вызов `Checkout.createTokenizeIntent()` можно добавить объект `TestParameters`.
-
-Поля класса `TestParameters:`
-* showLogs (Boolean) - включить отображение логов SDK. Все логи начинаются с тега 'YooKassa.SDK'
-* googlePayTestEnvironment (Boolean) - использовать тестовую среду Google Pay - все транзакции, проведенные через Google Pay, будут использовать `WalletConstants.ENVIRONMENT_TEST`. Имейте ввиду, что при попытке оплаты с параметром googlePayTestEnvironment=true произойдет ошибка токенизации. Подробнее см. на https://developers.google.com/pay/api/android/guides/test-and-deploy/integration-checklist#about-the-test-environment.
-* mockConfiguration (MockConfiguration) - использовать моковую конфигурацию. Если этот параметр присутствует, SDK будет работать в оффлайн режиме и генерировать тестовый токен. Этот токен нельзя использовать для платежей.
-
-`MockConfiguration`
-В библиотеке есть тестовый режим, с помощью которого можно посмотреть, как будет выглядеть работа SDK при различных входных данных.
-Для работы этого режима не нужен доступ в интернет. Полученный токен нельзя использовать для оплаты.
+
+ Java
-Поля класса `MockConfiguration`:
-* completeWithError (Boolean) - токенизация всегда возвращает ошибку;
-* paymentAuthPassed (Boolean) - пользователь всегда авторизован;
-* linkedCardsCount (Int) - количество карт, привязанных к кошельку пользователя;
-* serviceFee (Amount) - комиссия, которая будет отображена на контракте;
-
-Java:
```java
-class MyActivity extends AppCompatActivity {
-
- ...
-
- void timeToStartCheckout() {
- PaymentParameters paymentParameters = new PaymentParameters(...);
- TestParameters testParameters = new TestParameters(
- true,
- true,
- new MockConfiguration(false, true, 5, new Amount(BigDecimal.TEN, Currency.getInstance("RUB")))
+public class MyActivity extends Activity {
+
+ private void startSberPayTokenize() {
+ Set paymentMethodTypes = new HashSet(){{
+ add(PaymentMethodType.SBERBANK); // выбранный способ оплаты - SberPay
+ }};
+ paymentMethodTypes.add(PaymentMethodType.SBERBANK);
+ PaymentParameters paymentParameters = new PaymentParameters(
+ new Amount(BigDecimal.valueOf(10.0), Currency.getInstance("RUB")),
+ "Название товара",
+ "Описание товара",
+ "live_thisKeyIsNotReal", // ключ для клиентских приложений из личного кабинета ЮKassa (https://yookassa.ru/my/api-keys-settings)
+ "12345", // идентификатор вашего магазина ЮKassa
+ SavePaymentMethod.OFF, // флаг выключенного сохранения платежного метода
+ paymentMethodTypes, // выбранный способ оплаты - SberPay,
+ null, // gateway магазина для платежей Google Pay (необходим в случае, если в способах оплаты есть Google Pay)
+ null, // url страницы (поддерживается только https), на которую надо вернуться после прохождения 3ds. Должен использоваться только при при использовании своего Activity для 3ds url.
+ "+79041234567" // номер телефона пользователя. Используется для автозаполнения поля при оплате через SberPay. Поддерживаемый формат данных: "+7XXXXXXXXXX".
);
- Intent intent = Checkout.createTokenizeIntent(this, paymentParameters, testParameters);
+ Intent intent = Checkout.createTokenizeIntent(this, paymentParameters);
startActivityForResult(intent, REQUEST_CODE_TOKENIZE);
}
}
```
+
+
+**Обработка результата процесса токенизации находится в разделе** [Получить результат токенизации](#получить-результат-токенизации)
+
+
+### Запуск токенизации банковской картой
+
+Для запуска токенизации только банковской картой необходимо передать в `PaymentParameters` `setOf(PaymentMethodType.BANK_CARD)` :
+
+
+ Kotlin
-Kotlin:
```kotlin
class MyActivity : AppCompatActivity() {
- ...
-
- fun timeToStartCheckout() {
- val paymentParameters = PaymentParameters(...)
- val testParameters = TestParameters(
- true,
- true,
- MockConfiguration(false, true, 5, Amount(BigDecimal.TEN, Currency.getInstance("RUB")))
+ fun startBankCardTokenize() {
+ val paymentParameters = PaymentParameters(
+ amount = Amount(BigDecimal.TEN, Currency.getInstance("RUB")),
+ title = "Название товара",
+ subtitle = "Описание товара",
+ clientApplicationKey = "live_thisKeyIsNotReal", // ключ для клиентских приложений из личного кабинета ЮKassa (https://yookassa.ru/my/api-keys-settings)
+ shopId = "12345", // идентификатор магазина ЮKassa
+ savePaymentMethod = SavePaymentMethod.OFF, // флаг выключенного сохранения платежного метода,
+ paymentMethodTypes = setOf(PaymentMethodType.BANK_CARD) // выбранный способ оплаты - банковская карта
)
- val intent = createTokenizeIntent(this, paymentParameters, testParameters)
+ val intent = createTokenizeIntent(this, paymentParameters)
startActivityForResult(intent, REQUEST_CODE_TOKENIZE)
}
}
```
+
-### Настройка интерфейса
-
-Для настройки интерфейса SDK можно использовать объект `UiParameters`. Можно настроить цвета интерфейса и показ/скрытие логотипа ЮKassa.
-
-Поля класса `UiParameters`:
-* showLogo (Boolean) - показать/скрыть лого ЮKassa на экране способов оплаты.
-* colorScheme (ColorScheme) - цветовая схема.
-
-Поля класса `ColorScheme`:
-* primaryColor (ColorInt) - основной цвет приложения. В этот цвет будут краситься кнопки, переключатели, поля для ввода и т.д.
-Не рекомендуется задавать в качестве этого цвета слишком светлые цвета (они будут не видны на белом фоне) и красный цвет (он будет пересекаться с цветом ошибки).
+
+ Java
-Java:
```java
class MyActivity extends AppCompatActivity {
- ...
-
- void timeToStartCheckout() {
- PaymentParameters paymentParameters = new PaymentParameters(...);
- UiParameters uiParameters = new UiParameters(true, new ColorScheme(Color.rgb(0, 114, 245)));
- Intent intent = Checkout.createTokenizeIntent(this, paymentParameters, new TestParameters(), uiParameters);
+ void startBankCardTokenize() {
+ Set paymentMethodTypes = new HashSet<>();
+ PaymentParameters paymentParameters = new PaymentParameters(
+ new Amount(BigDecimal.TEN, Currency.getInstance("RUB")),
+ "Название товара",
+ "Описание товара",
+ "live_thisKeyIsNotReal", // ключ для клиентских приложений из личного кабинета ЮKassa (https://yookassa.ru/my/api-keys-settings)
+ "12345", // идентификатор магазина ЮKassa
+ SavePaymentMethod.OFF, // флаг выключенного сохранения платежного метода
+ paymentMethodTypes.add(PaymentMethodType.BANK_CARD) // выбранный способ оплаты - банковская карта
+ );
+ Intent intent = Checkout.createTokenizeIntent(this, paymentParameters);
startActivityForResult(intent, REQUEST_CODE_TOKENIZE);
}
}
-
```
-Kotlin:
-```kotlin
-class MyActivity : AppCompatActivity() {
+
- ...
+**Обработка результата процесса токенизации находится в разделе** [Получить результат токенизации](#получить-результат-токенизации)
- fun timeToStartCheckout() {
- val paymentParameters = PaymentParameters(...)
- val uiParameters = UiParameters(true, ColorScheme(Color.rgb(0, 114, 245)))
- val intent = createTokenizeIntent(this, paymentParameters, TestParameters(), uiParameters)
- startActivityForResult(intent, REQUEST_CODE_TOKENIZE)
- }
-}
-```
-## 3DSecure
+### Подготовка к запуску токенизации Google Pay
-Для упрощения интеграции платежей по банковским картам в SDK есть Activity для обработки 3DS.
-Не указывайте PaymentParameters.customReturnUrl при вызове Checkout.createTokenizeIntent(), если используете это Activity.
+Перед тем, как начать запускать токенизацию Google Pay, нужно сначала подготовить приложение и провести интеграцию с Google Pay API.
+
+#### Подготовка Google Play Console
+
+Для того, чтобы заработала оплата через Google Pay на production среде, убедитесь что у вас:
+- Есть аккаунт разработчика в консоли разработчика: https://play.google.com/console
+- Есть созданное приложение в консоли разработчика;
+- Ваше приложение подписано релизным ключом и загружено в консоль разработчика;
+
+#### Подготовка профиля в Google Pay Business Console
+
+После того, как выполнены шаги из раздела: [Подготовка Google Play Console](#подготовка-Google-Play-Console), можно перейти к подготовке профиля компании в Google Pay Business Console. Для этого:
+- Перейдите на сайт: https://pay.google.com/business/console;
+- Заполните всю необходимую информацию для профиля компании;
+- После заполнения профиля, там же на сайте, отправьте профиль компании на проверку сотрудникам Google Pay Business Console;
+- Дождитесь, когда профиль компании будет проверен сотрудниками Google Pay Business Console.
+
+#### Интеграция приложения c Google Pay API
+
+Если выполнены все условия выше, то можно приступить к интеграции Google Pay API.
+Для этого проделайте следующие шаги:
+- Перейдите на сайт google pay business console: https://pay.google.com/business/console;
+- Перейдите на вкладку Google Pay API;
+- Найдите блок "Интеграция с вашим Android приложением";
+- В этом блоке найдите ваше приложение, для которого вы хотите выполнить интеграцию и нажмите "Управление". Если вашего приложения нет в списке, нужно выполнить инструкции из раздела: [Подготовка Google Play Console](#подготовка-Google-Play-Console);
+- В открывшемся окне выберите тип интеграции через шлюз(gateway);
+- Загрузите скриншоты процесса покупки. Как подготовить скриншоты смотрите раздел: [Подготовка скриншотов процесса покупки для Google Pay API](#подготовка-скриншотов-процесса-покупки-для-Google-Pay-API);
+- Там же на сайте, отправьте форму на ревью.
+- После того как интеграцию проверят и подтвердят, должна заработать оплата через google pay в релизном приложении.
+- Если интеграцию отклонили, нужно исправить замечания и повторно отправить форму.
+
+#### Подготовка скриншотов процесса покупки для Google Pay API
+
+Для заполнения формы в разделе: [Интеграция приложения в Google Pay API](#Интеграция-приложения-в-Google-Pay-API), вам нужны будут скриншоты процесса оплаты.
+Для этого вам нужны будут скриншоты нескольких шагов, примеры показаны ниже.
+> Примеры скриншотов ниже предоставлены для ознакомления, использовать их для заполнения формы не нужно. Нужно сделать подобные скриншоты но в вашем приложении.
+
+| Экран товара | Экран со способами оплаты | Экран оплаты с помощью Google Pay | Экран успешной оплаты |
+| ------------- | ----- | ----- | ----- |
+| ![Экран товара](assets/images/pay-flow-examples/1_2_item_selection_pre_purchase_screen.png) | ![Экран товара](assets/images/pay-flow-examples/3_payment_method_screen.png) | ![Экран товара](assets/images/pay-flow-examples/4_google_pay_api_payment_screen.png) | ![Экран товара](assets/images/pay-flow-examples/5_post_purchase_screen.png) |
+
+Для того, чтобы можно было сделать скриншоты всего процесса оплаты, предлагается использовать mock-режим sdk. Это такой режим, где sdk не делает реальных запросов на сервер, а вместо этого использует заранее подготовленные данные.
+- Для этого запустите токенизацию со всеми способами оплаты которые вы планируете использовать.
+- Для параметра `testParameters` передайте `googlePayTestEnvironment = true` и `mockConfiguration = MockConfiguration()`
+
+`googlePayTestEnvironment` - отвечает за среду на которой будет работать Google Pay.
+- Если передать `googlePayTestEnvironment = true` - будет использоваться тестовая среда, подробнее можно почитать тут: https://developers.google.com/pay/api/android/guides/test-and-deploy/integration-checklist
+- Если передать `googlePayTestEnvironment = false`, или не передать параметр вообще, будет использоваться production среда.
+> **Обратите внимание**, если передать `googlePayTestEnvironment = true` то токенизация в самом sdk работать не будет.
+
+Ниже приведены примеры кода с запуском токенизации для создания скриншотов процесса оплаты с помощью Google Pay
+
+
+ Kotlin
+
+```kotlin
+class MyActivity: Activity() {
+
+ private fun startSberPayTokenize() {
+ val paymentParameters = PaymentParameters(
+ amount = Amount(BigDecimal.valueOf(10.0), Currency.getInstance("RUB")),
+ title = "Название товара",
+ subtitle = "Описание товара",
+ clientApplicationKey = "live_thisKeyIsNotReal", // ключ для клиентских приложений из личного кабинета ЮKassa (https://yookassa.ru/my/api-keys-settings)
+ shopId = "12345", // идентификатор вашего магазина ЮKassa
+ savePaymentMethod = SavePaymentMethod.OFF, // флаг выключенного сохранения платежного метода
+ authCenterClientId = "example_authCenterClientId" // идентификатор, полученный при регистрации приложения на сайте https://yookassa.ru
+ )
+ val intent = createTokenizeIntent(
+ context = this,
+ paymentParameters = paymentParameters,
+ testParameters = TestParameters(
+ showLogs = true,// showLogs - включить/выключить отображение логов SDK
+ googlePayTestEnvironment = true,// googlePayTestEnvironment - какую, тестовую или боевую, среду нужно использовать для Google Pay, подробнее можно почитать тут: https://developers.google.com/pay/api/android/guides/test-and-deploy/integration-checklist
+ mockConfiguration = MockConfiguration()//Включение mock-режима
+ )
+ )
+ startActivityForResult(intent, REQUEST_CODE_TOKENIZE)
+ }
+}
+```
+
+
+
+ Java
+
+```java
+class MyActivity extends AppCompatActivity {
+
+ private void startTokenize() {
+ TestParameters testParameters = new TestParameters(
+ true, // showLogs - включить/выключить отображение логов SDK
+ true, // googlePayTestEnvironment - какую, тестовую или боевую, среду нужно использовать для Google Pay, подробнее можно почитать тут: https://developers.google.com/pay/api/android/guides/test-and-deploy/integration-checklist
+ new MockConfiguration() // Включение mock-режима
+ );
+ PaymentParameters paymentParameters = new PaymentParameters(
+ new Amount(BigDecimal.TEN, Currency.getInstance("RUB")),
+ "Название товара",
+ "Описание товара",
+ "live_thisKeyIsNotReal", // ключ для клиентских приложений из личного кабинета ЮKassa
+ "12345", // идентификатор магазина ЮKassa
+ SavePaymentMethod.OFF, // флаг выключенного сохранения платежного метода
+ null, // передан весь список доступных методов оплаты
+ "gatewayId", // gatewayId магазина для платежей Google Pay (необходим в случае, если в способах оплаты есть Google Pay)
+ "https://custom.redirect.url", // url страницы (поддерживается только https), на которую надо вернуться после прохождения 3ds. Должен использоваться только при при использовании своего Activity для 3ds url.
+ "+79041234567", // номер телефона пользователя. Используется для автозаполнения поля при оплате через SberPay. Поддерживаемый формат данных: "+7XXXXXXXXXX".
+ null, // настройки для токенизации через GooglePay,
+ "example_authCenterClientId" // идентификатор, полученный при регистрации приложения на сайте https://yookassa.ru
+ );
+ Intent intent = Checkout.createTokenizeIntent(this, paymentParameters, testParameters);
+ startActivityForResult(intent, REQUEST_CODE_TOKENIZE);
+ }
+}
+```
+
+
+**Обработка результата процесса токенизации находится в разделе** [Получить результат токенизации](#получить-результат-токенизации)
+
+
+### Запуск токенизации Google Pay
+
+>Если вы интегрируете Google Pay впервые, убедитесь что выполнены все условия по подготовке из раздела: [Подготовка к запуску токенизации Google Pay](#подготовка-к-запуск-токенизации-Google-Pay)
+
+Для запуска токенизации Google Pay, нужно указать среди `paymentMethodTypes`, значение `PaymentMethodType.GOOGLE_PAY`
+
+
+ Kotlin
+
+```kotlin
+class MyActivity: Activity() {
+
+ private fun startGooglePayTokenize() {
+ val paymentParameters = PaymentParameters(
+ amount = Amount(BigDecimal.valueOf(10.0), Currency.getInstance("RUB")),
+ title = "Название товара",
+ subtitle = "Описание товара",
+ clientApplicationKey = "live_thisKeyIsNotReal", // ключ для клиентских приложений из личного кабинета ЮKassa (https://yookassa.ru/my/api-keys-settings)
+ shopId = "12345", // идентификатор вашего магазина ЮKassa
+ savePaymentMethod = SavePaymentMethod.OFF, // флаг выключенного сохранения платежного метода
+ paymentMethodTypes = setOf(PaymentMethodType.GOOGLE_PAY) // выбранный способ оплаты - Google Pay
+ )
+ val intent = createTokenizeIntent(context = this, paymentParameters = paymentParameters)
+ startActivityForResult(intent, REQUEST_CODE_TOKENIZE)
+ }
+}
+```
+
+
+
+ Java
+
+```java
+class MyActivity extends AppCompatActivity {
+
+ void startGooglePayTokenize() {
+ Set paymentMethodTypes = new HashSet<>();
+ PaymentParameters paymentParameters = new PaymentParameters(
+ new Amount(BigDecimal.TEN, Currency.getInstance("RUB")),
+ "Название товара",
+ "Описание товара",
+ "live_thisKeyIsNotReal", // ключ для клиентских приложений из личного кабинета ЮKassa (https://yookassa.ru/my/api-keys-settings)
+ "12345", // идентификатор магазина юKassa
+ SavePaymentMethod.OFF, // флаг выключенного сохранения платежного метода
+ paymentMethodTypes.add(PaymentMethodType.GOOGLE_PAY) // выбранный способ оплаты - Google Pay
+ );
+ Intent intent = Checkout.createTokenizeIntent(this, paymentParameters);
+ startActivityForResult(intent, REQUEST_CODE_TOKENIZE);
+ }
+}
+```
+
+
+**Обработка результата процесса токенизации находится в разделе** [Получить результат токенизации](#получить-результат-токенизации)
-Входные параметры для `Checkout.createConfirmationIntent()`:
+
+> Оплата через Google Pay работает только с релизным приложением, у которого релизный пакет приложения и которое подписано релизным ключом.
+
В остальных случаях токенизация через Google Pay, работать не будет.
+
+### Запуск токенизации для сохранённых банковских карт
+
+Данный способ токенизации используется в случае, если есть привязанная к магазину карта (см. [Привязанная карта](#привязанная-карта)) и необходимо заново запросить у пользователя её CSC.
+В остальных случаях следует использовать стандартный механизм токенизации (см. [Запуск токенизации](#токенизация)).
+
+Для запуска процесса токенизации с платежным идентификатором используется метод `Checkout.createSavedCardTokenizeIntent()`. Метод возвращает `Intent`, который нужно запустить в startActivityForResult().
+Готовый платёжный токен можно получить в `onActivityResult()` (см. [Получение результата токенизации](#получение-результата-токенизации))
+
+Обязательные параметры метода:
+- context (Context) - контекст приложения;
+- savedBankCardPaymentParameters (SavedBankCardPaymentParameters) - параметры платежа с сохранённой банковской картой.
+
+Опциональные параметры метода:
+- testParameters (TestParameters) - параметры для тестового режима - включить логирование/использовать mock-данные, (см. [Настройка логирования и mock режима](#настройка-логирования-и-mock-режима));
+- uiParameters (UiParameters) - настройка интерфейса, (см. [Настройка интерфейса](#настройка-интерфейса)).
+
+Поля `SavedBankCardPaymentParameters`:
Обязательные:
-* context (Context) - контекст для создания `Intent`;
-* confirmationUrl (String) - URL для перехода на 3DS;
-* paymentMethodType (PaymentMethodType) - выбранный тип платежного метода.
+- amount (Amount) - стоимость товара. Допустимые способы оплаты могут меняться в зависимости от этого параметра;
+- title (String) - название товара;
+- subtitle (String) - описание товара;
+- clientApplicationKey (String) - ключ для клиентских приложений из личного кабинета ЮKassa ([раздел Настройки — Ключи API](https://yookassa.ru/my/api-keys-settings));
+- shopId (String) - идентификатор магазина в ЮKassa ([раздел Организации](https://yookassa.ru/my/company/organization) - скопировать shopId у нужного магазина);
+- paymentMethodId (String) - идентификатор платежа;
+- savePaymentMethod (SavePaymentMethod) - настройка сохранения платёжного метода. Сохранённые платёжные методы можно использовать для проведения рекуррентных платежей. (см. [Рекуррентные платежи](#рекуррентные-платежи))
Необязательные:
-* colorScheme (ColorScheme) - цветовая схема;
-* testParameters (TestParameters) - параметры для дебага.
+- gatewayId (String) - gatewayId для магазина, (см. [Запуск токенизации Google Pay](#запуск-токенизации-Google-Pay)).
-Результат работы 3ds можно получить в `onActivityResult()`
+Поля класса `Amount`:
+* value (BigDecimal) - сумма;
+* currency (Currency) - валюта.
+
+Значения `SavePaymentMethod`:
+* ON - Сохранить платёжный метод для проведения рекуррентных платежей. Пользователю будут доступны только способы оплаты, поддерживающие сохранение. При первой оплате на экране выбранного способа оплаты будет отображено сообщение о том, что платёжный метод будет сохранён.
+* OFF - Не сохранять платёжный метод.
+* USER_SELECTS - Пользователь выбирает, сохранять платёжный метод или нет. Если метод можно сохранить, на экране выбранного способа оплаты появится переключатель.
+Подробнее про рекуррентные платежи можно прочитать в разделе [Рекуррентные платежи](#рекуррентные-платежи).
+
+
+ Kotlin
+
+```kotlin
+class MyActivity : AppCompatActivity() {
+
+ fun startSavedCardTokenize() {
+ val parameters = SavedBankCardPaymentParameters(
+ amount = Amount(BigDecimal.TEN, Currency.getInstance("RUB")),
+ title = "Название товара",
+ subtitle = "Описание товара",
+ clientApplicationKey = "live_thisKeyIsNotReal", // ключ для клиентских приложений из личного кабинета ЮKassa
+ shopId = "12345", // идентификатор магазина ЮKassa
+ paymentMethodId = "paymentMethodIdExample", // уникальный идентификатор платежа
+ savePaymentMethod = SavePaymentMethod.OFF
+ )
+ val intent = createSavedCardTokenizeIntent(this, parameters)
+ startActivityForResult(intent, REQUEST_CODE_TOKENIZE)
+ }
+}
+```
+
+
+
+ Java
+
+```java
+class MyActivity extends AppCompatActivity {
+
+ void startSavedCardTokenize() {
+ SavedBankCardPaymentParameters parameters = new SavedBankCardPaymentParameters(
+ new Amount(BigDecimal.TEN, Currency.getInstance("RUB")),
+ "Название товара",
+ "Описание товара",
+ "live_thisKeyIsNotReal", // ключ для клиентских приложений из личного кабинета ЮKassa
+ "12345", // идентификатор магазина ЮKassa
+ "paymentMethodIdExample", // уникальный идентификатор платежа
+ SavePaymentMethod.OFF // флаг выключенного сохранения платежного метода
+ );
+ Intent intent = Checkout.createSavedCardTokenizeIntent(this, parameters);
+ startActivityForResult(intent, REQUEST_CODE_TOKENIZE);
+ }
+}
+```
+
+
+**Обработка результата процесса токенизации находится в разделе** [Получить результат токенизации](#получить-результат-токенизации)
+
+
+### Получить результат токенизации
+
+Результат работы метода `Checkout.createTokenizeIntent` можно обработать в методе `onActivityResult()`.
Возможные типы результата:
-* Activity.RESULT_OK - сообщает о том что процесс 3ds завершён, но не гарантирует что успешно. После получения результата рекомендуется запросить статус платежа;
-* Activity.RESULT_CANCELED - прохождение 3ds было отменено (например, пользователь нажал на кнопку "назад" во время процесса);
-* Checkout.RESULT_ERROR - не удалось пройти 3ds.
+* Activity.RESULT_OK - токенизация прошла успешно;
+* Activity.RESULT_CANCELED - пользователь отменил токенизацию;
+
+В случае успешной токенизации mSDK вернёт сущность `TokenizationResult`, в которой лежит токен и тип платежного инструмента, с помощью которого он был получен.
+Для получения токена используйте метод `Checkout.createTokenizationResult()`.
+
+`TokenizationResult` хранит:
+* paymentToken (String) - платежный токен;
+* paymentMethodType (PaymentMethodType) - тип платежного метода.
+
+Значения `PaymentMethodType`:
+* YOO_MONEY - оплата произведена с кошелька ЮMoney;
+* BANK_CARD - оплата произведена с банковской карты;
+* SBERBANK - оплата произведена через Сбербанк (SMS invoicing или SberPay);
+* GOOGLE_PAY - оплата произведена через Google Pay.
+
+
+ Kotlin
+
+```kotlin
+class MainActivity : AppCompatActivity() {
+
+ override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+ super.onActivityResult(requestCode, resultCode, data)
+
+ if (requestCode == REQUEST_CODE_TOKENIZE) {
+ when (resultCode) {
+ RESULT_OK -> {
+ // successful tokenization
+ val result = data?.let { createTokenizationResult(it) }
+ }
+ RESULT_CANCELED -> {
+ // user canceled tokenization
+ }
+ }
+ }
+ }
+}
+```
+
+
+
+ Java
+
+```java
+public final class MainActivity extends AppCompatActivity {
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ if (requestCode == REQUEST_CODE_TOKENIZE) {
+ switch (resultCode) {
+ case RESULT_OK:
+ // successful tokenization
+ TokenizationResult result = Checkout.createTokenizationResult(data);
+ ...
+ break;
+ case RESULT_CANCELED:
+ // user canceled tokenization
+ ...
+ break;
+ }
+ }
+ }
+}
+```
+
+
+## Подтверждение платежа
+
+При необходимости система может запросить процесс подтверждения платежа, при котором пользователь подтверждает транзакцию с помощью сторонних сервисов.
+Существует два типа подтверждения платежа - 3Dsecure (при оплате банковской картой и Google Pay) и пуш-нотификации или App2App сценарий (при оплате через SberPay).
+
+### SberPay
+
+Для подтверждения платежа при оплате через SberPay необходимо:
+1. вызвать метод Checkout.createConfirmationIntent();
+2. обработать полученный результат в Activity в методе onActivityResult;
+
+Входные параметры для `Checkout.createConfirmationIntent()`:
+
+Обязательные параметры метода:
+- context (Context) - контекст приложения;
+- confirmationUrl (String) - URL для перехода на экран подтверждения платежа через SberPay;
+- paymentMethodType (PaymentMethodType) - выбранный тип платежного метода (тот, что был получен в методе `createTokenizationResult()`, (см. [Получить результат токенизации](#получить-результат-токенизации)) .
+
+Опциональные параметры метода:
+- testParameters (TestParameters) - параметры для тестового режима - включить логирование/использовать mock-данные, (см. [Настройка логирования и mock режима](#настройка-логирования-и-mock-режима));
+- colorScheme (ColorScheme) - цветовая схема, (см. [Настройка интерфейса](#настройка-интерфейса)).
+
+Возможные типы результата проведения подтверждения через SberPay:
+
+- Activity.RESULT_OK - сообщает о том, что процесс подтверждения через SberPay завершён, но не несет информацию о том, что процесс завершился успешно. После получения результата рекомендуется запросить статус платежа;
+- Activity.RESULT_CANCELED - прохождение подтверждения через SberPay было отменено (например, пользователь нажал на кнопку "назад" во время процесса);
+- Checkout.RESULT_ERROR - не удалось пройти подтверждение через SberPay.
**Запуск 3ds и получение результата**
-Java:
+
+
+ Kotlin
+
+```kotlin
+class MyActivity : AppCompatActivity() {
+
+ fun startConfirmSberPay() {
+ val intent = createConfirmationIntent(this, "your_app_scheme://invoicing/sberpay", PaymentMethodType.SBERBANK)
+ startActivityForResult(intent, REQUEST_CODE_CONFIRM)
+ }
+
+ override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+ if (requestCode == REQUEST_CODE_CONFIRM) {
+ when (resultCode) {
+ RESULT_OK -> {
+ // Процесс подтверждения через SberPay завершён, нет информации о том, завершился процесс с успехом или нет
+ // Рекомендуется запросить статус платежа
+ return
+ }
+ RESULT_CANCELED -> return // Экран подтверждения через SberPay был закрыт
+ Checkout.RESULT_ERROR -> {
+ // Во время подтверждения через SberPay произошла какая-то ошибка (нет соединения или что-то еще)
+ // Более подробную информацию можно посмотреть в data
+ // data.getIntExtra(Checkout.EXTRA_ERROR_CODE) - код ошибки из WebViewClient.ERROR_* или Checkout.ERROR_NOT_HTTPS_URL
+ // data.getStringExtra(Checkout.EXTRA_ERROR_DESCRIPTION) - описание ошибки (может отсутствовать)
+ // data.getStringExtra(Checkout.EXTRA_ERROR_FAILING_URL) - url по которому произошла ошибка (может отсутствовать)
+ }
+ }
+ }
+ }
+}
+```
+
+
+
+ Java
+
```java
class MyActivity extends AppCompatActivity {
- void timeToStart3DS() {
- Intent intent = Checkout.createConfirmationIntent(this, "https://3dsurl.com/", PaymentMethodType.BANK_CARD);
- startActivityForResult(intent, 1);
+ void startConfirmSberPay() {
+ Intent intent = Checkout.createConfirmationIntent(this, "your_app_scheme://invoicing/sberpay", PaymentMethodType.SBERBANK);
+ startActivityForResult(intent, REQUEST_CODE_CONFIRM);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- if (requestCode == 1) {
+ if (requestCode == REQUEST_CODE_CONFIRM) {
switch (resultCode) {
case RESULT_OK:
- // Процесс 3ds завершён
+ // Процесс подтверждения через SberPay завершён, нет информации о том, завершился процесс с успехом или нет
+ // Рекомендуется запросить статус платежа
break;
case RESULT_CANCELED:
- // экран 3ds был закрыт
+ // Экран подтверждения через SberPay был закрыт
break;
case Checkout.RESULT_ERROR:
- // во время 3ds произошла какая-то ошибка (нет соединения или что-то еще)
- // более подробную информацию можно посмотреть в data
+ // Во время подтверждения через SberPay произошла какая-то ошибка (нет соединения или что-то еще)
+ // Более подробную информацию можно посмотреть в data
// data.getIntExtra(Checkout.EXTRA_ERROR_CODE) - код ошибки из WebViewClient.ERROR_* или Checkout.ERROR_NOT_HTTPS_URL
// data.getStringExtra(Checkout.EXTRA_ERROR_DESCRIPTION) - описание ошибки (может отсутствовать)
// data.getStringExtra(Checkout.EXTRA_ERROR_FAILING_URL) - url по которому произошла ошибка (может отсутствовать)
@@ -541,24 +969,58 @@ class MyActivity extends AppCompatActivity {
}
}
```
+
+
+### 3DSecure
+
+Для проведения 3DSecure при оплате банковской картой вы можете воспользоваться Activity, которая предоставлена библиотекой mSdk.
+Для этого необходимо:
+1. при проведении токенизации не нужно передавать параметр `customReturnUrl` в методе `createTokenizeIntent` (см. [Запуск токенизации банковской картой](#запуск-токенизации-банковской-картой));
+2. вызвать метод Checkout.createConfirmationIntent();
+3. обработать полученный результат в Activity в методе onActivityResult;
+
+Входные параметры для `Checkout.createConfirmationIntent()`:
+
+Обязательные параметры метода:
+- context (Context) - контекст приложения;
+- confirmationUrl (String) - URL для перехода на 3DS;
+- paymentMethodType (PaymentMethodType) - выбранный тип платежного метода (тот, что был получен в методе `createTokenizationResult()`, (см. [Получить результат токенизации](#получить-результат-токенизации)) .
+
+Опциональные параметры метода:
+- testParameters (TestParameters) - параметры для тестового режима - включить логирование/использовать mock-данные, (см. [Настройка логирования и mock режима](#настройка-логирования-и-mock-режима));
+- colorScheme (ColorScheme) - цветовая схема, (см. [Настройка интерфейса](#настройка-интерфейса)).
+
+Возможные типы результата проведения 3DSecure:
+
+- Activity.RESULT_OK - сообщает о том, что процесс 3ds завершён, но не несет информацию о том, что процесс завершился успешно. После получения результата рекомендуется запросить статус платежа;
+- Activity.RESULT_CANCELED - прохождение 3ds было отменено (например, пользователь нажал на кнопку "назад" во время процесса);
+- Checkout.RESULT_ERROR - не удалось пройти 3ds.
+
+**Запуск 3ds и получение результата**
+
+
+ Kotlin
-Kotlin:
```kotlin
class MyActivity : AppCompatActivity() {
- fun timeToStart3DS() {
+ fun start3DSecure() {
val intent = createConfirmationIntent(this, "https://3dsurl.com/", PaymentMethodType.BANK_CARD)
- startActivityForResult(intent, 1)
+ startActivityForResult(intent, REQUEST_CODE_CONFIRM)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
- if (requestCode == 1) {
+ if (requestCode == REQUEST_CODE_CONFIRM) {
when (resultCode) {
- RESULT_OK -> return // Процесс 3ds завершён
- RESULT_CANCELED -> return // экран 3ds был закрыт
+ RESULT_OK -> {
+ // Процесс 3ds завершён, нет информации о том, завершился процесс с успехом или нет
+ // Рекомендуется запросить статус платежа
+ return
+ }
+ RESULT_CANCELED -> return // Экран 3ds был закрыт
Checkout.RESULT_ERROR -> {
- // во время 3ds произошла какая-то ошибка (нет соединения или что-то еще)
- // более подробную информацию можно посмотреть в data
+ // Во время 3ds произошла какая-то ошибка (нет соединения или что-то еще)
+ // Более подробную информацию можно посмотреть в data
// data.getIntExtra(Checkout.EXTRA_ERROR_CODE) - код ошибки из WebViewClient.ERROR_* или Checkout.ERROR_NOT_HTTPS_URL
// data.getStringExtra(Checkout.EXTRA_ERROR_DESCRIPTION) - описание ошибки (может отсутствовать)
// data.getStringExtra(Checkout.EXTRA_ERROR_FAILING_URL) - url по которому произошла ошибка (может отсутствовать)
@@ -568,12 +1030,357 @@ class MyActivity : AppCompatActivity() {
}
}
```
+
+
+
+ Java
+
+```java
+class MyActivity extends AppCompatActivity {
+
+ void start3DSecure() {
+ Intent intent = Checkout.createConfirmationIntent(this, "https://3dsurl.com/", PaymentMethodType.BANK_CARD);
+ startActivityForResult(intent, REQUEST_CODE_CONFIRM);
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (requestCode == REQUEST_CODE_CONFIRM) {
+ switch (resultCode) {
+ case RESULT_OK:
+ // Процесс 3ds завершён, нет информации о том, завершился процесс с успехом или нет
+ // Рекомендуется запросить статус платежа
+ break;
+ case RESULT_CANCELED:
+ // Экран 3ds был закрыт
+ break;
+ case Checkout.RESULT_ERROR:
+ // Во время 3ds произошла какая-то ошибка (нет соединения или что-то еще)
+ // Более подробную информацию можно посмотреть в data
+ // data.getIntExtra(Checkout.EXTRA_ERROR_CODE) - код ошибки из WebViewClient.ERROR_* или Checkout.ERROR_NOT_HTTPS_URL
+ // data.getStringExtra(Checkout.EXTRA_ERROR_DESCRIPTION) - описание ошибки (может отсутствовать)
+ // data.getStringExtra(Checkout.EXTRA_ERROR_FAILING_URL) - url по которому произошла ошибка (может отсутствовать)
+ break;
+ }
+ }
+ }
+}
+```
+
+
+## Привязанная карта
+
+Для того, чтобы после токенизации банковской картой эта банковская карта привязалась и отобразилась у пользователя в списке методов оплаты, необходимо в метод для токенизации (см. [Запуск токенизации банковской картой](#запуск-токенизации-банковской-картой)) передать опциональный параметр `customerId`. Карта привязывается исключительно тогда, когда пользователь дает согласие на ее привязку.
+- customerId (String) - уникальный идентификатор покупателя в вашей системе, например, электронная почта или номер телефона. Есть ограничение на длину - не более 200 символов.
+**Убедитесь, что customerId относится к пользователю, который хочет совершить покупку. Например, используйте двухфакторную аутентификацию. Если передать неверный идентификатор, пользователь сможет выбрать для оплаты чужие банковские карты.**
+
+Таким образом, метод для проведения токенизации банковской карты с привязкой этой банковской карты выглядит слкдующим образом:
+
+
+ Kotlin
+
+```kotlin
+class MyActivity : AppCompatActivity() {
+
+ fun startLinkedBankCardTokenize() {
+ val paymentParameters = PaymentParameters(
+ amount = Amount(BigDecimal.TEN, Currency.getInstance("RUB")),
+ title = "Название товара",
+ subtitle = "Описание товара",
+ clientApplicationKey = "live_thisKeyIsNotReal", // ключ для клиентских приложений из личного кабинета ЮKassa (https://yookassa.ru/my/api-keys-settings)
+ shopId = "12345", // идентификатор магазина ЮKassa
+ savePaymentMethod = SavePaymentMethod.OFF, // флаг выключенного сохранения платежного метода,
+ paymentMethodTypes = setOf(PaymentMethodType.BANK_CARD), // выбранный способ оплаты - банковская карта,
+ customerId = "uniqueCustomerId" // уникальный идентификатор покупателя в вашей системе
+ )
+ val intent = createTokenizeIntent(this, paymentParameters)
+ startActivityForResult(intent, REQUEST_CODE_TOKENIZE)
+ }
+}
+```
+
+
+
+ Java
+
+```java
+class MyActivity extends AppCompatActivity {
+
+ void startLinkedBankCardTokenize() {
+ Set paymentMethodTypes = new HashSet<>();
+ PaymentParameters paymentParameters = new PaymentParameters(
+ new Amount(BigDecimal.TEN, Currency.getInstance("RUB")),
+ "Название товара",
+ "Описание товара",
+ "live_thisKeyIsNotReal", // ключ для клиентских приложений из личного кабинета ЮKassa (https://yookassa.ru/my/api-keys-settings)
+ "12345", // идентификатор магазина юKassa
+ SavePaymentMethod.OFF, // флаг выключенного сохранения платежного метода
+ paymentMethodTypes.add(PaymentMethodType.BANK_CARD), // выбранный способ оплаты - банковская карта
+ "gatewayId", // gatewayId магазина для платежей Google Pay (необходим в случае, если в способах оплаты есть Google Pay)
+ "https://custom.redirect.url", // url страницы (поддерживается только https), на которую надо вернуться после прохождения 3ds. Должен использоваться только при при использовании своего Activity для 3ds url.
+ "+79041234567", // номер телефона пользователя. Используется для автозаполнения поля при оплате через SberPay. Поддерживаемый формат данных: "+7XXXXXXXXXX".
+ null, // настройки для токенизации через GooglePay,
+ "example_authCenterClientId", // идентификатор, полученный при регистрации приложения на сайте https://yookassa.ru
+ "uniqueCustomerId" // уникальный идентификатор покупателя в вашей системе
+ );
+ Intent intent = Checkout.createTokenizeIntent(this, paymentParameters);
+ startActivityForResult(intent, REQUEST_CODE_TOKENIZE);
+ }
+}
+```
+
+
+Для того, чтобы посмотреть, как будет выглядеть привязанная карта на экране списка методов оплаты, можно воспользоваться тестовым режимом.
+Необходимо задать в параметре `linkedCardsCount` объекта `MockConfiguration` количество карт и вызвать метод `createTokenizeIntent`. Подробнее можно почитать в разделе [Настройка логирования и mock режима](#настройка-логирования-и-mock-режима)
+
+## Рекуррентные платежи
+
+Рекуррентные платежи - это платежи, которые повторяются по определенному расписанию. Списания при таких платежах происходят автоматически после согласия пользователя.
+
+Вы можете сохранять некоторые способы оплаты и использовать их для повторных списаний. В этом случае пользователю нужно подтвердить только первый платеж — последующие списания будут безакцептными. [Подробнее можно прочитать тут](https://yookassa.ru/developers/payments/recurring-payments)
+
+Для включения автоплатежа, нужно при [токенизации](#токенизация) передать в параметр `savePaymentMethod` одно из значений:
+- `SavePaymentMethod.ON` - сохранить платёжный метод для проведения рекуррентных платежей. Пользователю будут доступны только способы оплаты, поддерживающие сохранение. На экране выбранного способа оплаты будет отображено сообщение о том, что платёжный метод будет сохранён.
+![SavePaymentMethod.ON](assets/images/recurrent-payments/save-payment-method-on.png)
+- `SavePaymentMethod.USER_SELECTS` - пользователь выбирает, сохранять платёжный метод или нет. Если метод можно сохранить, на экране выбранного способа оплаты появится переключатель.
+![SavePaymentMethod.USER_SELECTS](assets/images/recurrent-payments/save-payment-method-user-selects.png)
+
+
+ Kotlin
+
+```kotlin
+class MyActivity : AppCompatActivity() {
+
+ fun startTokenize() {
+ val paymentParameters = PaymentParameters(
+ amount = Amount(BigDecimal.TEN, Currency.getInstance("RUB")),
+ title = "Название товара",
+ subtitle = "Описание товара",
+ clientApplicationKey = "live_thisKeyIsNotReal", // ключ для клиентских приложений из личного кабинета ЮKassa (https://yookassa.ru/my/api-keys-settings)
+ shopId = "12345", // идентификатор магазина ЮKassa
+ savePaymentMethod = SavePaymentMethod.ON, // флаг включения сохранения платежного метода
+ authCenterClientId = "example_authCenterClientId", // идентификатор, полученный при регистрации приложения на сайте https://yookassa.ru
+ gatewayId = "gatewayId", // gatewayId магазина для платежей Google Pay (необходим в случае, если в способах оплаты есть Google Pay)
+ customReturnUrl = "https://custom.redirect.url", // url страницы (поддерживается только https), на которую надо вернуться после прохождения 3ds. Должен использоваться только при при использовании своего Activity для 3ds url.
+ userPhoneNumber = "+79041234567", // номер телефона пользователя. Используется для автозаполнения поля при оплате через SberPay. Поддерживаемый формат данных: "+7XXXXXXXXXX".
+ )
+ val intent = createTokenizeIntent(this, paymentParameters)
+ startActivityForResult(intent, REQUEST_CODE_TOKENIZE)
+ }
+}
+```
+
+
+
+ Java
+
+```java
+class MyActivity extends AppCompatActivity {
+
+ void startTokenize() {
+ PaymentParameters paymentParameters = new PaymentParameters(
+ new Amount(BigDecimal.TEN, Currency.getInstance("RUB")),
+ "Название товара",
+ "Описание товара",
+ "live_thisKeyIsNotReal", // ключ для клиентских приложений из личного кабинета ЮKassa
+ "12345", // идентификатор магазина ЮKassa
+ SavePaymentMethod.ON, // флаг включения сохранения платежного метода
+ null, // передан весь список доступных методов оплаты
+ "gatewayId", // gatewayId магазина для платежей Google Pay (необходим в случае, если в способах оплаты есть Google Pay)
+ "https://custom.redirect.url", // url страницы (поддерживается только https), на которую надо вернуться после прохождения 3ds. Должен использоваться только при при использовании своего Activity для 3ds url.
+ "+79041234567", // номер телефона пользователя. Используется для автозаполнения поля при оплате через SberPay. Поддерживаемый формат данных: "+7XXXXXXXXXX".
+ null, // настройки для токенизации через GooglePay,
+ "example_authCenterClientId" // идентификатор, полученный при регистрации приложения на сайте https://yookassa.ru
+ );
+ Intent intent = Checkout.createTokenizeIntent(this, paymentParameters);
+ startActivityForResult(intent, REQUEST_CODE_TOKENIZE);
+ }
+}
+```
+
+
+> После получения токена для рекуррентного платежа, проведите платёж и [следуйте инструкциям](https://yookassa.ru/developers/payments/recurring-payments#process)
+
+## Настройка логирования и mock режима
+
+#### Включение логирования
+
+Для отладки вам может понадобиться включить логи в sdk. Для этого нужно при запуске токенизации передать параметр `showLogs = true` в `TestParameters`
+
+
+ Kotlin
+
+```kotlin
+class MyActivity : AppCompatActivity() {
+
+ fun startTokenize() {
+ val testParameters = TestParameters(
+ showLogs = true // showLogs - включить/выключить отображение логов sdk
+ )
+ val intent = createTokenizeIntent(this, paymentParameters, testParameters)
+ startActivityForResult(intent, REQUEST_CODE_TOKENIZE)
+ }
+}
+```
+
+
+
+ Java
+
+```java
+class MyActivity extends AppCompatActivity {
+
+ void startTokenize() {
+ TestParameters testParameters = new TestParameters(
+ true // showLogs - включить/выключить отображение логов sdk
+ );
+ Intent intent = Checkout.createTokenizeIntent(this, paymentParameters, testParameters);
+ startActivityForResult(intent, REQUEST_CODE_TOKENIZE);
+ }
+}
+```
+
+
+> Обратите внимание, что логи будут выводиться только в debug приложении. Для релизной сборки приложения этот флаг передавать не нужно
+
+#### Настройка mock режима
+
+В библиотеке есть mock-режим, с помощью которого можно посмотреть, как будет выглядеть работа SDK при различных входных данных. Для работы этого режима не нужен доступ в интернет. Полученный токен нельзя использовать для оплаты.
+
+Поля класса `MockConfiguration`:
+- `completeWithError` (Boolean) - токенизация всегда возвращает ошибку;
+- `paymentAuthPassed` (Boolean) - авторизован пользователь или нет, для оплаты кошельком;
+- `linkedCardsCount` (Int) - количество карт, привязанных к кошельку пользователя;
+- `serviceFee` (Amount) - комиссия, которая будет отображена на экране выбранного способа оплаты;
+
+Для запуска токенизации с mock-режимом нужно передать параметр `mockConfiguration` в `TestParameters`
+
+
+ Kotlin
+
+```kotlin
+class MyActivity : AppCompatActivity() {
+
+ fun startTokenize() {
+ val testParameters = TestParameters(
+ showLogs = true, // showLogs - включить/выключить отображение логов sdk
+ googlePayTestEnvironment = true, // googlePayTestEnvironment - какую, тестовую или боевую, среду нужно использовать для Google Pay, подробнее можно почитать тут: https://developers.google.com/pay/api/android/guides/test-and-deploy/integration-checklist
+ mockConfiguration = MockConfiguration(
+ completeWithError = true, // completeWithError - возвращать всегда при токенизации ошибку
+ paymentAuthPassed = true, // paymentAuthPassed - авторизован пользователь или нет, для оплаты кошельком
+ linkedCardsCount = 3, // linkedCardsCount - количество карт, привязанных к кошельку пользователя;
+ serviceFee = Amount(BigDecimal.ONE, Currency.getInstance("RUB")) // serviceFee - комиссия, которая будет отображена на экране выбранного способа оплаты
+ )
+ )
+ val intent = createTokenizeIntent(this, paymentParameters, testParameters)
+ startActivityForResult(intent, REQUEST_CODE_TOKENIZE)
+ }
+}
+```
+
+
+
+ Java
+
+```java
+class MyActivity extends AppCompatActivity {
+
+ void startTokenize() {
+ MockConfiguration mockConfiguration = new MockConfiguration(
+ true, // completeWithError - возвращать всегда при токенизации ошибку
+ true, // paymentAuthPassed - авторизован пользователь или нет, для оплаты кошельком
+ 3,// linkedCardsCount - количество карт, привязанных к кошельку пользователя;
+ new Amount(BigDecimal.ONE, Currency.getInstance("RUB")) // serviceFee - комиссия, которая будет отображена на экране выбранного способа оплаты
+ );
+ TestParameters testParameters = new TestParameters(
+ true, // showLogs - включить/выключить отображение логов sdk
+ true, // googlePayTestEnvironment - какую, тестовую или боевую, среду нужно использовать для Google Pay, подробнее можно почитать тут: https://developers.google.com/pay/api/android/guides/test-and-deploy/integration-checklist
+ mockConfiguration
+ );
+ Intent intent = Checkout.createTokenizeIntent(this, paymentParameters, testParameters);
+ startActivityForResult(intent, REQUEST_CODE_TOKENIZE);
+ }
+}
+```
+
+
+## Настройка интерфейса
+
+Для настройки интерфейса SDK можно использовать объект `UiParameters`, а именно, можно настроить основной цвет интерфейса и настроить отображение логотипа ЮKassa на экране списка способов оплаты (скрыть или показать).
+
+Поля класса `UiParameters`:
+* showLogo (Boolean) - показать или скрыть логотип ЮKassa на экране списка способов оплаты;
+* colorScheme (ColorScheme) - цветовая схема mSdk в вашем приложении.
+
+Поля класса `ColorScheme`:
+* primaryColor (ColorInt) - основной цвет приложения. В этот цвет будут краситься кнопки, переключатели, поля для ввода и т.д.
+ Не рекомендуется задавать в качестве этого цвета слишком светлые цвета для светлой темы, так как они будут не видны на белом фоне, и темные цвета для темной темы, так как они не будуут видны на темном фоне, и красный цвет, так как он будет пересекаться с цветом ошибки.
+
+| С иконкой | Без иконки |
+| ------------- |:------------------:|
+| ![Список платежей с иконкой](assets/images/custom_ui_parameters_examples/1_show_logo_true.png) | ![Список плтажей без иконки](assets/images/custom_ui_parameters_examples/2_show_logo_false.png) |
+
+| Корректный кастомный цвет | Некорректный кастомный цвет |
+| ------------- |:------------------:|
+| ![Корректный цвет](assets/images/custom_ui_parameters_examples/3_good_color_example.png) | ![Некорректный цвет](assets/images/custom_ui_parameters_examples/4_bad_color_example.png) |
+
+
+ Kotlin
+
+```kotlin
+class MyActivity : AppCompatActivity() {
+
+ fun tokenizeCustomUiParameters() {
+ val paymentParameters = PaymentParameters(...)
+ val uiParameters = UiParameters(
+ showLogo = true,
+ colorScheme = ColorScheme(Color.rgb(0, 114, 245))
+ ) // передаем флаг true для того, чтобы логотип ЮKassa отобразился на экране списка способов оплаты, передаем ColorScheme, в котором находится кастомный цвет
+ val intent = createTokenizeIntent(
+ context = this,
+ paymentParameters = paymentParameters,
+ uiParameters = uiParameters
+ )
+ startActivityForResult(intent, REQUEST_CODE_TOKENIZE)
+ }
+}
+```
+
+
+
+ Java
+
+```java
+class MyActivity extends AppCompatActivity {
+
+ void tokenizeCustomUiParameters() {
+ PaymentParameters paymentParameters = new PaymentParameters(...);
+ UiParameters uiParameters = new UiParameters(true, new ColorScheme(Color.rgb(0, 114, 245))); // передаем флаг true для того, чтобы логотип ЮKassa отобразился на экране списка способов оплаты, передаем ColorScheme, в котором находится кастомный цвет
+ Intent intent = Checkout.createTokenizeIntent(
+ this,
+ paymentParameters,
+ null, // параметры для тестового режима - включить логирование/использовать mock-данные
+ uiParameters
+ );
+ startActivityForResult(intent, REQUEST_CODE_TOKENIZE);
+ }
+}
+
+```
+
## Сканирование банковской карты
-Создайте `Activity`, обрабатывающую action `ru.yoomoney.sdk.kassa.payments.action.SCAN_BANK_CARD`
+В sdk есть возможность подключить библиотеку для сканирования карт с помощью камеры. Если подключить сканирование, то на форме ввода номера банковской карты появится специальная кнопка ![Иконка сканирования карты](assets/images/scan-bank-card/icon-scanner.png):
+
+![Экран ввода данных банковской карты](assets/images/scan-bank-card/bank-card-form-with-scan.png)
-***Подключение activity для сканирования***
+При нажатии на эту кнопку sdk запустит `intent` для запуска `activity` в котором реализовано сканирование карт.
+>В самом sdk сканирование карты не реализовано, вместо этого предлагается реализовать сканирование в `activity` с помощью сторонней библиотеки.
+
+Для этого, создайте `activity` которое будет обрабатывать action `ru.yoomoney.sdk.kassa.payments.action.SCAN_BANK_CARD`
+
+И зарегистрируйте это `activity` в `AndroidManifest.xml`, с указанием `intent-filter` для action `ru.yoomoney.sdk.kassa.payments.action.SCAN_BANK_CARD`:
```xml
@@ -584,34 +1391,174 @@ class MyActivity : AppCompatActivity() {
```
-В этой `Activity` запустите Вашу библиотеку для сканирования карты.
-Полученный номер карты передайте c помощью `Intent`, как показано в примере ниже.
-Не забудьте поставить `Activity.RESULT_OK`, если сканирование прошло успешно.
+Теперь при клике на кнопку сканирования карты ![Иконка сканирования карты](assets/images/scan-bank-card/icon-scanner.png), будет запускаться ваша `activity`, в ней нужно реализовать сканирование карты и завершить `activity`, передав результат работы с помощью метода `setResult`.
+
+Для этого перед завершением работы `activity` вызовите метод `Checkout.createScanBankCardResult`, передав туда номер карты и опциональные параметры месяц/год и передайте в метод `setResult`. После чего вызовите метод `finish()`
+
+
+ Kotlin
+
+```kotlin
+class ScanBankCardActivity : Activity() {
+
+ private fun onScanningDone(cardNumber: String, expirationMonth: Int, expirationYear: Int) {
+ val result: Intent = Checkout.createScanBankCardResult(cardNumber, expirationMonth, expirationYear)
+ setResult(RESULT_OK, result)
+ finish()
+ }
+}
+```
+
+
+
+ Java
-***Возвращение результата с activity***
Java:
```java
-public class ScanBankCardActivity extends Activity {
-
+class ScanBankCardActivity extends Activity {
+
private void onScanningDone(final String cardNumber, final int expirationMonth, final int expirationYear) {
final Intent result = Checkout.createScanBankCardResult(cardNumber, expirationMonth, expirationYear);
setResult(Activity.RESULT_OK, result);
finish();
}
}
-
```
-Kotlin:
+
+
+#### Пример реализации `activity` для сканирования данных карты
+Ниже приведён пример реализации сканирования данных карты с помощью сторонней библиотеки card.io: https://github.com/card-io/card.io-Android-SDK
+Можно использовать любую другую подходящую вам библиотеку или решение.
+
+
+ Kotlin
+
```kotlin
class ScanBankCardActivity : Activity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ ActivityCompat.requestPermissions(this, arrayOf(permission.CAMERA), REQUEST_CODE)
+ }
- private fun onScanningDone(cardNumber: String, expirationMonth: Int, expirationYear: Int) {
- val result: Intent = Checkout.createScanBankCardResult(cardNumber, expirationMonth, expirationYear)
- setResult(RESULT_OK, result)
- finish()
+ override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults)
+ if (requestCode == REQUEST_CODE) {
+ if (grantResults[0] == PackageManager.PERMISSION_DENIED
+ && !ActivityCompat.shouldShowRequestPermissionRationale(this, permission.CAMERA)
+ ) {
+ Toast.makeText(
+ this,
+ "Выдайте разрешение на использование камеры в настройках",
+ Toast.LENGTH_SHORT
+ ).show()
+ finish()
+ } else {
+ val scanIntent = Intent(this, CardIOActivity::class.java)
+ scanIntent.putExtra(CardIOActivity.EXTRA_REQUIRE_EXPIRY, true)
+ startActivityForResult(scanIntent, REQUEST_CODE)
+ }
+ }
+ }
+
+ override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+ super.onActivityResult(requestCode, resultCode, data)
+ if (requestCode == REQUEST_CODE) {
+ if (data != null && data.hasExtra(CardIOActivity.EXTRA_SCAN_RESULT)) {
+ val scanResult: CreditCard = requireNotNull(data.getParcelableExtra(CardIOActivity.EXTRA_SCAN_RESULT))
+ val cardNumber = scanResult.formattedCardNumber
+ if (scanResult.isExpiryValid && scanResult.redactedCardNumber != null
+ && scanResult.redactedCardNumber.isNotEmpty()
+ ) {
+ val scanBankCardResult = createScanBankCardIntent(
+ cardNumber,
+ scanResult.expiryMonth,
+ scanResult.expiryYear % 100
+ )
+ setResult(RESULT_OK, scanBankCardResult)
+ } else {
+ setResult(RESULT_CANCELED)
+ }
+ } else {
+ setResult(RESULT_CANCELED)
+ }
+ finish()
+ }
+ }
+
+ companion object {
+ const val REQUEST_CODE = 1
+ }
+}
+```
+
+
+
+ Java
+
+```java
+public class ScanBankCardActivity extends AppCompatActivity {
+
+ public static final int REQUEST_CODE = 1;
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ ActivityCompat.requestPermissions(this, new String[]{ CAMERA }, REQUEST_CODE);
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+
+ if (requestCode == REQUEST_CODE) {
+ if (grantResults[0] == PackageManager.PERMISSION_DENIED
+ && !ActivityCompat.shouldShowRequestPermissionRationale(this, CAMERA)
+ ) {
+ Toast.makeText(
+ this,
+ "Выдайте разрешение на использование камеры в настройках",
+ Toast.LENGTH_SHORT
+ ).show();
+
+ finish();
+ } else {
+ Intent scanIntent = new Intent(this, CardIOActivity.class);
+ scanIntent.putExtra(CardIOActivity.EXTRA_REQUIRE_EXPIRY, true);
+ startActivityForResult(scanIntent, REQUEST_CODE);
+ }
+ }
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ if (requestCode == REQUEST_CODE) {
+ if (data != null && data.hasExtra(CardIOActivity.EXTRA_SCAN_RESULT)) {
+ CreditCard scanResult = data.getParcelableExtra(CardIOActivity.EXTRA_SCAN_RESULT);
+ final String cardNumber = scanResult.getFormattedCardNumber();
+
+ if (scanResult.isExpiryValid() && scanResult.getRedactedCardNumber() != null &&
+ !scanResult.getRedactedCardNumber().isEmpty()) {
+ final Intent scanBankCardResult = Checkout.createScanBankCardIntent(
+ cardNumber,
+ scanResult.expiryMonth,
+ scanResult.expiryYear % 100
+ );
+ setResult(RESULT_OK, scanBankCardResult);
+ } else {
+ setResult(RESULT_CANCELED);
+ }
+ } else {
+ setResult(RESULT_CANCELED);
+ }
+ finish();
+ }
}
}
```
+
# Полезные ссылки
* [Сайт ЮKassa](https://yookassa.ru)
diff --git a/assets/images/custom_ui_parameters_examples/1_show_logo_true.png b/assets/images/custom_ui_parameters_examples/1_show_logo_true.png
new file mode 100644
index 0000000..ad0ccd1
Binary files /dev/null and b/assets/images/custom_ui_parameters_examples/1_show_logo_true.png differ
diff --git a/assets/images/custom_ui_parameters_examples/2_show_logo_false.png b/assets/images/custom_ui_parameters_examples/2_show_logo_false.png
new file mode 100644
index 0000000..7897ff6
Binary files /dev/null and b/assets/images/custom_ui_parameters_examples/2_show_logo_false.png differ
diff --git a/assets/images/custom_ui_parameters_examples/3_good_color_example.png b/assets/images/custom_ui_parameters_examples/3_good_color_example.png
new file mode 100644
index 0000000..aa2bac7
Binary files /dev/null and b/assets/images/custom_ui_parameters_examples/3_good_color_example.png differ
diff --git a/assets/images/custom_ui_parameters_examples/4_bad_color_example.png b/assets/images/custom_ui_parameters_examples/4_bad_color_example.png
new file mode 100644
index 0000000..55f0ed6
Binary files /dev/null and b/assets/images/custom_ui_parameters_examples/4_bad_color_example.png differ
diff --git a/assets/images/diagrams/base_flow_diagram.png b/assets/images/diagrams/base_flow_diagram.png
new file mode 100644
index 0000000..205d099
Binary files /dev/null and b/assets/images/diagrams/base_flow_diagram.png differ
diff --git a/assets/images/diagrams/base_flow_diagram_en.png b/assets/images/diagrams/base_flow_diagram_en.png
new file mode 100644
index 0000000..1d2480b
Binary files /dev/null and b/assets/images/diagrams/base_flow_diagram_en.png differ
diff --git a/assets/images/pay-flow-examples/1_2_item_selection_pre_purchase_screen.png b/assets/images/pay-flow-examples/1_2_item_selection_pre_purchase_screen.png
new file mode 100644
index 0000000..4abcd96
Binary files /dev/null and b/assets/images/pay-flow-examples/1_2_item_selection_pre_purchase_screen.png differ
diff --git a/assets/images/pay-flow-examples/3_payment_method_screen.png b/assets/images/pay-flow-examples/3_payment_method_screen.png
new file mode 100644
index 0000000..68b1759
Binary files /dev/null and b/assets/images/pay-flow-examples/3_payment_method_screen.png differ
diff --git a/assets/images/pay-flow-examples/4_google_pay_api_payment_screen.png b/assets/images/pay-flow-examples/4_google_pay_api_payment_screen.png
new file mode 100644
index 0000000..e455b40
Binary files /dev/null and b/assets/images/pay-flow-examples/4_google_pay_api_payment_screen.png differ
diff --git a/assets/images/pay-flow-examples/5_post_purchase_screen.png b/assets/images/pay-flow-examples/5_post_purchase_screen.png
new file mode 100644
index 0000000..e6ce393
Binary files /dev/null and b/assets/images/pay-flow-examples/5_post_purchase_screen.png differ
diff --git a/assets/images/recurrent-payments/save-payment-method-on.png b/assets/images/recurrent-payments/save-payment-method-on.png
new file mode 100644
index 0000000..b48e1e8
Binary files /dev/null and b/assets/images/recurrent-payments/save-payment-method-on.png differ
diff --git a/assets/images/recurrent-payments/save-payment-method-user-selects.png b/assets/images/recurrent-payments/save-payment-method-user-selects.png
new file mode 100644
index 0000000..73268a1
Binary files /dev/null and b/assets/images/recurrent-payments/save-payment-method-user-selects.png differ
diff --git a/assets/images/scan-bank-card/bank-card-form-with-scan.png b/assets/images/scan-bank-card/bank-card-form-with-scan.png
new file mode 100644
index 0000000..1bcd00e
Binary files /dev/null and b/assets/images/scan-bank-card/bank-card-form-with-scan.png differ
diff --git a/assets/images/scan-bank-card/bank-card-form-without-scan.png b/assets/images/scan-bank-card/bank-card-form-without-scan.png
new file mode 100644
index 0000000..29138c6
Binary files /dev/null and b/assets/images/scan-bank-card/bank-card-form-without-scan.png differ
diff --git a/assets/images/scan-bank-card/icon-scanner.png b/assets/images/scan-bank-card/icon-scanner.png
new file mode 100644
index 0000000..5ce5891
Binary files /dev/null and b/assets/images/scan-bank-card/icon-scanner.png differ
diff --git a/build.gradle b/build.gradle
index 4163204..da744e7 100644
--- a/build.gradle
+++ b/build.gradle
@@ -28,7 +28,7 @@ allprojects {
applyFromFileIfExists('buildInternal.gradle')
buildscript {
- ext.kotlin_version = '1.4.32'
+ ext.kotlin_version = '1.5.21'
ext.dokka_version = '0.9.17'
ext.okhttp_version = '4.3.1'
ext.mockito_version = '2.19.0'
@@ -42,16 +42,16 @@ buildscript {
ext.material = '1.2.1'
ext.recyclerview = '1.1.0'
ext.constraintlayout = '2.0.1'
- ext.espresso_core = '3.3.0'
- ext.espresso_intents = '3.3.0'
- ext.espresso_web = '3.3.0'
+ ext.espresso_core = '3.4.0'
+ ext.espresso_intents = '3.4.0'
+ ext.espresso_web = '3.4.0'
ext.androidx_junit = '1.1.2'
- ext.target_sdk_version = 30
+ ext.target_sdk_version = 31
repositories {
google()
- jcenter()
+ mavenCentral()
maven { url "https://jitpack.io" }
def file = file("buildscriptDependencies.gradle")
if (file.exists()) {
@@ -60,7 +60,7 @@ buildscript {
}
dependencies {
- classpath 'com.android.tools.build:gradle:4.2.2'
+ classpath "com.android.tools.build:gradle:7.0.3"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.dokka:dokka-android-gradle-plugin:$dokka_version"
classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:2.6'
@@ -72,9 +72,8 @@ buildscript {
allprojects {
repositories {
google()
- jcenter()
mavenCentral()
- maven { url "http://pay.cards/maven" }
+ maven { url "https://pay.cards/maven" }
maven { url "https://jitpack.io" }
}
}
@@ -85,4 +84,4 @@ if (file("buildscriptDependencies.gradle").exists()) {
task clean(type: Delete) {
delete rootProject.buildDir
-}
+}
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index c6a44c6..2580fa0 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -24,4 +24,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip
\ No newline at end of file
diff --git a/library/build.gradle b/library/build.gradle
index e789dfd..1f38654 100644
--- a/library/build.gradle
+++ b/library/build.gradle
@@ -32,7 +32,7 @@ ext {
android {
compileSdkVersion target_sdk_version
- buildToolsVersion "30.0.2"
+ buildToolsVersion "31.0.0"
resourcePrefix 'ym_'
@@ -89,42 +89,5 @@ android {
}
}
-dependencies {
- implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
- implementation 'com.google.android.gms:play-services-wallet:18.1.2'
- implementation "androidx.appcompat:appcompat:$appcompat"
- implementation "com.google.android.material:material:$material"
- implementation "androidx.recyclerview:recyclerview:$recyclerview"
- implementation "androidx.constraintlayout:constraintlayout:$constraintlayout"
- implementation "com.squareup.okhttp3:okhttp:$okhttp_version"
- implementation "com.squareup.okhttp3:logging-interceptor:$okhttp_version"
- implementation 'com.yandex.android:mobmetricalib:3.21.0'
- implementation 'ru.tinkoff.decoro:decoro:1.5.0'
- implementation 'androidx.fragment:fragment-ktx:1.3.5'
-
- implementation 'commons-io:commons-io:2.5'
- implementation 'commons-codec:commons-codec:1.15'
- implementation "ru.yoomoney.sdk:march:$march_lib_version"
- implementation "ru.yoomoney.sdk.gui:ui-lib:$ui_lib_version"
- compileOnly fileTree(dir: "libs", include: ["profiling-tool.aar"])
- implementation ("ru.yoomoney.sdk.auth:auth:$yoo_sdk_auth_version")
-
- def daggerVersion = "2.35.1"
- implementation "com.google.dagger:dagger:$daggerVersion"
- kapt "com.google.dagger:dagger-compiler:$daggerVersion"
-
- testImplementation "junit:junit:$junit"
- testImplementation 'androidx.test:core:1.3.0'
- testImplementation "org.mockito:mockito-core:$mockito_version"
- testImplementation "com.nhaarman.mockitokotlin2:mockito-kotlin:2.0.0"
- testImplementation 'org.robolectric:robolectric:4.0.1'
- testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.3.7"
- testImplementation 'org.assertj:assertj-core:3.15.0'
- testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.3.7"
-}
-
-task copyTestClasses(type: Copy) {
- from "build/tmp/kotlin-classes/devDebugUnitTest"
- into "build/intermediates/classes/devDebug"
- exclude '*/META-INF/library_devDebug.kotlin_module'
-}
\ No newline at end of file
+apply from: 'buildDependencies.gradle'
+apply from: 'buildTestDependencies.gradle'
\ No newline at end of file
diff --git a/library/buildDependencies.gradle b/library/buildDependencies.gradle
new file mode 100644
index 0000000..4541fa9
--- /dev/null
+++ b/library/buildDependencies.gradle
@@ -0,0 +1,45 @@
+/*
+ * The MIT License (MIT)
+ * Copyright © 2022 NBCO YooMoney LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+ * associated documentation files (the “Software”), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
+ * following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
+ * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+dependencies {
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+ implementation 'com.google.android.gms:play-services-wallet:18.1.2'
+ implementation 'androidx.work:work-runtime:2.7.1'
+ implementation "androidx.appcompat:appcompat:$appcompat"
+ implementation "com.google.android.material:material:$material"
+ implementation "androidx.recyclerview:recyclerview:$recyclerview"
+ implementation "androidx.constraintlayout:constraintlayout:$constraintlayout"
+ implementation "com.squareup.okhttp3:okhttp:$okhttp_version"
+ implementation "com.squareup.okhttp3:logging-interceptor:$okhttp_version"
+ implementation 'com.yandex.android:mobmetricalib:4.1.1'
+ implementation 'ru.tinkoff.decoro:decoro:1.5.0'
+ implementation 'androidx.fragment:fragment-ktx:1.3.5'
+
+ implementation 'commons-io:commons-io:2.5'
+ implementation 'commons-codec:commons-codec:1.15'
+ implementation "ru.yoomoney.sdk:march:$march_lib_version"
+ implementation "ru.yoomoney.sdk.gui:ui-lib:$ui_lib_version"
+ implementation ("ru.yoomoney.sdk.auth:auth:$yoo_sdk_auth_version")
+
+ def daggerVersion = "2.35.1"
+ implementation "com.google.dagger:dagger:$daggerVersion"
+ kapt "com.google.dagger:dagger-compiler:$daggerVersion"
+}
\ No newline at end of file
diff --git a/library/src/main/java/ru/yoomoney/sdk/kassa/payments/metrics/UserAuthTokenTypeParamProvider.kt b/library/buildTestDependencies.gradle
similarity index 66%
rename from library/src/main/java/ru/yoomoney/sdk/kassa/payments/metrics/UserAuthTokenTypeParamProvider.kt
rename to library/buildTestDependencies.gradle
index ab04ba6..e2a6b9b 100644
--- a/library/src/main/java/ru/yoomoney/sdk/kassa/payments/metrics/UserAuthTokenTypeParamProvider.kt
+++ b/library/buildTestDependencies.gradle
@@ -1,6 +1,6 @@
/*
* The MIT License (MIT)
- * Copyright © 2020 NBCO YooMoney LLC
+ * Copyright © 2022 NBCO YooMoney LLC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
* associated documentation files (the “Software”), to deal in the Software without restriction, including
@@ -19,18 +19,13 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
-package ru.yoomoney.sdk.kassa.payments.metrics
-
-import ru.yoomoney.sdk.kassa.payments.paymentAuth.PaymentAuthTokenRepository
-
-internal class UserAuthTokenTypeParamProvider(
- private val paymentAuthTokenRepository: PaymentAuthTokenRepository
-) : () -> AuthTokenType {
-
- override fun invoke() = if (paymentAuthTokenRepository.isPaymentAuthPersisted) {
- AuthTokenTypeMultiple()
- } else {
- AuthTokenTypeSingle()
- }
-
-}
+dependencies {
+ testImplementation "junit:junit:$junit"
+ testImplementation 'androidx.test:core:1.4.0'
+ testImplementation "org.mockito:mockito-core:$mockito_version"
+ testImplementation "com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0"
+ testImplementation 'org.robolectric:robolectric:4.3.1'
+ testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.5.0"
+ testImplementation 'org.assertj:assertj-core:3.15.0'
+ testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.5.0"
+}
\ No newline at end of file
diff --git a/library/jacoco.gradle b/library/jacoco.gradle
index 45e9052..bddb5cb 100644
--- a/library/jacoco.gradle
+++ b/library/jacoco.gradle
@@ -22,7 +22,7 @@
apply plugin: 'jacoco'
jacoco {
- toolVersion = "0.7.9"
+ toolVersion = "0.8.6"
reportsDir = file("$buildDir/reports")
}
diff --git a/library/src/debug/AndroidManifest.xml b/library/src/debug/AndroidManifest.xml
index 8c5e7f1..9887226 100644
--- a/library/src/debug/AndroidManifest.xml
+++ b/library/src/debug/AndroidManifest.xml
@@ -20,8 +20,11 @@
-->
-
+
diff --git a/library/src/debug/res/xml/ym_network_security_config.xml b/library/src/debug/res/xml/ym_network_security_config.xml
new file mode 100644
index 0000000..c2577fb
--- /dev/null
+++ b/library/src/debug/res/xml/ym_network_security_config.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+ jenkins-ot.test.yamoney.ru
+ iva-test-cms1.yamoney.ru
+ stubohub.appb2b1.cloud.yooteam.ru
+ payment-api-v3.appb2b1.cloud.yooteam.ru
+
+
\ No newline at end of file
diff --git a/library/src/main/java/ru/yoomoney/sdk/kassa/payments/Checkout.kt b/library/src/main/java/ru/yoomoney/sdk/kassa/payments/Checkout.kt
index 2700d30..9944fd2 100644
--- a/library/src/main/java/ru/yoomoney/sdk/kassa/payments/Checkout.kt
+++ b/library/src/main/java/ru/yoomoney/sdk/kassa/payments/Checkout.kt
@@ -131,7 +131,7 @@ object Checkout {
return WebViewActivity.create(
context = context,
url = url,
- logParam = "screen3ds"
+ logParam = "openScreen3ds"
)
}
@@ -218,7 +218,7 @@ object Checkout {
WebViewActivity.create(
context = context,
url = confirmationUrl,
- logParam = "screen3ds"
+ logParam = "openScreen3ds"
)
}
}
diff --git a/library/src/main/java/ru/yoomoney/sdk/kassa/payments/contract/TokenizeAnalytics.kt b/library/src/main/java/ru/yoomoney/sdk/kassa/payments/contract/TokenizeAnalytics.kt
index f922a2b..d0d991d 100644
--- a/library/src/main/java/ru/yoomoney/sdk/kassa/payments/contract/TokenizeAnalytics.kt
+++ b/library/src/main/java/ru/yoomoney/sdk/kassa/payments/contract/TokenizeAnalytics.kt
@@ -21,57 +21,64 @@
package ru.yoomoney.sdk.kassa.payments.contract
+import ru.yoomoney.sdk.kassa.payments.checkoutParameters.PaymentParameters
import ru.yoomoney.sdk.kassa.payments.metrics.AuthType
-import ru.yoomoney.sdk.kassa.payments.metrics.ErrorScreenReporter
import ru.yoomoney.sdk.kassa.payments.metrics.Reporter
-import ru.yoomoney.sdk.kassa.payments.model.LinkedCard
-import ru.yoomoney.sdk.kassa.payments.model.BankCardPaymentOption
-import ru.yoomoney.sdk.kassa.payments.model.PaymentIdCscConfirmation
+import ru.yoomoney.sdk.kassa.payments.metrics.SavePaymentMethodProvider
import ru.yoomoney.sdk.march.Logic
import ru.yoomoney.sdk.march.Out
import ru.yoomoney.sdk.kassa.payments.metrics.TokenizeScheme
+import ru.yoomoney.sdk.kassa.payments.metrics.TokenizeSchemeParamProvider
import ru.yoomoney.sdk.kassa.payments.model.PaymentInstrumentBankCard
import ru.yoomoney.sdk.kassa.payments.model.PaymentOption
+private const val ACTION_SCREEN_PAYMENT_CONTRACT = "screenPaymentContract"
+private const val ACTION_SCREEN_PAYMENT_CONTRACT_ERROR = "screenErrorContract"
+private const val ACTION_LOGOUT = "actionLogout"
+
internal class ContractAnalytics(
private val reporter: Reporter,
- private val errorScreenReporter: ErrorScreenReporter,
private val businessLogic: Logic,
private val getUserAuthType: () -> AuthType,
+ private val paymentParameters: PaymentParameters,
+ private val tokenizeSchemeParamProvider: TokenizeSchemeParamProvider,
private val getTokenizeScheme: (PaymentOption, PaymentInstrumentBankCard?) -> TokenizeScheme
) : Logic {
override fun invoke(state: Contract.State, action: Contract.Action): Out {
val nameArgsPairs = when (action) {
- Contract.Action.Logout -> listOf("actionLogout" to null)
+ Contract.Action.Logout -> listOf(ACTION_LOGOUT to null)
is Contract.Action.LoadContractSuccess -> {
listOf(
- "screenPaymentContract" to listOf(
+ ACTION_SCREEN_PAYMENT_CONTRACT to listOf(
getUserAuthType(),
getTokenizeScheme(
action.outputModel.paymentOption,
action.outputModel.instrument
)
- ),
- when (action.outputModel.paymentOption) {
- is BankCardPaymentOption -> "screenBankCardForm" to listOf(getUserAuthType())
- is LinkedCard -> "screenLinkedCardForm" to null
- is PaymentIdCscConfirmation -> "screenRecurringCardForm" to null
- else -> null to null
- }
+ )
)
}
+ is Contract.Action.LoadContractFailed -> {
+ tokenizeSchemeParamProvider.invoke()?.let { tokenizeScheme ->
+ listOf(
+ ACTION_SCREEN_PAYMENT_CONTRACT_ERROR to listOf(
+ getUserAuthType(),
+ tokenizeScheme,
+ SavePaymentMethodProvider().invoke(paymentParameters)
+ )
+ )
+ }
+ }
else -> listOf(null to null)
}
- nameArgsPairs.forEach { pair ->
+ nameArgsPairs?.forEach { pair ->
pair.first?.let {
reporter.report(it, pair.second)
}
}
- errorScreenReporter.takeIf { action is Contract.Action.LoadContractFailed }?.report()
-
return businessLogic(state, action)
}
}
\ No newline at end of file
diff --git a/library/src/main/java/ru/yoomoney/sdk/kassa/payments/contract/di/ContractModule.kt b/library/src/main/java/ru/yoomoney/sdk/kassa/payments/contract/di/ContractModule.kt
index f713385..14d82af 100644
--- a/library/src/main/java/ru/yoomoney/sdk/kassa/payments/contract/di/ContractModule.kt
+++ b/library/src/main/java/ru/yoomoney/sdk/kassa/payments/contract/di/ContractModule.kt
@@ -66,7 +66,7 @@ import ru.yoomoney.sdk.kassa.payments.contract.ContractAnalytics
import ru.yoomoney.sdk.kassa.payments.contract.ContractBusinessLogic
import ru.yoomoney.sdk.kassa.payments.extensions.toTokenizeScheme
import ru.yoomoney.sdk.kassa.payments.http.HostProvider
-import ru.yoomoney.sdk.kassa.payments.metrics.UserAuthTokenTypeParamProvider
+import ru.yoomoney.sdk.kassa.payments.metrics.TokenizeSchemeParamProvider
import ru.yoomoney.sdk.kassa.payments.model.GetConfirmation
import ru.yoomoney.sdk.kassa.payments.paymentOptionList.ConfigUseCase
import ru.yoomoney.sdk.kassa.payments.paymentOptionList.ShopPropertiesRepository
@@ -170,12 +170,11 @@ internal class ContractModule {
testParameters: TestParameters,
logoutUseCase: LogoutUseCase,
reporter: Reporter,
- errorScreenReporter: ErrorScreenReporter,
userAuthTypeParamProvider: UserAuthTypeParamProvider,
getConfirmation: GetConfirmation,
loadedPaymentOptionListRepository: GetLoadedPaymentOptionListRepository,
userAuthInfoRepository: TokensStorage,
- paymentAuthTokenRepository: PaymentAuthTokenRepository,
+ tokenizeSchemeParamProvider: TokenizeSchemeParamProvider,
shopPropertiesRepository: ShopPropertiesRepository,
configRepository: ConfigRepository
): ViewModel {
@@ -191,7 +190,6 @@ internal class ContractModule {
logic = {
ContractAnalytics(
reporter = reporter,
- errorScreenReporter = errorScreenReporter,
businessLogic = ContractBusinessLogic(
paymentParameters = paymentParameters,
showState = showState,
@@ -205,7 +203,9 @@ internal class ContractModule {
userAuthInfoRepository = userAuthInfoRepository,
configRepository = configRepository
),
+ tokenizeSchemeParamProvider = tokenizeSchemeParamProvider,
getUserAuthType = userAuthTypeParamProvider,
+ paymentParameters = paymentParameters,
getTokenizeScheme = { paymentOption, paymentInstrument ->
paymentOption.toTokenizeScheme(context, sberbankPackage, paymentInstrument)
}
diff --git a/library/src/main/java/ru/yoomoney/sdk/kassa/payments/di/PaymentModule.kt b/library/src/main/java/ru/yoomoney/sdk/kassa/payments/di/PaymentModule.kt
index c644c7f..abe5576 100644
--- a/library/src/main/java/ru/yoomoney/sdk/kassa/payments/di/PaymentModule.kt
+++ b/library/src/main/java/ru/yoomoney/sdk/kassa/payments/di/PaymentModule.kt
@@ -22,7 +22,6 @@
package ru.yoomoney.sdk.kassa.payments.di
import android.content.Context
-import android.content.SharedPreferences
import dagger.Module
import dagger.Provides
import ru.yoomoney.sdk.kassa.payments.checkoutParameters.PaymentParameters
@@ -32,14 +31,9 @@ import ru.yoomoney.sdk.kassa.payments.extensions.CheckoutOkHttpClient
import ru.yoomoney.sdk.kassa.payments.http.HostProvider
import ru.yoomoney.sdk.kassa.payments.metrics.ErrorReporter
import ru.yoomoney.sdk.kassa.payments.secure.TokensStorage
-import ru.yoomoney.sdk.kassa.payments.payment.SharedPreferencesCurrentUserRepository
import ru.yoomoney.sdk.kassa.payments.paymentMethodInfo.ApiV3PaymentMethodInfoGateway
import ru.yoomoney.sdk.kassa.payments.paymentMethodInfo.MockPaymentInfoGateway
import ru.yoomoney.sdk.kassa.payments.payment.googlePay.GooglePayRepositoryImpl
-import ru.yoomoney.sdk.kassa.payments.payment.googlePay.MockGooglePayRepository
-import ru.yoomoney.sdk.kassa.payments.model.AuthorizedUser
-import ru.yoomoney.sdk.kassa.payments.model.CurrentUser
-import ru.yoomoney.sdk.kassa.payments.payment.CurrentUserRepository
import ru.yoomoney.sdk.kassa.payments.payment.GetLoadedPaymentOptionListRepository
import ru.yoomoney.sdk.kassa.payments.payment.googlePay.GooglePayRepository
import ru.yoomoney.sdk.kassa.payments.payment.loadPaymentInfo.PaymentMethodInfoGateway
@@ -78,18 +72,14 @@ internal class PaymentModule {
errorReporter: ErrorReporter,
configRepository: ConfigRepository
): GooglePayRepository {
- return if (testParameters.mockConfiguration != null) {
- MockGooglePayRepository(true)
- } else {
- GooglePayRepositoryImpl(
- context = context,
- shopId = paymentParameters.shopId,
- useTestEnvironment = testParameters.googlePayTestEnvironment,
- loadedPaymentOptionsRepository = getLoadedPaymentOptionListRepository,
- googlePayParameters = paymentParameters.googlePayParameters,
- errorReporter = errorReporter,
- getGateway = { configRepository.getConfig().gateway }
- )
- }
+ return GooglePayRepositoryImpl(
+ context = context,
+ shopId = paymentParameters.shopId,
+ useTestEnvironment = testParameters.googlePayTestEnvironment,
+ loadedPaymentOptionsRepository = getLoadedPaymentOptionListRepository,
+ googlePayParameters = paymentParameters.googlePayParameters,
+ errorReporter = errorReporter,
+ getGateway = { configRepository.getConfig().gateway }
+ )
}
}
\ No newline at end of file
diff --git a/library/src/main/java/ru/yoomoney/sdk/kassa/payments/di/PaymentOptionsModule.kt b/library/src/main/java/ru/yoomoney/sdk/kassa/payments/di/PaymentOptionsModule.kt
index fc77ce7..0a43ac4 100644
--- a/library/src/main/java/ru/yoomoney/sdk/kassa/payments/di/PaymentOptionsModule.kt
+++ b/library/src/main/java/ru/yoomoney/sdk/kassa/payments/di/PaymentOptionsModule.kt
@@ -30,7 +30,6 @@ import ru.yoomoney.sdk.kassa.payments.payment.PaymentMethodRepository
import ru.yoomoney.sdk.kassa.payments.checkoutParameters.PaymentParameters
import ru.yoomoney.sdk.kassa.payments.checkoutParameters.TestParameters
import ru.yoomoney.sdk.kassa.payments.config.ConfigRepository
-import ru.yoomoney.sdk.kassa.payments.secure.TokensStorage
import ru.yoomoney.sdk.kassa.payments.metrics.Reporter
import ru.yoomoney.sdk.kassa.payments.metrics.TokenizeSchemeParamProvider
import ru.yoomoney.sdk.kassa.payments.metrics.UserAuthTypeParamProvider
@@ -44,6 +43,7 @@ import ru.yoomoney.sdk.kassa.payments.payment.googlePay.GooglePayRepository
import ru.yoomoney.sdk.kassa.payments.payment.loadOptionList.PaymentOptionListRepository
import ru.yoomoney.sdk.kassa.payments.payment.loadPaymentInfo.PaymentMethodInfoGateway
import ru.yoomoney.sdk.kassa.payments.errorFormatter.ErrorFormatter
+import ru.yoomoney.sdk.kassa.payments.extensions.toTokenizeScheme
import ru.yoomoney.sdk.kassa.payments.model.GetConfirmation
import ru.yoomoney.sdk.kassa.payments.payment.unbindCard.UnbindCardGateway
import ru.yoomoney.sdk.kassa.payments.paymentOptionList.ConfigUseCase
@@ -57,6 +57,7 @@ import ru.yoomoney.sdk.kassa.payments.paymentOptionList.unbind.UnbindCardUseCase
import ru.yoomoney.sdk.kassa.payments.paymentOptionList.unbind.UnbindCardUseCaseImpl
import ru.yoomoney.sdk.kassa.payments.paymentOptionList.ShopPropertiesRepository
import ru.yoomoney.sdk.kassa.payments.paymentOptionList.ShopPropertiesRepositoryImpl
+import ru.yoomoney.sdk.kassa.payments.utils.getSberbankPackage
import ru.yoomoney.sdk.march.Out
import ru.yoomoney.sdk.march.RuntimeViewModel
import ru.yoomoney.sdk.march.input
@@ -141,6 +142,7 @@ internal class PaymentOptionsModule {
@[Provides IntoMap ViewModelKey(PAYMENT_OPTIONS)]
fun viewModel(
+ context: Context,
paymentOptionsListUseCase: PaymentOptionsListUseCase,
paymentParameters: PaymentParameters,
paymentMethodId: String?,
@@ -152,8 +154,10 @@ internal class PaymentOptionsModule {
unbindCardUseCase: UnbindCardUseCase,
shopPropertiesRepository: ShopPropertiesRepository,
configUseCase: ConfigUseCase,
+ testParameters: TestParameters,
configRepository: ConfigRepository
): ViewModel {
+ val sberbankPackage = getSberbankPackage(testParameters.hostParameters.isDevHost)
return RuntimeViewModel(
featureName = "PaymentOptionList",
initial = {
@@ -176,7 +180,11 @@ internal class PaymentOptionsModule {
getConfirmation = getConfirmation,
unbindCardUseCase = unbindCardUseCase,
shopPropertiesRepository = shopPropertiesRepository,
- configRepository = configRepository
+ configRepository = configRepository,
+ getTokenizeScheme = { paymentOption, paymentInstrument ->
+ paymentOption.toTokenizeScheme(context, sberbankPackage, paymentInstrument)
+ },
+ tokenizeSchemeProvider = tokenizeSchemeParamProvider
),
getUserAuthType = userAuthTypeParamProvider,
getTokenizeScheme = tokenizeSchemeParamProvider
diff --git a/library/src/main/java/ru/yoomoney/sdk/kassa/payments/extensions/PaymentOptionExtensions.kt b/library/src/main/java/ru/yoomoney/sdk/kassa/payments/extensions/PaymentOptionExtensions.kt
index 61d2219..f8344ed 100644
--- a/library/src/main/java/ru/yoomoney/sdk/kassa/payments/extensions/PaymentOptionExtensions.kt
+++ b/library/src/main/java/ru/yoomoney/sdk/kassa/payments/extensions/PaymentOptionExtensions.kt
@@ -25,10 +25,7 @@ package ru.yoomoney.sdk.kassa.payments.extensions
import android.content.Context
import android.graphics.drawable.InsetDrawable
-import android.net.Uri
import androidx.appcompat.content.res.AppCompatResources
-import com.squareup.picasso.Picasso
-import kotlinx.android.synthetic.main.ym_yoo_money_info_view.yooImage
import ru.yoomoney.sdk.kassa.payments.R
import ru.yoomoney.sdk.kassa.payments.metrics.TokenizeSchemeBankCard
import ru.yoomoney.sdk.kassa.payments.metrics.TokenizeSchemeGooglePay
diff --git a/library/src/main/java/ru/yoomoney/sdk/kassa/payments/logging/ReporterLogger.kt b/library/src/main/java/ru/yoomoney/sdk/kassa/payments/logging/ReporterLogger.kt
index a6c7061..a09a8f1 100644
--- a/library/src/main/java/ru/yoomoney/sdk/kassa/payments/logging/ReporterLogger.kt
+++ b/library/src/main/java/ru/yoomoney/sdk/kassa/payments/logging/ReporterLogger.kt
@@ -27,7 +27,11 @@ import ru.yoomoney.sdk.kassa.payments.metrics.Reporter
internal class ReporterLogger(private val reporter: Reporter) : Reporter {
override fun report(name: String, args: List?) {
- Log.d("ANALYTICS_EVENT", "$name ${args?.joinToString(",")}")
+ if (args == null) {
+ Log.d("ANALYTICS_EVENT", name)
+ } else {
+ Log.d("ANALYTICS_EVENT", "$name ${args.joinToString(",")}")
+ }
reporter.report(name, args)
}
@@ -35,4 +39,9 @@ internal class ReporterLogger(private val reporter: Reporter) : Reporter {
Log.d("ANALYTICS_EVENT", "$name - $arg")
reporter.report(name, arg)
}
+
+ override fun report(name: String, arg: Boolean) {
+ Log.d("ANALYTICS_EVENT", "$name - $arg")
+ reporter.report(name, arg)
+ }
}
diff --git a/library/src/main/java/ru/yoomoney/sdk/kassa/payments/metrics/MetricsProvider.kt b/library/src/main/java/ru/yoomoney/sdk/kassa/payments/metrics/MetricsProvider.kt
new file mode 100644
index 0000000..dd70697
--- /dev/null
+++ b/library/src/main/java/ru/yoomoney/sdk/kassa/payments/metrics/MetricsProvider.kt
@@ -0,0 +1,71 @@
+/*
+ * The MIT License (MIT)
+ * Copyright © 2021 NBCO YooMoney LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+ * associated documentation files (the “Software”), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
+ * following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
+ * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package ru.yoomoney.sdk.kassa.payments.metrics
+
+import android.graphics.Color
+import ru.yoomoney.sdk.kassa.payments.checkoutParameters.PaymentParameters
+import ru.yoomoney.sdk.kassa.payments.checkoutParameters.SavePaymentMethod
+import ru.yoomoney.sdk.kassa.payments.checkoutParameters.UiParameters
+import ru.yoomoney.sdk.kassa.payments.ui.color.ColorScheme
+import ru.yoomoney.sdk.kassa.payments.userAuth.UserAuthInfoRepository
+
+internal class SavePaymentMethodProvider : (PaymentParameters) -> SavePaymentMethodParam {
+
+ override fun invoke(parameters: PaymentParameters) = when (parameters.savePaymentMethod) {
+ SavePaymentMethod.OFF -> SavePaymentMethodOff()
+ SavePaymentMethod.ON -> SavePaymentMethodOn()
+ SavePaymentMethod.USER_SELECTS -> SavePaymentMethodUserSelect()
+ }
+}
+
+internal class YooKassaIconProvider : (UiParameters) -> YookassaIcon {
+
+ override fun invoke(
+ uiParameters: UiParameters
+ ) = if (uiParameters.showLogo) ShownYookassaIcon() else HiddenYookassaIcon()
+}
+
+internal class ColorMetricsProvider : (UiParameters) -> CustomColor {
+
+ override fun invoke(
+ uiParameters: UiParameters
+ ) = if (uiParameters.colorScheme.primaryColor == ColorScheme.defaultPrimaryColor) {
+ UsedDefaultColor()
+ } else {
+ UsedCustomColor()
+ }
+}
+
+internal class UserAttiributionOnInitProvider(
+ private val userAuthInfoRepository: UserAuthInfoRepository
+) : (PaymentParameters) -> UserAttiributionOnInit {
+
+ override fun invoke(
+ paymentParameters: PaymentParameters
+ ) = when {
+ paymentParameters.customerId != null && userAuthInfoRepository.userAuthToken != null -> AllAttributesOnInit()
+ paymentParameters.customerId != null -> CustomerIdOnInit()
+ userAuthInfoRepository.userAuthToken != null -> YooMoneyOnInit()
+ else -> NoneOnInit()
+ }
+}
+
diff --git a/library/src/main/java/ru/yoomoney/sdk/kassa/payments/metrics/Params.kt b/library/src/main/java/ru/yoomoney/sdk/kassa/payments/metrics/Params.kt
index f6cfc90..eaf7839 100644
--- a/library/src/main/java/ru/yoomoney/sdk/kassa/payments/metrics/Params.kt
+++ b/library/src/main/java/ru/yoomoney/sdk/kassa/payments/metrics/Params.kt
@@ -96,18 +96,6 @@ internal class AuthTypePaymentAuth : AuthType() {
override val value = "paymentAuth"
}
-internal sealed class AuthTokenType : Param() {
- final override val name = "authTokenType"
-}
-
-internal class AuthTokenTypeSingle : AuthTokenType() {
- override val value = "single"
-}
-
-internal class AuthTokenTypeMultiple : AuthTokenType() {
- override val value = "multiple"
-}
-
internal sealed class MoneyAuthLoginStatus : Param() {
final override val name = "moneyAuthLoginStatus"
}
@@ -178,4 +166,64 @@ internal sealed class SberPayConfirmationStatus : Param() {
internal class SberPayConfirmationStatusSuccess : SberPayConfirmationStatus() {
override val value = "Success"
+}
+
+internal sealed class SavePaymentMethodParam: Param() {
+ final override val name = "savePaymentMethod"
+}
+
+internal class SavePaymentMethodOn : SavePaymentMethodParam() {
+ override val value = "on"
+}
+
+internal class SavePaymentMethodOff : SavePaymentMethodParam() {
+ override val value = "off"
+}
+
+internal class SavePaymentMethodUserSelect : SavePaymentMethodParam() {
+ override val value = "userSelect"
+}
+
+internal sealed class UserAttiributionOnInit: Param() {
+ final override val name = "userAttiributionOnInit"
+}
+
+internal class AllAttributesOnInit : UserAttiributionOnInit() {
+ override val value = "YooMoney, CustomerId"
+}
+
+internal class CustomerIdOnInit : UserAttiributionOnInit() {
+ override val value = "CustomerId"
+}
+
+internal class YooMoneyOnInit : UserAttiributionOnInit() {
+ override val value = "YooMoney"
+}
+
+internal class NoneOnInit : UserAttiributionOnInit() {
+ override val value = "None"
+}
+
+internal sealed class CustomColor: Param() {
+ final override val name = "customColor"
+}
+
+internal class UsedCustomColor : CustomColor() {
+ override val value = "Custom"
+}
+
+internal class UsedDefaultColor : CustomColor() {
+ override val value = "Default"
+}
+
+internal sealed class YookassaIcon: Param() {
+ final override val name = "yookassaIcon"
+}
+
+internal class ShownYookassaIcon : YookassaIcon() {
+ override val value = "Shown"
+}
+
+internal class HiddenYookassaIcon : YookassaIcon() {
+ override val value = "Hidden"
}
\ No newline at end of file
diff --git a/library/src/main/java/ru/yoomoney/sdk/kassa/payments/metrics/Reporter.kt b/library/src/main/java/ru/yoomoney/sdk/kassa/payments/metrics/Reporter.kt
index fb54920..a3a3f1e 100644
--- a/library/src/main/java/ru/yoomoney/sdk/kassa/payments/metrics/Reporter.kt
+++ b/library/src/main/java/ru/yoomoney/sdk/kassa/payments/metrics/Reporter.kt
@@ -27,6 +27,7 @@ import ru.yoomoney.sdk.kassa.payments.model.UnhandledException
internal interface Reporter {
fun report(name: String, args: List? = null)
fun report(name: String, arg: String)
+ fun report(name: String, arg: Boolean)
}
internal interface ErrorReporter {
diff --git a/library/src/main/java/ru/yoomoney/sdk/kassa/payments/metrics/TokenizeSchemeParamProvider.kt b/library/src/main/java/ru/yoomoney/sdk/kassa/payments/metrics/TokenizeSchemeParamProvider.kt
index cd8a089..aab81ff 100644
--- a/library/src/main/java/ru/yoomoney/sdk/kassa/payments/metrics/TokenizeSchemeParamProvider.kt
+++ b/library/src/main/java/ru/yoomoney/sdk/kassa/payments/metrics/TokenizeSchemeParamProvider.kt
@@ -21,7 +21,7 @@
package ru.yoomoney.sdk.kassa.payments.metrics
-internal class TokenizeSchemeParamProvider : () -> TokenizeScheme? {
+internal open class TokenizeSchemeParamProvider : () -> TokenizeScheme? {
var tokenizeScheme: TokenizeScheme? = null
override operator fun invoke() = tokenizeScheme
diff --git a/library/src/main/java/ru/yoomoney/sdk/kassa/payments/metrics/YandexMetricaReporter.kt b/library/src/main/java/ru/yoomoney/sdk/kassa/payments/metrics/YandexMetricaReporter.kt
index fba9f55..fad34a2 100644
--- a/library/src/main/java/ru/yoomoney/sdk/kassa/payments/metrics/YandexMetricaReporter.kt
+++ b/library/src/main/java/ru/yoomoney/sdk/kassa/payments/metrics/YandexMetricaReporter.kt
@@ -47,6 +47,10 @@ internal class YandexMetricaReporter(
override fun report(name: String, arg: String) {
metrica.reportEvent(name, mapOf(arg to "") + mapOf("msdkVersion" to BuildConfig.VERSION_NAME))
}
+
+ override fun report(name: String, arg: Boolean) {
+ metrica.reportEvent(name, mapOf(arg.toString() to "") + mapOf("msdkVersion" to BuildConfig.VERSION_NAME))
+ }
}
internal class YandexMetricaErrorReporter(
diff --git a/library/src/main/java/ru/yoomoney/sdk/kassa/payments/paymentOptionList/PaymentOptionsListBusinessLogic.kt b/library/src/main/java/ru/yoomoney/sdk/kassa/payments/paymentOptionList/PaymentOptionsListBusinessLogic.kt
index 49559ef..faa5b38 100644
--- a/library/src/main/java/ru/yoomoney/sdk/kassa/payments/paymentOptionList/PaymentOptionsListBusinessLogic.kt
+++ b/library/src/main/java/ru/yoomoney/sdk/kassa/payments/paymentOptionList/PaymentOptionsListBusinessLogic.kt
@@ -24,25 +24,25 @@ package ru.yoomoney.sdk.kassa.payments.paymentOptionList
import ru.yoomoney.sdk.kassa.payments.checkoutParameters.PaymentParameters
import ru.yoomoney.sdk.kassa.payments.checkoutParameters.SavePaymentMethod
import ru.yoomoney.sdk.kassa.payments.config.ConfigRepository
-import ru.yoomoney.sdk.kassa.payments.contract.Contract
import ru.yoomoney.sdk.kassa.payments.logout.LogoutUseCase
+import ru.yoomoney.sdk.kassa.payments.metrics.TokenizeScheme
+import ru.yoomoney.sdk.kassa.payments.metrics.TokenizeSchemeParamProvider
import ru.yoomoney.sdk.kassa.payments.model.AbstractWallet
import ru.yoomoney.sdk.kassa.payments.model.BankCardPaymentOption
-import ru.yoomoney.sdk.kassa.payments.model.Config
import ru.yoomoney.sdk.kassa.payments.model.GetConfirmation
import ru.yoomoney.sdk.kassa.payments.model.LinkedCard
+import ru.yoomoney.sdk.kassa.payments.model.PaymentInstrumentBankCard
+import ru.yoomoney.sdk.kassa.payments.model.PaymentOption
import ru.yoomoney.sdk.kassa.payments.model.isSplitPayment
import ru.yoomoney.sdk.kassa.payments.payment.tokenize.TokenizeInstrumentInputModel
import ru.yoomoney.sdk.kassa.payments.paymentOptionList.PaymentOptionList.Action
import ru.yoomoney.sdk.kassa.payments.paymentOptionList.PaymentOptionList.Effect
import ru.yoomoney.sdk.kassa.payments.paymentOptionList.PaymentOptionList.State
import ru.yoomoney.sdk.kassa.payments.paymentOptionList.unbind.UnbindCardUseCase
-import ru.yoomoney.sdk.kassa.payments.unbind.UnbindCard
import ru.yoomoney.sdk.march.Logic
import ru.yoomoney.sdk.march.Out
import ru.yoomoney.sdk.march.input
import ru.yoomoney.sdk.march.output
-import javax.inject.Inject
internal class PaymentOptionsListBusinessLogic(
private val showState: suspend (State) -> Action,
@@ -55,10 +55,11 @@ internal class PaymentOptionsListBusinessLogic(
private val unbindCardUseCase: UnbindCardUseCase,
private val getConfirmation: GetConfirmation,
private val shopPropertiesRepository: ShopPropertiesRepository,
- private val configRepository: ConfigRepository
+ private val configRepository: ConfigRepository,
+ private val getTokenizeScheme: (PaymentOption, PaymentInstrumentBankCard?) -> TokenizeScheme,
+ private val tokenizeSchemeProvider: TokenizeSchemeParamProvider
) : Logic {
- private val currentConfig: Config get() = configRepository.getConfig()
private val currentLogoUrl: String get() = configRepository.getConfig().yooMoneyLogoUrlLight
override fun invoke(state: State, action: Action): Out = when (state) {
@@ -101,7 +102,17 @@ internal class PaymentOptionsListBusinessLogic(
}
}
is Action.ProceedWithPaymentMethod -> {
- when (val option = useCase.selectPaymentOption(action.optionId, action.instrumentId)) {
+ val option = useCase.selectPaymentOption(action.optionId, action.instrumentId)
+ option?.let { paymentOption ->
+ val instrumentBankCard = if (option is BankCardPaymentOption) {
+ option.paymentInstruments.firstOrNull { it.paymentInstrumentId == action.instrumentId }
+ } else {
+ null
+ }
+ tokenizeSchemeProvider.tokenizeScheme = getTokenizeScheme(paymentOption, instrumentBankCard)
+ }
+
+ when (option) {
is AbstractWallet -> {
Out(State.WaitingForAuthState(currentLogoUrl, this)) {
output { showEffect(Effect.RequireAuth) }
diff --git a/library/src/main/java/ru/yoomoney/sdk/kassa/payments/tokenize/TokenizeAnalytics.kt b/library/src/main/java/ru/yoomoney/sdk/kassa/payments/tokenize/TokenizeAnalytics.kt
index 4c750fe..3521014 100644
--- a/library/src/main/java/ru/yoomoney/sdk/kassa/payments/tokenize/TokenizeAnalytics.kt
+++ b/library/src/main/java/ru/yoomoney/sdk/kassa/payments/tokenize/TokenizeAnalytics.kt
@@ -21,37 +21,59 @@
package ru.yoomoney.sdk.kassa.payments.tokenize
-import ru.yoomoney.sdk.kassa.payments.metrics.AuthTokenType
+import ru.yoomoney.sdk.kassa.payments.checkoutParameters.PaymentParameters
+import ru.yoomoney.sdk.kassa.payments.checkoutParameters.UiParameters
import ru.yoomoney.sdk.kassa.payments.metrics.AuthType
+import ru.yoomoney.sdk.kassa.payments.metrics.ColorMetricsProvider
import ru.yoomoney.sdk.kassa.payments.metrics.ErrorScreenReporter
import ru.yoomoney.sdk.kassa.payments.metrics.Reporter
+import ru.yoomoney.sdk.kassa.payments.metrics.SavePaymentMethodProvider
import ru.yoomoney.sdk.kassa.payments.metrics.TokenizeScheme
+import ru.yoomoney.sdk.kassa.payments.metrics.UserAttiributionOnInitProvider
+import ru.yoomoney.sdk.kassa.payments.metrics.YooKassaIconProvider
import ru.yoomoney.sdk.kassa.payments.model.PaymentInstrumentBankCard
import ru.yoomoney.sdk.kassa.payments.model.PaymentOption
import ru.yoomoney.sdk.kassa.payments.payment.tokenize.TokenizeOutputModel
+import ru.yoomoney.sdk.kassa.payments.userAuth.UserAuthInfoRepository
import ru.yoomoney.sdk.march.Logic
import ru.yoomoney.sdk.march.Out
+private const val ACTION_TRY_TOKENIZE = "actionTryTokenize"
+private const val ACTION_TOKENIZE = "actionTokenize"
+
internal class TokenizeAnalytics(
private val reporter: Reporter,
private val errorScreenReporter: ErrorScreenReporter,
private val businessLogic: Logic,
private val getUserAuthType: () -> AuthType,
- private val getUserAuthTokenType: () -> AuthTokenType,
- private val getTokenizeScheme: (PaymentOption, PaymentInstrumentBankCard?) -> TokenizeScheme
+ private val userAuthInfoRepository: UserAuthInfoRepository,
+ private val getTokenizeScheme: () -> TokenizeScheme?,
+ private val paymentParameters: PaymentParameters,
+ private val uiParameters: UiParameters
) : Logic {
override fun invoke(state: Tokenize.State, action: Tokenize.Action): Out {
val nameArgsPairs = when (action) {
- is Tokenize.Action.TokenizeSuccess -> {
- if (action.content is TokenizeOutputModel) {
+ is Tokenize.Action.Tokenize -> {
+ getTokenizeScheme()?.let { tokenizeScheme ->
listOf(
- "actionTokenize" to listOf(
- getTokenizeScheme(action.content.option, action.content.instrumentBankCard),
+ ACTION_TRY_TOKENIZE to listOf(
getUserAuthType(),
- getUserAuthTokenType()
+ tokenizeScheme,
+ SavePaymentMethodProvider().invoke(paymentParameters),
+ YooKassaIconProvider().invoke(uiParameters),
+ ColorMetricsProvider().invoke(uiParameters),
+ UserAttiributionOnInitProvider(userAuthInfoRepository).invoke(paymentParameters)
)
)
+ } ?: listOf(null to null)
+ }
+ is Tokenize.Action.TokenizeSuccess -> {
+ val tokenizeScheme = getTokenizeScheme()
+ if (action.content is TokenizeOutputModel && tokenizeScheme != null) {
+ listOf(
+ ACTION_TOKENIZE to listOf(tokenizeScheme, getUserAuthType())
+ )
} else {
listOf(null to null)
}
diff --git a/library/src/main/java/ru/yoomoney/sdk/kassa/payments/tokenize/di/TokenizeModule.kt b/library/src/main/java/ru/yoomoney/sdk/kassa/payments/tokenize/di/TokenizeModule.kt
index 48c346b..f3962e6 100644
--- a/library/src/main/java/ru/yoomoney/sdk/kassa/payments/tokenize/di/TokenizeModule.kt
+++ b/library/src/main/java/ru/yoomoney/sdk/kassa/payments/tokenize/di/TokenizeModule.kt
@@ -21,28 +21,27 @@
package ru.yoomoney.sdk.kassa.payments.tokenize.di
-import android.content.Context
import androidx.lifecycle.ViewModel
import dagger.Module
import dagger.Provides
import dagger.multibindings.IntoMap
-import ru.yoomoney.sdk.kassa.payments.checkoutParameters.TestParameters
+import ru.yoomoney.sdk.kassa.payments.checkoutParameters.PaymentParameters
+import ru.yoomoney.sdk.kassa.payments.checkoutParameters.UiParameters
import ru.yoomoney.sdk.kassa.payments.di.ViewModelKey
-import ru.yoomoney.sdk.kassa.payments.extensions.toTokenizeScheme
import ru.yoomoney.sdk.kassa.payments.metrics.ErrorScreenReporter
import ru.yoomoney.sdk.kassa.payments.metrics.Reporter
-import ru.yoomoney.sdk.kassa.payments.metrics.UserAuthTokenTypeParamProvider
+import ru.yoomoney.sdk.kassa.payments.metrics.TokenizeSchemeParamProvider
import ru.yoomoney.sdk.kassa.payments.metrics.UserAuthTypeParamProvider
import ru.yoomoney.sdk.kassa.payments.payment.CheckPaymentAuthRequiredGateway
import ru.yoomoney.sdk.kassa.payments.payment.GetLoadedPaymentOptionListRepository
import ru.yoomoney.sdk.kassa.payments.payment.tokenize.TokenizeRepository
import ru.yoomoney.sdk.kassa.payments.paymentAuth.PaymentAuthTokenRepository
+import ru.yoomoney.sdk.kassa.payments.secure.TokensStorage
import ru.yoomoney.sdk.kassa.payments.tokenize.Tokenize
import ru.yoomoney.sdk.kassa.payments.tokenize.TokenizeAnalytics
import ru.yoomoney.sdk.kassa.payments.tokenize.TokenizeBusinessLogic
import ru.yoomoney.sdk.kassa.payments.tokenize.TokenizeUseCase
import ru.yoomoney.sdk.kassa.payments.tokenize.TokenizeUseCaseImpl
-import ru.yoomoney.sdk.kassa.payments.utils.getSberbankPackage
import ru.yoomoney.sdk.march.Out
import ru.yoomoney.sdk.march.RuntimeViewModel
import ru.yoomoney.sdk.march.input
@@ -67,15 +66,15 @@ internal class TokenizeModule {
@[Provides IntoMap ViewModelKey(TOKENIZE)]
fun viewModel(
- context: Context,
- testParameters: TestParameters,
tokenizeUseCase: TokenizeUseCase,
reporter: Reporter,
errorScreenReporter: ErrorScreenReporter,
- userAuthTokenTypeParamProvider: UserAuthTokenTypeParamProvider,
- userAuthTypeParamProvider: UserAuthTypeParamProvider
+ paymentParameters: PaymentParameters,
+ uiParameters: UiParameters,
+ tokensStorage: TokensStorage,
+ userAuthTypeParamProvider: UserAuthTypeParamProvider,
+ tokenizeSchemeParamProvider: TokenizeSchemeParamProvider
): ViewModel {
- val sberbankPackage = getSberbankPackage(testParameters.hostParameters.isDevHost)
return RuntimeViewModel(
featureName = "Tokenize",
initial = {
@@ -93,11 +92,11 @@ internal class TokenizeModule {
source = source,
tokenizeUseCase = tokenizeUseCase
),
- getUserAuthTokenType = userAuthTokenTypeParamProvider,
getUserAuthType = userAuthTypeParamProvider,
- getTokenizeScheme = { paymentOption, paymentInstrument ->
- paymentOption.toTokenizeScheme(context, sberbankPackage, paymentInstrument)
- }
+ userAuthInfoRepository = tokensStorage,
+ getTokenizeScheme = tokenizeSchemeParamProvider,
+ paymentParameters = paymentParameters,
+ uiParameters = uiParameters
)
}
)
diff --git a/library/src/main/java/ru/yoomoney/sdk/kassa/payments/ui/CheckoutActivity.kt b/library/src/main/java/ru/yoomoney/sdk/kassa/payments/ui/CheckoutActivity.kt
index 17af005..e893cdd 100644
--- a/library/src/main/java/ru/yoomoney/sdk/kassa/payments/ui/CheckoutActivity.kt
+++ b/library/src/main/java/ru/yoomoney/sdk/kassa/payments/ui/CheckoutActivity.kt
@@ -29,9 +29,17 @@ import ru.yoomoney.sdk.kassa.payments.BuildConfig
import ru.yoomoney.sdk.kassa.payments.checkoutParameters.SavedBankCardPaymentParameters
import ru.yoomoney.sdk.kassa.payments.checkoutParameters.PaymentMethodType
import ru.yoomoney.sdk.kassa.payments.checkoutParameters.PaymentParameters
+import ru.yoomoney.sdk.kassa.payments.checkoutParameters.UiParameters
import ru.yoomoney.sdk.kassa.payments.di.CheckoutInjector
import ru.yoomoney.sdk.kassa.payments.errorFormatter.ErrorFormatter
+import ru.yoomoney.sdk.kassa.payments.metrics.ColorMetricsProvider
+import ru.yoomoney.sdk.kassa.payments.metrics.Reporter
+import ru.yoomoney.sdk.kassa.payments.metrics.SavePaymentMethodProvider
+import ru.yoomoney.sdk.kassa.payments.metrics.UserAttiributionOnInitProvider
+import ru.yoomoney.sdk.kassa.payments.metrics.UserAuthTypeParamProvider
import ru.yoomoney.sdk.kassa.payments.metrics.YandexMetricaExceptionReporter
+import ru.yoomoney.sdk.kassa.payments.metrics.YooKassaIconProvider
+import ru.yoomoney.sdk.kassa.payments.secure.TokensStorage
import javax.inject.Inject
internal const val EXTRA_CREATED_WITH_CHECKOUT_METHOD = "ru.yoomoney.sdk.kassa.payments.extra.CREATED_WITH_CHECKOUT_METHOD"
@@ -44,16 +52,28 @@ internal const val EXTRA_PAYMENT_TOKEN = "ru.yoomoney.sdk.kassa.payments.extra.P
private val TAG_BOTTOM_SHEET = MainDialogFragment::class.java.name
+private const val ACTION_SDK_INITIALIZED = "actionSDKInitialised"
+
internal class CheckoutActivity : AppCompatActivity() {
@Inject
lateinit var errorFormatter: ErrorFormatter
+ @Inject
+ lateinit var reporter: Reporter
+
+ @Inject
+ lateinit var userAuthParamProvider: UserAuthTypeParamProvider
+
+ @Inject
+ lateinit var tokensStorage: TokensStorage
+
private val paymentParameters: PaymentParameters by lazy {
if (intent.hasExtra(EXTRA_PAYMENT_PARAMETERS)) {
requireNotNull(intent.getParcelableExtra(EXTRA_PAYMENT_PARAMETERS))
} else {
- val cscParameter = requireNotNull(intent.getParcelableExtra(EXTRA_CSC_PARAMETERS))
+ val cscParameter =
+ requireNotNull(intent.getParcelableExtra(EXTRA_CSC_PARAMETERS))
PaymentParameters(
amount = cscParameter.amount,
title = cscParameter.title,
@@ -75,15 +95,17 @@ internal class CheckoutActivity : AppCompatActivity() {
} else {
null
}
+ val uiParameters: UiParameters = requireNotNull(intent.getParcelableExtra(EXTRA_UI_PARAMETERS))
CheckoutInjector.setupComponent(
this,
paymentParameters,
requireNotNull(intent.getParcelableExtra(EXTRA_TEST_PARAMETERS)),
- requireNotNull(intent.getParcelableExtra(EXTRA_UI_PARAMETERS)),
+ uiParameters,
paymentMethodId,
YandexMetricaExceptionReporter(YandexMetrica.getReporter(applicationContext, BuildConfig.APP_METRICA_KEY))
)
CheckoutInjector.injectCheckoutActivity(this)
+ sendInitializeAction(paymentParameters, uiParameters)
super.onCreate(savedInstanceState)
showDialog(supportFragmentManager)
@@ -116,4 +138,17 @@ internal class CheckoutActivity : AppCompatActivity() {
)
}
}
-}
+
+ private fun sendInitializeAction(paymentParameters: PaymentParameters, uiParameters: UiParameters) {
+ reporter.report(
+ ACTION_SDK_INITIALIZED,
+ listOf(
+ userAuthParamProvider.invoke(),
+ SavePaymentMethodProvider().invoke(paymentParameters),
+ YooKassaIconProvider().invoke(uiParameters),
+ ColorMetricsProvider().invoke(uiParameters),
+ UserAttiributionOnInitProvider(tokensStorage).invoke(paymentParameters)
+ )
+ )
+ }
+}
\ No newline at end of file
diff --git a/library/src/main/java/ru/yoomoney/sdk/kassa/payments/ui/color/ColorScheme.kt b/library/src/main/java/ru/yoomoney/sdk/kassa/payments/ui/color/ColorScheme.kt
index 7b20b2f..5d3b6d7 100644
--- a/library/src/main/java/ru/yoomoney/sdk/kassa/payments/ui/color/ColorScheme.kt
+++ b/library/src/main/java/ru/yoomoney/sdk/kassa/payments/ui/color/ColorScheme.kt
@@ -36,25 +36,30 @@ import kotlinx.android.parcel.Parcelize
* Caution: using red color will clash with error color on edit texts.
*/
@[Parcelize Keep SuppressLint("ParcelCreator")]
-data class ColorScheme
+open class ColorScheme
@Keep constructor(
@[Keep ColorInt] val primaryColor: Int
) : Parcelable {
@Keep
companion object {
+
+ /**
+ * Current default color, used by mSDK
+ */
+ val defaultPrimaryColor = Color.rgb(0, 168, 132)
+
+ /**
+ * Legacy color, used by previous versions of mSDK
+ */
+ private val legacyPrimaryColor = Color.rgb(255, 219, 77)
+
/**
* Current default color scheme, used by mSDK
*/
@[JvmStatic Keep]
fun getDefaultScheme(): ColorScheme {
- return ColorScheme(
- primaryColor = Color.rgb(
- 0,
- 168,
- 132
- )
- )
+ return ColorScheme(primaryColor = defaultPrimaryColor)
}
/**
@@ -62,13 +67,7 @@ data class ColorScheme
*/
@[JvmStatic Keep]
fun getLegacyScheme(): ColorScheme {
- return ColorScheme(
- primaryColor = Color.rgb(
- 255,
- 219,
- 77
- )
- )
+ return ColorScheme(primaryColor = legacyPrimaryColor)
}
}
}
diff --git a/library/src/main/java/ru/yoomoney/sdk/kassa/payments/ui/view/BankCardView.kt b/library/src/main/java/ru/yoomoney/sdk/kassa/payments/ui/view/BankCardView.kt
index b870b25..de882ad 100644
--- a/library/src/main/java/ru/yoomoney/sdk/kassa/payments/ui/view/BankCardView.kt
+++ b/library/src/main/java/ru/yoomoney/sdk/kassa/payments/ui/view/BankCardView.kt
@@ -86,6 +86,8 @@ internal const val EXTRA_CARD_NUMBER = "cardNumber"
internal const val EXTRA_EXPIRY_MONTH = "expiryMonth"
internal const val EXTRA_EXPIRY_YEAR = "expiryYear"
+internal const val MIN_EXPIRY_DATE = "01/22"
+
internal class BankCardView
@JvmOverloads constructor(
context: Context,
@@ -511,7 +513,7 @@ internal class BankCardView
private fun isExpiryCorrect(): Boolean {
return expiryEditText.length() == MIN_LENGTH_EXPIRY && try {
- expiryFormat.parse(expiryEditText.text.toString()) > minExpiry.time
+ expiryFormat.parse(expiryEditText.text.toString()) >= expiryFormat.parse(MIN_EXPIRY_DATE)
} catch (e: ParseException) {
false
}
diff --git a/library/src/main/java/ru/yoomoney/sdk/kassa/payments/userAuth/MoneyAuthFragment.kt b/library/src/main/java/ru/yoomoney/sdk/kassa/payments/userAuth/MoneyAuthFragment.kt
index e3a2c41..908c1bc 100644
--- a/library/src/main/java/ru/yoomoney/sdk/kassa/payments/userAuth/MoneyAuthFragment.kt
+++ b/library/src/main/java/ru/yoomoney/sdk/kassa/payments/userAuth/MoneyAuthFragment.kt
@@ -182,10 +182,7 @@ internal class MoneyAuthFragment : Fragment() {
supportEmail = getString(R.string.ym_support_email),
supportHelpUrl = getString(R.string.ym_support_help_url),
supportPhone = getString(R.string.ym_support_phone),
- migrationBannerVisible = true,
- migrationBannerText = getString(R.string.ym_migration_banner_text),
- migrationBannerButtonText = getString(R.string.ym_migration_banner_button_text),
- migrationBannerImageUrl = "https://static.yoomoney.ru/files-front/mobile/img/android_migration_banner_logo.png",
+ migrationBannerVisible = false,
applicationUserAgent = UserAgent.getUserAgent(requireContext()),
remoteConfig = RemoteConfig(
restorePasswordEnabled = false,
diff --git a/library/src/main/java/ru/yoomoney/sdk/kassa/payments/userAuth/di/UserAuthModule.kt b/library/src/main/java/ru/yoomoney/sdk/kassa/payments/userAuth/di/UserAuthModule.kt
index 50d7136..39d3e1d 100644
--- a/library/src/main/java/ru/yoomoney/sdk/kassa/payments/userAuth/di/UserAuthModule.kt
+++ b/library/src/main/java/ru/yoomoney/sdk/kassa/payments/userAuth/di/UserAuthModule.kt
@@ -36,14 +36,12 @@ import ru.yoomoney.sdk.kassa.payments.di.ViewModelKey
import ru.yoomoney.sdk.kassa.payments.http.HostProvider
import ru.yoomoney.sdk.kassa.payments.metrics.Reporter
import ru.yoomoney.sdk.kassa.payments.metrics.TokenizeSchemeParamProvider
-import ru.yoomoney.sdk.kassa.payments.metrics.UserAuthTokenTypeParamProvider
import ru.yoomoney.sdk.kassa.payments.metrics.UserAuthTypeParamProvider
import ru.yoomoney.sdk.kassa.payments.model.Executor
import ru.yoomoney.sdk.kassa.payments.model.Result
import ru.yoomoney.sdk.kassa.payments.payment.CheckPaymentAuthRequiredGateway
import ru.yoomoney.sdk.kassa.payments.payment.CurrentUserRepository
import ru.yoomoney.sdk.kassa.payments.payment.GetLoadedPaymentOptionListRepository
-import ru.yoomoney.sdk.kassa.payments.paymentAuth.PaymentAuthTokenRepository
import ru.yoomoney.sdk.kassa.payments.paymentOptionList.PaymentOptionsListUseCase
import ru.yoomoney.sdk.kassa.payments.secure.TokensStorage
import ru.yoomoney.sdk.kassa.payments.tmx.TmxSessionIdStorage
@@ -121,14 +119,6 @@ internal class UserAuthModule {
)
}
- @Provides
- @Singleton
- fun userAuthTokenTypeParamProvider(
- paymentAuthTokenRepository: PaymentAuthTokenRepository
- ): UserAuthTokenTypeParamProvider {
- return UserAuthTokenTypeParamProvider(paymentAuthTokenRepository)
- }
-
@Provides
@Singleton
fun transferDataRepository(
diff --git a/library/src/main/java/ru/yoomoney/sdk/kassa/payments/utils/WebViewActivity.kt b/library/src/main/java/ru/yoomoney/sdk/kassa/payments/utils/WebViewActivity.kt
index 1788e2f..9ee31fc 100644
--- a/library/src/main/java/ru/yoomoney/sdk/kassa/payments/utils/WebViewActivity.kt
+++ b/library/src/main/java/ru/yoomoney/sdk/kassa/payments/utils/WebViewActivity.kt
@@ -44,6 +44,8 @@ import ru.yoomoney.sdk.kassa.payments.extensions.visible
import ru.yoomoney.sdk.kassa.payments.logging.ReporterLogger
import ru.yoomoney.sdk.kassa.payments.metrics.YandexMetricaReporter
+private const val ACTION_CLOSE_3DS_SCREEN = "close3dsScreen"
+
const val EXTRA_URL = "ru.yoomoney.sdk.kassa.payments.extra.URL"
const val EXTRA_LOG_PARAM = "ru.yoomoney.sdk.kassa.payments.extra.LOG_PARAM"
@@ -51,6 +53,7 @@ class WebViewActivity : AppCompatActivity(),
WebViewFragment.Listener {
private lateinit var webViewFragment: WebViewFragment
+ private lateinit var reporterLogger: ReporterLogger
private var progress: ContentLoadingProgressBar? = null
private var showProgress: Boolean = false
@@ -58,15 +61,16 @@ class WebViewActivity : AppCompatActivity(),
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
+ reporterLogger = ReporterLogger(YandexMetricaReporter(
+ YandexMetrica.getReporter(applicationContext, BuildConfig.APP_METRICA_KEY)
+ ))
val url = requireNotNull(intent.getStringExtra(EXTRA_URL))
val logParam = intent.getStringExtra(EXTRA_LOG_PARAM)
if (checkUrl(url)) {
if (savedInstanceState == null && logParam != null) {
- ReporterLogger(YandexMetricaReporter(
- YandexMetrica.getReporter(applicationContext, BuildConfig.APP_METRICA_KEY)
- )).report(logParam)
+ reporterLogger.report(logParam)
}
setContentView(R.layout.ym_activity_web_view)
@@ -77,7 +81,7 @@ class WebViewActivity : AppCompatActivity(),
load(url, DEFAULT_REDIRECT_URL)
}
} else {
- onError(Checkout.ERROR_NOT_HTTPS_URL, "Not https:// url", url.toString())
+ onError(Checkout.ERROR_NOT_HTTPS_URL, "Not https:// url", url)
}
}
@@ -95,6 +99,7 @@ class WebViewActivity : AppCompatActivity(),
override fun onContentChanged() {
toolbar = findViewById(R.id.toolbar)?.also { toolbar ->
toolbar.setNavigationOnClickListener {
+ reporterLogger.report(ACTION_CLOSE_3DS_SCREEN, false)
setResult(Activity.RESULT_CANCELED)
finish()
}
@@ -135,6 +140,7 @@ class WebViewActivity : AppCompatActivity(),
override fun onBackPressed() {
if (!(this::webViewFragment.isInitialized && webViewFragment.onBackPressed())) {
+ reporterLogger.report(ACTION_CLOSE_3DS_SCREEN, false)
super.onBackPressed()
}
}
@@ -156,6 +162,7 @@ class WebViewActivity : AppCompatActivity(),
}
override fun onError(errorCode: Int, description: String?, failingUrl: String?) {
+ reporterLogger.report(ACTION_CLOSE_3DS_SCREEN, false)
setResult(
RESULT_ERROR,
Intent()
@@ -168,6 +175,7 @@ class WebViewActivity : AppCompatActivity(),
}
override fun onSuccess() {
+ reporterLogger.report(ACTION_CLOSE_3DS_SCREEN, true)
setResult(RESULT_OK, Intent().putExtras(intent))
finish()
}
diff --git a/library/src/test/java/ru/yoomoney/sdk/kassa/payments/contract/ContractAnalyticsTest.kt b/library/src/test/java/ru/yoomoney/sdk/kassa/payments/contract/ContractAnalyticsTest.kt
index 7c36cd1..405d08d 100644
--- a/library/src/test/java/ru/yoomoney/sdk/kassa/payments/contract/ContractAnalyticsTest.kt
+++ b/library/src/test/java/ru/yoomoney/sdk/kassa/payments/contract/ContractAnalyticsTest.kt
@@ -21,25 +21,24 @@
package ru.yoomoney.sdk.kassa.payments.contract
-import com.nhaarman.mockitokotlin2.any
import com.nhaarman.mockitokotlin2.mock
import com.nhaarman.mockitokotlin2.verify
import com.nhaarman.mockitokotlin2.whenever
-import okio.ByteString.Companion.decodeHex
import org.junit.Test
import ru.yoomoney.sdk.kassa.payments.checkoutParameters.Amount
+import ru.yoomoney.sdk.kassa.payments.checkoutParameters.PaymentParameters
+import ru.yoomoney.sdk.kassa.payments.checkoutParameters.SavePaymentMethod
import ru.yoomoney.sdk.kassa.payments.extensions.RUB
import ru.yoomoney.sdk.kassa.payments.metrics.AuthTypeYooMoneyLogin
-import ru.yoomoney.sdk.kassa.payments.metrics.ErrorScreenReporterImpl
import ru.yoomoney.sdk.kassa.payments.metrics.Reporter
+import ru.yoomoney.sdk.kassa.payments.metrics.SavePaymentMethodOn
import ru.yoomoney.sdk.kassa.payments.metrics.TokenizeScheme
import ru.yoomoney.sdk.kassa.payments.metrics.TokenizeSchemeLinkedCard
+import ru.yoomoney.sdk.kassa.payments.metrics.TokenizeSchemeParamProvider
import ru.yoomoney.sdk.kassa.payments.model.CardBrand
import ru.yoomoney.sdk.kassa.payments.model.ConfirmationType
import ru.yoomoney.sdk.kassa.payments.model.Fee
import ru.yoomoney.sdk.kassa.payments.model.LinkedCard
-import ru.yoomoney.sdk.kassa.payments.model.BankCardPaymentOption
-import ru.yoomoney.sdk.kassa.payments.model.PaymentIdCscConfirmation
import ru.yoomoney.sdk.kassa.payments.model.PaymentInstrumentBankCard
import ru.yoomoney.sdk.kassa.payments.model.PaymentOption
import ru.yoomoney.sdk.kassa.payments.model.SdkException
@@ -49,20 +48,27 @@ import java.math.BigDecimal
class ContractAnalyticsTest {
private val reporter: Reporter = mock()
- private val userAuthType = AuthTypeYooMoneyLogin()
- private val errorScreenReporter = ErrorScreenReporterImpl(
- reporter = reporter,
- getAuthType = { userAuthType },
- getTokenizeScheme = { null }
+ private val paymentParameters = PaymentParameters(
+ amount = Amount(BigDecimal.TEN, RUB),
+ title = "shopTitle",
+ subtitle = "shopSubtitle",
+ clientApplicationKey = "clientApplicationKey",
+ shopId = "shopId",
+ savePaymentMethod = SavePaymentMethod.ON,
+ authCenterClientId = "authCenterClientId"
)
+
+ private val userAuthType = AuthTypeYooMoneyLogin()
+ private val tokenizeSchemeParamProvider: TokenizeSchemeParamProvider = mock()
private val getTokenizeScheme: (PaymentOption, PaymentInstrumentBankCard?) -> TokenizeScheme = mock()
private val contractAnalytics = ContractAnalytics(
reporter = reporter,
- errorScreenReporter = errorScreenReporter,
businessLogic = mock(),
getUserAuthType = { userAuthType },
- getTokenizeScheme = getTokenizeScheme
+ getTokenizeScheme = getTokenizeScheme,
+ paymentParameters = paymentParameters,
+ tokenizeSchemeParamProvider = tokenizeSchemeParamProvider
)
@Test
@@ -79,100 +85,10 @@ class ContractAnalyticsTest {
verify(reporter).report("actionLogout")
}
- @Test
- fun `verify screenBankCardForm analytics sends`() {
- // given
- val newCard = BankCardPaymentOption(
- id = 0,
- charge = Amount(BigDecimal("2.00"), RUB),
- fee = null,
- savePaymentMethodAllowed = true,
- confirmationTypes = listOf(ConfirmationType.REDIRECT),
- savePaymentInstrument = false,
- paymentInstruments = emptyList(),
- title = null,
- icon = null
- )
-
- // when
- contractAnalytics(
- Contract.State.Loading,
- Contract.Action.LoadContractSuccess(
- SelectedPaymentMethodOutputModel(newCard, instrument = null, walletLinkingPossible = false)
- )
- )
-
- // then
- verify(reporter).report("screenBankCardForm", listOf(userAuthType))
- }
-
- @Test
- fun `verify screenLinkedCardForm analytics sends`() {
- // given
- val linkedCard = LinkedCard(
- id = 1,
- charge = Amount(BigDecimal.TEN, RUB),
- fee = Fee(
- Amount(BigDecimal.ONE, RUB),
- Amount(BigDecimal("0.5"), RUB)
- ),
- title = null,
- icon = null,
- cardId = "12345654321",
- brand = CardBrand.MASTER_CARD,
- pan = "1234567887654321",
- savePaymentMethodAllowed = true,
- confirmationTypes = listOf(ConfirmationType.REDIRECT),
- savePaymentInstrument = false
- )
-
- // when
- contractAnalytics(
- Contract.State.Loading,
- Contract.Action.LoadContractSuccess(
- SelectedPaymentMethodOutputModel(linkedCard, null, false)
- )
- )
-
- // then
- verify(reporter).report("screenLinkedCardForm")
- }
-
- @Test
- fun `verify screenRecurringCardForm analytics sends`() {
- // given
- val cscConfirmation = PaymentIdCscConfirmation(
- id = 0,
- charge = Amount(BigDecimal.TEN, RUB),
- paymentMethodId = "123",
- fee = null,
- first = "123456",
- last = "7890",
- expiryYear = "2020",
- expiryMonth = "12",
- title = null,
- icon = null,
- savePaymentMethodAllowed = true,
- confirmationTypes = emptyList(),
- brand = CardBrand.MASTER_CARD,
- savePaymentInstrument = false
- )
-
- // when
- contractAnalytics(
- Contract.State.Loading,
- Contract.Action.LoadContractSuccess(
- SelectedPaymentMethodOutputModel(cscConfirmation, null, false)
- )
- )
-
- // then
- verify(reporter).report("screenRecurringCardForm")
- }
-
@Test
fun `verify error screen analytics sends`() {
// given
+ whenever(tokenizeSchemeParamProvider.invoke()).thenReturn(TokenizeSchemeLinkedCard())
// when
contractAnalytics(
@@ -181,7 +97,10 @@ class ContractAnalyticsTest {
)
// then
- verify(reporter).report("screenError", listOf(userAuthType))
+ verify(reporter).report(
+ "screenErrorContract",
+ listOf(userAuthType, TokenizeSchemeLinkedCard(), SavePaymentMethodOn())
+ )
}
@Test
diff --git a/library/src/test/java/ru/yoomoney/sdk/kassa/payments/impl/metrics/UserAuthTokenTypeParamProviderTest.kt b/library/src/test/java/ru/yoomoney/sdk/kassa/payments/impl/metrics/UserAuthTokenTypeParamProviderTest.kt
deleted file mode 100644
index d23d5bf..0000000
--- a/library/src/test/java/ru/yoomoney/sdk/kassa/payments/impl/metrics/UserAuthTokenTypeParamProviderTest.kt
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * The MIT License (MIT)
- * Copyright © 2020 NBCO YooMoney LLC
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
- * associated documentation files (the “Software”), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
- * following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all copies or substantial
- * portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
- * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
- * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
- * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-package ru.yoomoney.sdk.kassa.payments.impl.metrics
-
-import org.hamcrest.MatcherAssert.assertThat
-import org.hamcrest.core.IsEqual.equalTo
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.Mock
-import org.mockito.junit.MockitoJUnitRunner
-import ru.yoomoney.sdk.kassa.payments.metrics.AuthTokenType
-import ru.yoomoney.sdk.kassa.payments.metrics.AuthTokenTypeMultiple
-import ru.yoomoney.sdk.kassa.payments.metrics.AuthTokenTypeSingle
-import ru.yoomoney.sdk.kassa.payments.metrics.UserAuthTokenTypeParamProvider
-import ru.yoomoney.sdk.kassa.payments.on
-import ru.yoomoney.sdk.kassa.payments.paymentAuth.PaymentAuthTokenRepository
-
-@RunWith(MockitoJUnitRunner.StrictStubs::class)
-class UserAuthTokenTypeParamProviderTest {
-
- @Mock
- private lateinit var paymentAuthTokenRepository: PaymentAuthTokenRepository
- private lateinit var userAuthTokenTypeParamProvider: UserAuthTokenTypeParamProvider
-
- @Before
- fun setUp() {
- userAuthTokenTypeParamProvider =
- UserAuthTokenTypeParamProvider(
- paymentAuthTokenRepository
- )
- }
-
- @Test
- fun `should return AuthTokenTypeSingle if paymentAuthToken not persisted`() {
- // prepare
- on(paymentAuthTokenRepository.isPaymentAuthPersisted).thenReturn(false)
-
- // invoke
- val tokenTypeParam = userAuthTokenTypeParamProvider()
-
- // assert
- assertThat(tokenTypeParam, equalTo(AuthTokenTypeSingle() as AuthTokenType))
- }
-
- @Test
- fun `should return AuthTokenTypeMultiple if paymentAuthToken persisted`() {
- // prepare
- on(paymentAuthTokenRepository.isPaymentAuthPersisted).thenReturn(true)
-
- // invoke
- val tokenTypeParam = userAuthTokenTypeParamProvider()
-
- // assert
- assertThat(tokenTypeParam, equalTo(AuthTokenTypeMultiple() as AuthTokenType))
- }
-}
\ No newline at end of file
diff --git a/library/src/test/java/ru/yoomoney/sdk/kassa/payments/paymentOptionList/PaymentOptionsListBusinessLogicEffectTest.kt b/library/src/test/java/ru/yoomoney/sdk/kassa/payments/paymentOptionList/PaymentOptionsListBusinessLogicEffectTest.kt
index 1033fbd..928cc28 100644
--- a/library/src/test/java/ru/yoomoney/sdk/kassa/payments/paymentOptionList/PaymentOptionsListBusinessLogicEffectTest.kt
+++ b/library/src/test/java/ru/yoomoney/sdk/kassa/payments/paymentOptionList/PaymentOptionsListBusinessLogicEffectTest.kt
@@ -32,12 +32,14 @@ import ru.yoomoney.sdk.kassa.payments.checkoutParameters.PaymentParameters
import ru.yoomoney.sdk.kassa.payments.checkoutParameters.SavePaymentMethod
import ru.yoomoney.sdk.kassa.payments.extensions.RUB
import ru.yoomoney.sdk.kassa.payments.logoUrl
+import ru.yoomoney.sdk.kassa.payments.metrics.TokenizeScheme
import ru.yoomoney.sdk.kassa.payments.model.BankCardPaymentOption
import ru.yoomoney.sdk.kassa.payments.model.CardBrand
import ru.yoomoney.sdk.kassa.payments.model.Fee
import ru.yoomoney.sdk.kassa.payments.model.GetConfirmation
import ru.yoomoney.sdk.kassa.payments.model.NoConfirmation
import ru.yoomoney.sdk.kassa.payments.model.PaymentInstrumentBankCard
+import ru.yoomoney.sdk.kassa.payments.model.PaymentOption
import ru.yoomoney.sdk.kassa.payments.model.ShopProperties
import ru.yoomoney.sdk.kassa.payments.payment.tokenize.TokenizeInstrumentInputModel
import ru.yoomoney.sdk.march.Effect
@@ -51,6 +53,7 @@ internal class PaymentOptionsListBusinessLogicEffectTest {
private val useCase: PaymentOptionsListUseCase = mock()
private val shopPropertiesRepository: ShopPropertiesRepository = mock()
private val contentState = PaymentOptionList.State.Content(logoUrl, PaymentOptionListSuccessOutputModel(listOf()))
+ private val getTokenizeScheme: (PaymentOption, PaymentInstrumentBankCard?) -> TokenizeScheme = mock()
private val logic =
PaymentOptionsListBusinessLogic(
@@ -72,7 +75,9 @@ internal class PaymentOptionsListBusinessLogicEffectTest {
unbindCardUseCase = mock(),
paymentMethodId = null,
configRepository = mock(),
- shopPropertiesRepository = mock()
+ shopPropertiesRepository = mock(),
+ tokenizeSchemeProvider = mock(),
+ getTokenizeScheme = getTokenizeScheme
)
@Test
@@ -301,7 +306,9 @@ internal class PaymentOptionsListBusinessLogicEffectTest {
unbindCardUseCase = mock(),
shopPropertiesRepository = shopPropertiesRepository,
configRepository = mock(),
- paymentMethodId = "paymentMethodId"
+ paymentMethodId = "paymentMethodId",
+ tokenizeSchemeProvider = mock(),
+ getTokenizeScheme = getTokenizeScheme
)
private fun cratePaymentParameters(
diff --git a/library/src/test/java/ru/yoomoney/sdk/kassa/payments/paymentOptionList/PaymentOptionsListBusinessLogicTest.kt b/library/src/test/java/ru/yoomoney/sdk/kassa/payments/paymentOptionList/PaymentOptionsListBusinessLogicTest.kt
index 68307dc..64a6f10 100644
--- a/library/src/test/java/ru/yoomoney/sdk/kassa/payments/paymentOptionList/PaymentOptionsListBusinessLogicTest.kt
+++ b/library/src/test/java/ru/yoomoney/sdk/kassa/payments/paymentOptionList/PaymentOptionsListBusinessLogicTest.kt
@@ -22,11 +22,9 @@
package ru.yoomoney.sdk.kassa.payments.paymentOptionList
import com.google.gson.Gson
-import com.google.gson.JsonObject
import com.nhaarman.mockitokotlin2.mock
import com.nhaarman.mockitokotlin2.whenever
import org.hamcrest.CoreMatchers.equalTo
-import org.json.JSONObject
import org.junit.Assert.assertThat
import org.junit.Test
import org.junit.runner.RunWith
@@ -37,11 +35,12 @@ import ru.yoomoney.sdk.kassa.payments.checkoutParameters.SavePaymentMethod
import ru.yoomoney.sdk.kassa.payments.config.ConfigRepository
import ru.yoomoney.sdk.kassa.payments.extensions.RUB
import ru.yoomoney.sdk.kassa.payments.logoUrl
+import ru.yoomoney.sdk.kassa.payments.metrics.TokenizeScheme
import ru.yoomoney.sdk.kassa.payments.model.CardBrand
import ru.yoomoney.sdk.kassa.payments.model.Config
import ru.yoomoney.sdk.kassa.payments.model.PaymentInstrumentBankCard
+import ru.yoomoney.sdk.kassa.payments.model.PaymentOption
import ru.yoomoney.sdk.kassa.payments.model.SdkException
-import ru.yoomoney.sdk.kassa.payments.model.toConfig
import ru.yoomoney.sdk.kassa.payments.paymentOptionList.PaymentOptionList.Action
import ru.yoomoney.sdk.kassa.payments.paymentOptionList.PaymentOptionList.State
import ru.yoomoney.sdk.kassa.payments.utils.readTextFromResources
@@ -57,6 +56,7 @@ internal class PaymentOptionsListBusinessLogicTest(
) {
private val configRepository: ConfigRepository = mock()
+ private val getTokenizeScheme: (PaymentOption, PaymentInstrumentBankCard?) -> TokenizeScheme = mock()
companion object {
@[Parameterized.Parameters(name = "{0}") JvmStatic]
@@ -182,13 +182,15 @@ internal class PaymentOptionsListBusinessLogicTest(
unbindCardUseCase = mock(),
getConfirmation = mock(),
shopPropertiesRepository = mock(),
- configRepository = configRepository
+ configRepository = configRepository,
+ getTokenizeScheme = getTokenizeScheme,
+ tokenizeSchemeProvider = mock()
)
@Test
fun test() {
whenever(configRepository.getConfig()).thenReturn(
- Gson().fromJson(readTextFromResources("ym_default_config.json"), Config::class.java)
+ Gson().fromJson(readTextFromResources("ym_default_config.json"), Config::class.java)
)
// when
diff --git a/library/src/test/java/ru/yoomoney/sdk/kassa/payments/tokenize/TokenizeAnalyticsTest.kt b/library/src/test/java/ru/yoomoney/sdk/kassa/payments/tokenize/TokenizeAnalyticsTest.kt
deleted file mode 100644
index be08a36..0000000
--- a/library/src/test/java/ru/yoomoney/sdk/kassa/payments/tokenize/TokenizeAnalyticsTest.kt
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * The MIT License (MIT)
- * Copyright © 2021 NBCO YooMoney LLC
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
- * associated documentation files (the “Software”), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
- * following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all copies or substantial
- * portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
- * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
- * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
- * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-package ru.yoomoney.sdk.kassa.payments.tokenize
-
-import com.nhaarman.mockitokotlin2.mock
-import com.nhaarman.mockitokotlin2.verify
-import com.nhaarman.mockitokotlin2.whenever
-import org.junit.Test
-import ru.yoomoney.sdk.kassa.payments.checkoutParameters.Amount
-import ru.yoomoney.sdk.kassa.payments.extensions.RUB
-import ru.yoomoney.sdk.kassa.payments.metrics.AuthTokenTypeSingle
-import ru.yoomoney.sdk.kassa.payments.metrics.AuthTypeYooMoneyLogin
-import ru.yoomoney.sdk.kassa.payments.metrics.ErrorScreenReporterImpl
-import ru.yoomoney.sdk.kassa.payments.metrics.Reporter
-import ru.yoomoney.sdk.kassa.payments.metrics.TokenizeScheme
-import ru.yoomoney.sdk.kassa.payments.metrics.TokenizeSchemeSberPay
-import ru.yoomoney.sdk.kassa.payments.model.ConfirmationType
-import ru.yoomoney.sdk.kassa.payments.model.PaymentInstrumentBankCard
-import ru.yoomoney.sdk.kassa.payments.model.PaymentOption
-import ru.yoomoney.sdk.kassa.payments.model.Wallet
-import ru.yoomoney.sdk.kassa.payments.payment.tokenize.TokenizeOutputModel
-import java.math.BigDecimal
-
-class TokenizeAnalyticsTest {
- private val reporter: Reporter = mock()
-
- private val userAuthType = AuthTypeYooMoneyLogin()
- private val userAuthTokenType = AuthTokenTypeSingle()
- private val errorScreenReporter = ErrorScreenReporterImpl(
- reporter = reporter,
- getAuthType = { userAuthType },
- getTokenizeScheme = { null }
- )
- private val getTokenizeScheme: (PaymentOption, PaymentInstrumentBankCard?) -> TokenizeScheme = mock()
-
- private val tokenizeAnalytics = TokenizeAnalytics(
- reporter = reporter,
- errorScreenReporter = errorScreenReporter,
- businessLogic = mock(),
- getUserAuthType = { userAuthType },
- getTokenizeScheme = getTokenizeScheme,
- getUserAuthTokenType = { userAuthTokenType }
- )
-
- @Test
- fun `verify actionTokenize analytics sends`() {
- // given
- val wallet = Wallet(
- id = 1,
- charge = Amount(BigDecimal("3.00"), RUB),
- fee = null,
- icon = null,
- title = null,
- walletId = "123456789",
- balance = Amount(BigDecimal("5.00"), RUB),
- savePaymentMethodAllowed = true,
- confirmationTypes = listOf(ConfirmationType.REDIRECT),
- savePaymentInstrument = false
- )
-
- whenever(getTokenizeScheme(wallet, null)).thenReturn(TokenizeSchemeSberPay())
-
- // when
- tokenizeAnalytics(
- Tokenize.State.Start,
- Tokenize.Action.TokenizeSuccess(
- TokenizeOutputModel(
- "token",
- wallet,
- null
- )
- )
- )
-
- // then
- verify(reporter).report(
- "actionTokenize", listOf(
- TokenizeSchemeSberPay(),
- userAuthType,
- userAuthTokenType
- )
- )
- }
-}
\ No newline at end of file
diff --git a/library/src/test/resources/robolectric.properties b/library/src/test/resources/robolectric.properties
index 9b5b9c4..242dd87 100644
--- a/library/src/test/resources/robolectric.properties
+++ b/library/src/test/resources/robolectric.properties
@@ -19,4 +19,4 @@
# OTHER DEALINGS IN THE SOFTWARE.
#
-sdk=28
\ No newline at end of file
+sdk=29
\ No newline at end of file
diff --git a/librarytests/.gitignore b/librarytests/.gitignore
new file mode 100644
index 0000000..42afabf
--- /dev/null
+++ b/librarytests/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/librarytests/build.gradle b/librarytests/build.gradle
new file mode 100644
index 0000000..cc26b18
--- /dev/null
+++ b/librarytests/build.gradle
@@ -0,0 +1,128 @@
+/*
+ * The MIT License (MIT)
+ * Copyright © 2022 NBCO YooMoney LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+ * associated documentation files (the “Software”), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
+ * following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
+ * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+plugins {
+ id 'com.android.library'
+ id 'kotlin-android-extensions'
+ id 'kotlin-android'
+ id 'kotlin-kapt'
+}
+
+apply from: file('espresso.gradle.kts')
+
+android {
+ compileSdkVersion target_sdk_version
+ buildToolsVersion "31.0.0"
+
+ resourcePrefix 'ym_'
+
+ defaultConfig {
+ minSdkVersion 21
+ versionCode project.ext.versionCode
+ versionName project.ext.versionName
+
+ multiDexEnabled true
+ targetSdkVersion rootProject.ext.target_sdk_version
+
+ missingDimensionStrategy 'metrica', 'metricaTest'
+
+ testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
+
+ buildConfigField "String", "THREAT_METRIX_ORIG_ID", "${optionalProperty('threatMetrixOrigId')}"
+ buildConfigField "String", "THREAT_METRIX_FP_SERVER", "${optionalProperty('threatMetrixFPServer')}"
+ buildConfigField "String", "THREAT_METRIX_CERTIFICATE_HASHES", "${optionalProperty('threatMetrixCertificateHashes')}"
+ buildConfigField "String", "APP_METRICA_KEY", "${optionalProperty('metricaKey')}"
+
+ buildConfigField "Integer", "VERSION_CODE", "${project.ext.versionCode}"
+ buildConfigField "String", "VERSION_NAME", "\"${project.ext.versionName}\""
+
+ vectorDrawables.useSupportLibrary = true
+
+ resValue "string", "ym_app_scheme", ""
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+
+ testOptions {
+ unitTests {
+ includeAndroidResources = true
+ }
+ }
+
+ useLibrary 'org.apache.http.legacy'
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+ kotlinOptions {
+ jvmTarget = '1.8'
+ }
+
+ sourceSets {
+ main {
+ setRoot '../library/src'
+ java.srcDirs = ['../library/src/main/java']
+ manifest.srcFile '../library/src/main/AndroidManifest.xml'
+ resources.srcDirs = ['../library/src/main/resources']
+ res.srcDirs = ['../library/src/main/res', '../library/src/main/generated/res']
+ assets.srcDirs = ['../library/src/main/assets']
+ }
+ androidTest {
+ setRoot '../library/src'
+ java.srcDirs = ['../library/src/androidTest/java']
+ manifest.srcFile '../library/src/androidTest/AndroidManifest.xml'
+ resources.srcDirs = ['../library/src/androidTest/resources']
+ res.srcDirs = ['../library/src/androidTest/res']
+ assets.srcDirs = ['../library/src/androidTest/assets']
+ }
+ test {
+ setRoot '../library/src'
+ java.srcDirs = ['../library/src/test/java']
+ manifest.srcFile '../library/src/test/AndroidManifest.xml'
+ resources.srcDirs = ['../library/src/test/resources']
+ res.srcDirs = ['../library/src/test/res', '../library/src/test/res/xml']
+ assets.srcDirs = ['../library/src/test/assets']
+ }
+ }
+}
+
+repositories {
+ maven {
+ url 'https://nexus.yamoney.ru/repository/mobile-releases/'
+ content {
+ includeGroup "ru.yoomoney.sdk.tmx"
+ }
+ }
+}
+
+apply from: '../library/buildDependencies.gradle'
+apply from: '../library/buildTestDependencies.gradle'
+apply from: '../library/buildAndroidTestDependencies.gradle'
+
+dependencies {
+ implementation "ru.yoomoney.sdk.tmx:tmx-profiling:6.2.97"
+}
\ No newline at end of file
diff --git a/librarytests/espresso.gradle.kts b/librarytests/espresso.gradle.kts
new file mode 100644
index 0000000..5f1a476
--- /dev/null
+++ b/librarytests/espresso.gradle.kts
@@ -0,0 +1,263 @@
+/*
+ * The MIT License (MIT)
+ * Copyright © 2021 NBCO YooMoney LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+ * associated documentation files (the “Software”), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
+ * following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
+ * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+import org.gradle.kotlin.dsl.support.unzipTo
+import java.io.ByteArrayOutputStream
+import java.io.FileOutputStream
+import java.lang.Thread.sleep
+import java.net.URL
+import java.nio.channels.Channels
+import kotlin.properties.Delegates
+
+
+val APK_TEST_FOLDER_PATH = "${projectDir.absolutePath}/build/outputs/apk/androidTest/debug"
+
+
+tasks.register("spoonDebugAndroidTest") {
+ group = "ci"
+ val apkTestFolder = File(APK_TEST_FOLDER_PATH)
+ if (!apkTestFolder.exists()) {
+ println("APK_TEST_FOLDER $apkTestFolder is !exists")
+ dependsOn("assembleDebugAndroidTest")
+ }
+
+
+ doLast() {
+ val PROJECT_NAME = "money-payments-sdk-android"
+
+ mkdir("${rootDir.absolutePath}/espresso")
+ var apkPath = getApkDebugName()
+ var apkTestPath = getApkTestDebugName()
+
+ }
+}
+
+
+class Device() {
+ lateinit var id: String
+ var nubmer by Delegates.notNull()
+ private var runParam = mutableListOf()
+
+ constructor(
+ idDevices: String,
+ numberDevice: Int
+ ) : this() {
+ this.id = idDevices
+ this.nubmer = numberDevice
+ }
+
+ fun addParam(param: String) {
+ runParam.add(param)
+ }
+
+ fun getParamToString(): MutableList {
+ return runParam
+ }
+
+ fun clearParam() {
+ runParam.clear()
+ }
+
+ override fun toString(): String {
+ return "Devices(id='$id', nubmer='$nubmer')"
+ }
+
+ fun killEmu() {
+ execCmd("emu kill")
+ }
+
+ fun execCmd(command: String = "shell ls -s") {
+ var thread = ThreadShellInput("adb -s ${this.id} $command")
+ thread.start()
+ thread.join()
+ }
+}
+
+
+class TinyHelper(project: String) {
+
+ private val projectName = project
+
+ fun getListFullNameBlockedTests(): List {
+ var ansCurl = curlReq(listOf("curl", "https://tiny.yooteam.ru/api/test/blockedTests?project=$projectName"))
+ var json = groovy.json.JsonSlurper().parseText(ansCurl) as List
\ No newline at end of file
diff --git a/settings.gradle b/settings.gradle
index 8d74873..1e4e184 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -20,3 +20,4 @@
*/
include ':demo', ':library', 'sample'
+include ':librarytests'