Инструменты страницы
Mobile SDK Core
Введение
Mobile SDK Core - это скорее библиотека, чем SDK. Она используется для шифрования данных карты в seToken, который можно безопасно передать и сохранить в любой системе (например, на сервере продавца). Это хорошее решение для продавцов, которые хотят максимальной гибкости или не хотят иметь дело с данными карты на своих серверах.
Обратите внимание, что для использования этой библиотеки может потребоваться соответствие стандарту PCI DSS.
Способы оплаты, поддерживаемые этим SDK:
Способ оплаты | |
---|---|
Apple Pay | Не требуется |
Google Pay | Не требуется |
Банковская карта | Да |
Сохраненные учетные данные/карта | Да |
Если seToken содержит шифрованные данные о связке (bindingId
), вместо запроса paymentorder.do
для оплаты следует использовать запрос paymentOrderBinding.do.
Процесс оплаты SDK Core
Web View для 3DS
На приведенной ниже диаграмме показан процесс оплаты SDK Core с перенаправлением 3DS через Web View.
Описание:
1 | Клиент создает заказ. |
2 | Мобильный сервер регистрирует этот заказ в платежном шлюзе через register.do. Используйте параметр returnUrl в качестве маркера для закрытия Web View после перенаправления из ACS на Шаге 14. |
3 | Мобильный сервер получает в ответе уникальный номер заказа mdOrder . |
4 | Клиент заполняет платежные данные в мобильном приложении. |
5 | Мобильное приложение вызывает SDK для создания seToken. (Android: sdkCore.generateWithCard; iOS: CKCToken.generateWithCard). Публичный ключ, который требуется в соответствующем методе, необходимо брать с online ресурса https://api.sbergate.com/payment/se/keys.do . Если по этой ссылке доступно несколько ключей, следует использовать первый ключ. (Имейте в виду, что для тестовой и рабочей сред используются разные ключи.) |
6 | Мобильное приложение отправляет seToken на мобильный сервер. |
7 | Мобильный сервер использует этот seToken для совершения платежа через paymentorder.do.
|
8 | Мобильный сервер получает ответ без редиректа на ACS. Это означает, что оплата завершена и нужно перейти к Шагу 16. |
9 | Мобильный сервер получает ответ с редиректом на ACS. |
10 | Мобильное приложение открывает Web View с данными редиректа на ACS. |
11 | Клиент вводит свой одноразовый пароль в форму ACS. |
12 | ACS перенаправляет клиента на платежный шлюз. |
13 | Платежный шлюз осуществляет платеж. |
14 | Платежный шлюз перенаправляет клиента на returnUrl , который можно использовать в качестве маркера для закрытия Web View. |
15 | Мобильное приложение закрывает Web View. |
16 | Платежный шлюз отправляет уведомление обратного вызова на сервер продавца, если оно настроено для продавца. |
17 | Мобильный сервер проверяет окончательный статус платежа через getOrderStatusExtended.do. |
18 | Мобильное приложение показывает результат платежа клиенту. |
iOS
iOS-интеграция
Интеграция SDKCore.framework
Вы можете интегрировать SDKCore.framework, добавив его вручную.
- Используйте последнюю версию фреймворка - sdkcore.zip ;
- Выберите файл
SDKCore.framework
и добавьте его в папку проекта.
- Откройте страницу Targets → General → Frameworks, Libraries, and Embedded Content. Для
SDKCore.framework
с столбце Embed замените Do not Embed на Embed & Sign.
- Затем импортируйте фреймворк в файл
ViewController.swift
.
//ViewController.swift ... import SDKCore ...
Работа с API
Внешние зависимости
Для генерации токена необходимо задать открытый ключ.
let publicKey: String = "-----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoIITqh9xlGx4tWA+aucb0V0YuFC9aXzJb0epdioSkq3qzNdRSZIxe/dHqcbMN2SyhzvN6MRVl3xyjGAV+lwk8poD4BRW3VwPUkT8xG/P/YLzi5N8lY6ILlfw6WCtRPK5bKGGnERcX5dqL60LhOPRDSYT5NHbbp/J2eFWyLigdU9Sq7jvz9ixOLh6xD7pgNgHtnOJ3Cw0Gqy03r3+m3+CBZwrzcp7ZFs41bit7/t1nIqgx78BCTPugap88Gs+8ZjdfDvuDM+/3EwwK0UVTj0SQOv0E5KcEHENL9QQg3ujmEi+zAavulPqXH5907q21lwQeemzkTJH4o2RCCVeYO+YrQIDAQAB-----END PUBLIC KEY-----"
Метод генерации токена
let sdkCore = SdkCore() let cardParams = CardParams( pan: "4111111111111111", cvc: "123", expiryMMYY: "12/28", cardholder: "TEST CARDHOLDER", mdOrder: "mdOrder", pubKey: publicKey ) let cardParamsConfig = SDKCoreConfig( paymentMethodParams: .cardParams(params: cardParams) ) let tokenResult = sdkCore.generateWithConfig(config: cardParamsConfig) let bindignParams = BindingParams( pubKey: publicKey, bindingId: "das", cvc: "123", mdOrder: "mdOrder" ) let bindingParamsConfig = SDKCoreConfig( paymentMethodParams: .bindingParams(params: bindignParams) ) let tokenResult = sdkCore.generateWithConfig(config: bindingParamsConfig)
Модели
CardParams
Название свойства | Тип данных | Значение по умолчанию | Необязательное | Описание |
---|---|---|---|---|
cardHolder | String | - | Да | Имя и фамилия держателя карты |
mdOrder | String | - | Нет | Номер заказа |
pan | String | - | Нет | Номер карты |
pubKey | String | - | Нет | Открытый ключ |
cvc | String | - | Нет | Секретный код карты |
expiryMMYY | String | - | Нет | Срок действия карты |
BindingParams
Название свойства | Тип данных | Значение по умолчанию | Необязательное | Описание |
---|---|---|---|---|
mdOrder | String | - | Нет | Номер заказа |
bindingId | String | - | Нет | Номер связки для карты |
cvc | String | - | Да | Секретный код карты |
pubKey | String | - | Нет | Открытый ключ |
Ошибки валидации полей
ParamField | Ошибка | ||
---|---|---|---|
UNKNOWN | - | Неизвестная ошибка | |
PAN | required | Указано пустое поле | |
invalid | Некорректное значение | ||
invalid-format | Используются недопустимые символы. Доступны только цифры. | ||
CVC | required | Указано пустое поле | |
invalid | Некорректное значение | ||
EXPIRY | required | Указано пустое поле | |
invalid | Некорректное значение | ||
invalid-format | Формат не соответствует шаблону MM/YY | ||
CARDHOLDER | required | Указано пустое поле | |
invalid | Некорректное значение | ||
invalid-format | Используются недопустимые символы. Доступны только буквы и пробелы. | ||
BINDING_ID | required | Указано пустое поле | |
invalid | Некорректное значение | ||
MD_ORDER | required | Указано пустое поле | |
invalid | Некорректное значение | ||
PUB_KEY | required | Указано пустое поле |
Android
Android-интеграция
Подключение к Gradle проекту путем добавления файлов .aar библиотеки
Последняя версия файла библиотеки - sdk_core-release.zip.
Необходимо добавить файл библиотеки sdk_core-release.aar в папку libs, а затем указать зависимость добавленной библиотеки.
build.gradle.kts
allprojects { repositories { // ... flatDir { dirs("libs") } } } dependencies { // dependency is mandatory to add implementation(group = "", name = "sdk_core-release", ext = "aar") }
build.gradle
allprojects { repositories { // ... flatDir { dirs 'libs' } } } dependencies { // dependency is mandatory to add implementation(group: '', name: 'sdk_core-release', ext: 'aar') }
Конфигурация Android
Логирование
Внутренние процессы логируются с тегом SDK-Core
. Вы также можете логировать свои процессы.
Логирование доступно через объект Logger
.
- Для добавления log- интерфейсов необходимо вызвать Logger-метод
addLogInterface()
.
Пример для логирования в LogCat:
... Logger.addLogInterface(object : LogInterface { override fun log(classMethod: Class<Any>, tag: String, message: String, exception: Exception?) { Log.i(tag, "$classMethod: $message", exception) } }) ...
По умолчанию используется тег SDK-Core
. Вы можете установить свой собственный, если хотите.
- Для логирования собственных событий необходимо вызвать Logger-метод log().
... Logger.log(this.javaClass, "MyTag", "My process...", null) ...
Пример Kotlin_core (без графического интерфейса)
Пример формирования криптограммы:
import net.payrdr.mobile.payment.sdk.core.SDKCore import net.payrdr.mobile.payment.sdk.core.TokenResult import net.payrdr.mobile.payment.sdk.core.model.BindingParams import net.payrdr.mobile.payment.sdk.core.model.CardParams import net.payrdr.mobile.payment.sdk.core.validation.BaseValidator import net.payrdr.mobile.payment.sdk.core.validation.CardCodeValidator import net.payrdr.mobile.payment.sdk.core.validation.CardExpiryValidator import net.payrdr.mobile.payment.sdk.core.validation.CardHolderValidator import net.payrdr.mobile.payment.sdk.core.validation.CardNumberValidator import net.payrdr.mobile.payment.sdk.core.validation.OrderNumberValidator class MainActivity : AppCompatActivity() { // initialization of validators for card information entry fields private val cardNumberValidator by lazy { CardNumberValidator(this) } private val cardExpiryValidator by lazy { CardExpiryValidator(this) } private val cardCodeValidator by lazy { CardCodeValidator(this) } private val cardHolderValidator by lazy { CardHolderValidator(this) } private val orderNumberValidator by lazy { OrderNumberValidator(this) } private val sdkCore by lazy { SDKCore(context = this) } override fun onCreate(savedInstanceState: Bundle?) { // installation of validators on the card information entry fields cardNumberInput.setupValidator(cardNumberValidator) cardExpiryInput.setupValidator(cardExpiryValidator) cardCodeInput.setupValidator(cardCodeValidator) cardHolderInput.setupValidator(cardHolderValidator) mdOrderInput.setupValidator(orderNumberValidator) // creation of an object and initialization of fields for a new card val params = NewPaymentMethodCardParams( pan = cardNumberInput.text.toString(), cvc = cardCodeInput.text.toString(), expiryMMYY = cardExpiryInput.text.toString(), cardHolder = cardHolderInput.text.toString(), pubKey = pubKeyInput.text.toString() ) // method call to get the cryptogram for a new card sdkCore.generateWithConfig(SDKCoreConfig(params)) // Creation of an object and initialization of fields for the linked card val params = NewPaymentMethodStoredCardParams( storedPaymentId = "storedPaymentMethodId", cvc = "123", pubKey = pubKeyInput.text.toString() ) // method call to get the cryptogram for the linked card sdkCore.generateWithConfig(SDKCoreConfig(params)) } }
Модели
NewPaymentMethodCardParams
Название свойства | Тип данных | Значение по умолчанию | Необязательно | Описание |
---|---|---|---|---|
pan | String | - | Нет | Номер карты |
cvc | String | - | Нет | Секретный код карты |
expiryMMYY | String | - | Нет | Срок действия карты |
cardHolder | String | - | Нет | Имя и фамилия держателя карты |
pubKey | String | - | Нет | Открытый ключ |
NewPaymentMethodStoredCardParams
Название свойства | Тип данных | Значение по умолчанию | Необязательно | Описание |
---|---|---|---|---|
storedPaymentId | String | - | Нет | Номер связки для карты |
cvc | String | - | Нет | Секретный код карты |
pubKey | String | - | Нет | Открытый ключ |
TokenResult
Название свойства | Тип данных | Значение по умолчанию | Необязательно | Описание |
---|---|---|---|---|
token | String | - | Нет | Токен как строка |
errors | Map | - | Нет | Ошибка при генерации токена |
Ошибки валидации полей
ParamField | Ошибка | Описание |
---|---|---|
PAN | required | Указано пустое поле |
invalid | Некорректное значение | |
invalid-format | Используются недопустимые символы. Доступны только цифры. | |
CVC | required | Указано пустое поле |
invalid | Некорректное значение | |
EXPIRY | required | Указано пустое поле |
invalid | Некорректное значение | |
invalid-format | Формат не соответствует шаблону MM/YY | |
CARDHOLDER | required | Указано пустое поле |
invalid | Некорректное значение | |
invalid-format | Используются недопустимые символы. Доступны только буквы и пробелы. | |
PUB_KEY | required | Указано пустое поле |
STORED_PAYMENT_ID | required | Указано пустое поле |
invalid | Некорректное значение |
Работа с API
Внешние зависимости
Для генерации токена необходимо установить открытый ключ.
val publicKey: String = "-----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoIITqh9xlGx4tWA+aucb0V0YuFC9aXzJb0epdioSkq3qzNdRSZIxe/dHqcbMN2SyhzvN6MRVl3xyjGAV+lwk8poD4BRW3VwPUkT8xG/P/YLzi5N8lY6ILlfw6WCtRPK5bKGGnERcX5dqL60LhOPRDSYT5NHbbp/J2eFWyLigdU9Sq7jvz9ixOLh6xD7pgNgHtnOJ3Cw0Gqy03r3+m3+CBZwrzcp7ZFs41bit7/t1nIqgx78BCTPugap88Gs+8ZjdfDvuDM+/3EwwK0UVTj0SQOv0E5KcEHENL9QQg3ujmEi+zAavulPqXH5907q21lwQeemzkTJH4o2RCCVeYO+YrQIDAQAB-----END PUBLIC KEY-----"
Метод генерации токена
// TokenResult with CardParams val cardParams: CardParams = CardParams( mdOrder = "mdOrder", pan = "4111111111111111", cvc = "123", expiryMMYY = "12/28", cardHolder = "TEST CARDHOLDER", pubKey = "publicKey" ) val tokenResult = sdkCore.generationWithConfig(paymentCardParams = cardParams) // TokenResult with BindingParams val bindingParams: BindingParams = BindingParams( mdOrder = "mdOrder", bindingID = "das", cvc = "123", pubKey = "publicKey" ) val tokenResult = sdkCore.generationWithConfig(paymentCardParams = bindingParams)
React Native
Для реализации интеграции Mobile SDK Core в React Native-приложение необходимо настроить мост — обёртку на Kotlin/Java или Swift/Objective-C, которая будет принимать вызовы из JavaScript и передавать их в нативный код SDK. З Мосты в React Native позволяют вашему JS-коду вызывать методы нативных библиотек так же просто, как обычные асинхронные функции: вы объявляете нативный модуль с методами, которые возвращают результат через Promise, React Native автоматически связывает эти методы с JavaScript, и дальше вы работаете с ними в приложении без глубоких знаний платформенных API.
IOS
1. Интегрируйте SDKCore в ваш проект в соответствии с разделом iOS-интеграция.
2. Проверьте, что для фреймворка DKCore.xcframework
в колонке Embed выбрано Embed & Sign.
3. Создайте Swift-модуль RadarSdkBridge.swift
со следующим содержимым:
import Foundation import React import SDKCore @objc(RadarSdk) class RadarSdkBridge: NSObject { private let sdkCore = SdkCore() @objc func generateNewCardToken( _ pan: String, cvc: String, expiryMMYY: String, cardHolder: String, mdOrder: String, pubKey: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock ) { do { let params = CardParams( pan: pan, cvc: cvc, expiryMMYY: expiryMMYY, cardholder: cardHolder, mdOrder: mdOrder, pubKey: pubKey ) let config = SDKCoreConfig(paymentMethodParams: .cardParams(params: params)) let result = try sdkCore.generateWithConfig(config: config) resolve(result.token) } catch { reject("TOKEN_ERROR", error.localizedDescription, error) } } @objc func generateStoredCardToken( _ storedPaymentId: String, cvc: String, pubKey: String, mdOrder: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock ) { do { let params = BindingParams( pubKey: pubKey, bindingId: storedPaymentId, cvc: cvc, mdOrder: mdOrder ) let config = SDKCoreConfig(paymentMethodParams: .bindingParams(params: params)) let result = try sdkCore.generateWithConfig(config: config) resolve(result.token) } catch { reject("TOKEN_ERROR", error.localizedDescription, error) } } @objc static func requiresMainQueueSetup() -> Bool { return false } }4. Реализуйте Objective-C мост в файле
RadarSdkBridge.m
:
#import <React/RCTBridgeModule.h> @interface RCT_EXTERN_MODULE(RadarSdk, NSObject) RCT_EXTERN_METHOD(generateNewCardToken: (NSString *)pan cvc:(NSString *)cvc expiryMMYY:(NSString *)expiryMMYY cardHolder:(NSString *)cardHolder mdOrder:(NSString *)mdOrder pubKey:(NSString *)pubKey resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject ) RCT_EXTERN_METHOD(generateStoredCardToken: (NSString *)storedPaymentId cvc:(NSString *)cvc pubKey:(NSString *)pubKey mdOrder:(NSString *)mdOrder resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject ) @end
Android
1. Скачайте файлы sdk_core-release.aar
и sdk_logs-release.aar
и скопируйте их в папку android/app/libs/
согласно разделу Android-интеграция .
2. Добавьте плоский репозиторий и зависимости в файл android/app/build.gradle
:
android { // … остальная конфигурация вашего проекта … } repositories { flatDir { dirs 'libs' } } dependencies { // … прочие зависимости … implementation(name: 'sdk_core-release', ext: 'aar') implementation(name: 'sdk_logs-release', ext: 'aar') }
Реализация Native Module для Kotlin
1. Создайте файл RadarSdkModule.kt в директории android/app/src/main/java/…/radar/
:
package com.mobilesdkdemo.radar import com.facebook.react.bridge.Promise import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.bridge.ReactContextBaseJavaModule import com.facebook.react.bridge.ReactMethod import net.payrdr.mobile.payment.sdk.core.SDKCore import net.payrdr.mobile.payment.sdk.core.model.SDKCoreConfig import net.payrdr.mobile.payment.sdk.core.model.CardParams import net.payrdr.mobile.payment.sdk.core.model.BindingParams class RadarSdkModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) { override fun getName(): String = "RadarSdk" private val sdkCore by lazy { SDKCore(context = reactApplicationContext) } @ReactMethod fun generateNewCardToken( pan: String, cvc: String, expiryMMYY: String, cardHolder: String, mdOrder: String, pubKey: String, promise: Promise ) { try { val params = CardParams( pan = pan, cvc = cvc, expiryMMYY = expiryMMYY, cardHolder = cardHolder, mdOrder = mdOrder, pubKey = pubKey ) val config = SDKCoreConfig(paymentCardParams = params) val result = sdkCore.generateWithConfig(config) promise.resolve(result.token) } catch (e: Exception) { promise.reject("TOKEN_ERROR", e) } } @ReactMethod fun generateStoredCardToken( storedPaymentId: String, cvc: String, pubKey: String, mdOrder: String, promise: Promise ) { try { val params = BindingParams( bindingID = storedPaymentId, mdOrder = mdOrder, cvc = cvc, pubKey = pubKey ) val config = SDKCoreConfig(paymentCardParams = params) val result = sdkCore.generateWithConfig(config) promise.resolve(result.token) } catch (e: Exception) { promise.reject("TOKEN_ERROR", e) } } }2. Создайте пакет
RadarSdkPackage.kt
в той же директории:
package com.mobilesdkdemo.radar import com.facebook.react.ReactPackage import com.facebook.react.bridge.NativeModule import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.uimanager.ViewManager class RadarSdkPackage : ReactPackage { override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> = listOf(RadarSdkModule(reactContext)) override fun createViewManagers( reactContext: ReactApplicationContext ): List<ViewManager<*, *>> = emptyList() }
3. Зарегистрируйте созданный пакет в MainApplication.kt
:
package com.mobilesdkdemo import android.app.Application import com.facebook.react.PackageList import com.facebook.react.ReactApplication import com.facebook.react.ReactNativeHost import com.facebook.react.ReactHost import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load import com.facebook.react.defaults.DefaultReactNativeHost import com.facebook.soloader.SoLoader import com.mobilesdkdemo.radar.RadarSdkPackage class MainApplication : Application(), ReactApplication { override val reactNativeHost: ReactNativeHost = object : DefaultReactNativeHost(this) { override fun getPackages(): List<ReactPackage> = PackageList(this).packages.apply { add(RadarSdkPackage()) // Регистрируем пакет } override fun getJSMainModuleName(): String = "index" override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED } override val reactHost: ReactHost get() = getReactNativeHost(applicationContext, reactNativeHost) override fun onCreate() { super.onCreate() SoLoader.init(this, false) if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { load() } } }
Использование в React Native
Используйте методы из JavaScript/TypeScript следующим образом:
import { NativeModules } from 'react-native'; const { RadarSdk } = NativeModules; // Генерация токена для новой карты const token = await RadarSdk.generateNewCardToken( '4111111111111111', // PAN '123', // CVC '12/25', // Expiry MM/YY 'CARDHOLDER NAME', // Имя держателя карты 'mdOrder', // Номер, полученный при регистрации заказа '-----BEGIN PUBLIC KEY-----...' // Публичный ключ из /payment/se/keys.do ); // Генерация токена для привязанной карты const bindToken = await RadarSdk.generateStoredCardToken( 'bindingId', // ID сохранённой карты '123', // CVC '-----BEGIN PUBLIC KEY-----…', // Публичный ключ из /payment/se/keys.do 'mdOrder' // Номер, полученный при регистрации заказа );