├── app ├── .gitignore ├── release │ ├── app-release.apk │ └── output.json ├── src │ └── main │ │ ├── res │ │ ├── drawable │ │ │ ├── bike.jpg │ │ │ ├── filled_box.xml │ │ │ ├── button_gradient_bg.xml │ │ │ ├── button_add_to_cart_bg.xml │ │ │ ├── ic_email_white_24dp.xml │ │ │ ├── ic_person_black_24dp.xml │ │ │ ├── splashscreen_bg.xml │ │ │ ├── ic_credit_card_black_24dp.xml │ │ │ ├── ic_date_range_black_24dp.xml │ │ │ ├── ic_phone_white_24dp.xml │ │ │ ├── ic_lock_black_24dp.xml │ │ │ ├── ic_shopping_cart_white_24dp.xml │ │ │ ├── pay_with_google_button_no_shadow_background.xml │ │ │ ├── pay_with_google_button_overlay.xml │ │ │ ├── pay_with_google_button_background.xml │ │ │ ├── pay_with_google_button_short_content.xml │ │ │ └── ic_launcher_background.xml │ │ ├── mipmap-hdpi │ │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ │ └── ic_launcher.png │ │ ├── drawable-xhdpi │ │ │ ├── temp_product.png │ │ │ ├── pay_with_google_button_background_image.9.png │ │ │ ├── pay_with_google_button_background_image_focused.9.png │ │ │ ├── pay_with_google_button_background_image_pressed.9.png │ │ │ ├── pay_with_google_button_no_shadow_background_image.9.png │ │ │ ├── pay_with_google_button_no_shadow_background_image_focused.9.png │ │ │ └── pay_with_google_button_no_shadow_background_image_pressed.9.png │ │ ├── drawable-xxhdpi │ │ │ ├── splash_logo.png │ │ │ ├── pay_with_google_button_background_image.9.png │ │ │ ├── pay_with_google_button_background_image_focused.9.png │ │ │ ├── pay_with_google_button_background_image_pressed.9.png │ │ │ ├── pay_with_google_button_no_shadow_background_image.9.png │ │ │ ├── pay_with_google_button_no_shadow_background_image_focused.9.png │ │ │ └── pay_with_google_button_no_shadow_background_image_pressed.9.png │ │ ├── mipmap-xxxhdpi │ │ │ └── ic_launcher.png │ │ ├── drawable-hdpi │ │ │ ├── pay_with_google_button_background_image.9.png │ │ │ ├── pay_with_google_button_background_image_focused.9.png │ │ │ ├── pay_with_google_button_background_image_pressed.9.png │ │ │ ├── pay_with_google_button_no_shadow_background_image.9.png │ │ │ ├── pay_with_google_button_no_shadow_background_image_focused.9.png │ │ │ └── pay_with_google_button_no_shadow_background_image_pressed.9.png │ │ ├── drawable-mdpi │ │ │ ├── pay_with_google_button_background_image.9.png │ │ │ ├── pay_with_google_button_background_image_focused.9.png │ │ │ ├── pay_with_google_button_background_image_pressed.9.png │ │ │ ├── pay_with_google_button_no_shadow_background_image.9.png │ │ │ ├── pay_with_google_button_no_shadow_background_image_focused.9.png │ │ │ └── pay_with_google_button_no_shadow_background_image_pressed.9.png │ │ ├── drawable-xxxhdpi │ │ │ ├── pay_with_google_button_background_image.9.png │ │ │ ├── pay_with_google_button_background_image_focused.9.png │ │ │ ├── pay_with_google_button_background_image_pressed.9.png │ │ │ ├── pay_with_google_button_no_shadow_background_image.9.png │ │ │ ├── pay_with_google_button_no_shadow_background_image_focused.9.png │ │ │ └── pay_with_google_button_no_shadow_background_image_pressed.9.png │ │ ├── values │ │ │ ├── colors.xml │ │ │ ├── dimens.xml │ │ │ ├── styles.xml │ │ │ └── strings.xml │ │ ├── menu │ │ │ └── main.xml │ │ ├── layout │ │ │ ├── toolbar.xml │ │ │ ├── progress_dialog.xml │ │ │ ├── pay_with_google_button_no_shadow.xml │ │ │ ├── pay_with_google_button.xml │ │ │ ├── pay_with_google_button_short_no_shadow.xml │ │ │ ├── pay_with_google_button_short.xml │ │ │ ├── item_list_cart.xml │ │ │ ├── item_list_product.xml │ │ │ ├── activity_main.xml │ │ │ ├── activity_cart.xml │ │ │ └── activity_checkout.xml │ │ ├── drawable-v21 │ │ │ ├── pay_with_google_button_no_shadow_background.xml │ │ │ └── pay_with_google_button_background.xml │ │ ├── drawable-v24 │ │ │ └── ic_launcher_foreground.xml │ │ └── drawable-ja │ │ │ └── pay_with_google_button_content.xml │ │ ├── java │ │ └── ru │ │ │ └── cloudpayments │ │ │ └── demo │ │ │ ├── api │ │ │ ├── events │ │ │ │ └── EmptyEvent.java │ │ │ ├── response │ │ │ │ ├── ShopApiResponse.java │ │ │ │ ├── PayApiError.java │ │ │ │ └── PayApiResponse.java │ │ │ ├── interfaces │ │ │ │ ├── ShopMethods.java │ │ │ │ └── PayMethods.java │ │ │ ├── models │ │ │ │ ├── Post3dsRequestArgs.java │ │ │ │ ├── Transaction.java │ │ │ │ └── PayRequestArgs.java │ │ │ ├── ShopApi.java │ │ │ ├── ApiMap.java │ │ │ ├── PayApiFactory.java │ │ │ ├── ShopApiFactory.java │ │ │ └── PayApi.java │ │ │ ├── base │ │ │ ├── BaseAdapter.java │ │ │ ├── BaseListActivity.java │ │ │ ├── Base3DSDialog.java │ │ │ ├── BaseViewHolder.java │ │ │ └── BaseActivity.java │ │ │ ├── support │ │ │ ├── Constants.java │ │ │ └── SideSpaceItemDecoration.java │ │ │ ├── models │ │ │ └── Product.java │ │ │ ├── managers │ │ │ └── CartManager.java │ │ │ ├── screens │ │ │ ├── cart │ │ │ │ ├── CartAdapter.java │ │ │ │ ├── CartHolder.java │ │ │ │ └── CartActivity.java │ │ │ └── main │ │ │ │ ├── ProductsAdapter.java │ │ │ │ ├── ProductHolder.java │ │ │ │ └── MainActivity.java │ │ │ └── googlepay │ │ │ ├── ItemInfo.java │ │ │ ├── ConstantsGPay.java │ │ │ └── PaymentsUtil.java │ │ └── AndroidManifest.xml ├── proguard-rules.pro └── build.gradle ├── sdk ├── .gitignore ├── src │ └── main │ │ ├── res │ │ ├── values │ │ │ └── strings.xml │ │ └── layout │ │ │ └── dialog_fragment_three_ds.xml │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── ru │ │ └── cloudpayments │ │ └── sdk │ │ ├── three_ds │ │ ├── ThreeDSDialogListener.java │ │ └── ThreeDsDialogFragment.java │ │ └── cp_card │ │ ├── api │ │ ├── models │ │ │ ├── BinInfo.java │ │ │ └── BinInfoResponse.java │ │ └── CPCardApi.java │ │ ├── CPCardType.java │ │ └── CPCard.java ├── proguard-rules.pro ├── build.gradle └── sdk.iml ├── settings.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .idea ├── compiler.xml ├── misc.xml └── jarRepositories.xml ├── api ├── cp_config.php ├── cp_post3ds.php ├── cp_auth.php └── cp_charge.php ├── local.properties ├── gradle.properties ├── CloudPaymentsDemo.iml ├── .gitignore ├── gradlew.bat ├── gradlew └── README.md /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /sdk/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app', ':sdk' 2 | -------------------------------------------------------------------------------- /sdk/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | sdk 3 | 4 | -------------------------------------------------------------------------------- /app/release/app-release.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudpayments/SDK-Android/HEAD/app/release/app-release.apk -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudpayments/SDK-Android/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /app/src/main/res/drawable/bike.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudpayments/SDK-Android/HEAD/app/src/main/res/drawable/bike.jpg -------------------------------------------------------------------------------- /sdk/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /app/src/main/java/ru/cloudpayments/demo/api/events/EmptyEvent.java: -------------------------------------------------------------------------------- 1 | package ru.cloudpayments.demo.api.events; 2 | 3 | public class EmptyEvent { 4 | } 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudpayments/SDK-Android/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudpayments/SDK-Android/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudpayments/SDK-Android/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudpayments/SDK-Android/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/temp_product.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudpayments/SDK-Android/HEAD/app/src/main/res/drawable-xhdpi/temp_product.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/splash_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudpayments/SDK-Android/HEAD/app/src/main/res/drawable-xxhdpi/splash_logo.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudpayments/SDK-Android/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/java/ru/cloudpayments/demo/api/response/ShopApiResponse.java: -------------------------------------------------------------------------------- 1 | package ru.cloudpayments.demo.api.response; 2 | 3 | public class ShopApiResponse { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/pay_with_google_button_background_image.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudpayments/SDK-Android/HEAD/app/src/main/res/drawable-hdpi/pay_with_google_button_background_image.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/pay_with_google_button_background_image.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudpayments/SDK-Android/HEAD/app/src/main/res/drawable-mdpi/pay_with_google_button_background_image.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/pay_with_google_button_background_image.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudpayments/SDK-Android/HEAD/app/src/main/res/drawable-xhdpi/pay_with_google_button_background_image.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/pay_with_google_button_background_image.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudpayments/SDK-Android/HEAD/app/src/main/res/drawable-xxhdpi/pay_with_google_button_background_image.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/pay_with_google_button_background_image.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudpayments/SDK-Android/HEAD/app/src/main/res/drawable-xxxhdpi/pay_with_google_button_background_image.9.png -------------------------------------------------------------------------------- /app/release/output.json: -------------------------------------------------------------------------------- 1 | [{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":1},"path":"app-release.apk","properties":{"packageId":"ru.cloudpayments.paywithgoogletest","split":"","minSdkVersion":"19"}}] -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/pay_with_google_button_background_image_focused.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudpayments/SDK-Android/HEAD/app/src/main/res/drawable-hdpi/pay_with_google_button_background_image_focused.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/pay_with_google_button_background_image_pressed.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudpayments/SDK-Android/HEAD/app/src/main/res/drawable-hdpi/pay_with_google_button_background_image_pressed.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/pay_with_google_button_no_shadow_background_image.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudpayments/SDK-Android/HEAD/app/src/main/res/drawable-hdpi/pay_with_google_button_no_shadow_background_image.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/pay_with_google_button_background_image_focused.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudpayments/SDK-Android/HEAD/app/src/main/res/drawable-mdpi/pay_with_google_button_background_image_focused.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/pay_with_google_button_background_image_pressed.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudpayments/SDK-Android/HEAD/app/src/main/res/drawable-mdpi/pay_with_google_button_background_image_pressed.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/pay_with_google_button_no_shadow_background_image.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudpayments/SDK-Android/HEAD/app/src/main/res/drawable-mdpi/pay_with_google_button_no_shadow_background_image.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/pay_with_google_button_background_image_focused.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudpayments/SDK-Android/HEAD/app/src/main/res/drawable-xhdpi/pay_with_google_button_background_image_focused.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/pay_with_google_button_background_image_pressed.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudpayments/SDK-Android/HEAD/app/src/main/res/drawable-xhdpi/pay_with_google_button_background_image_pressed.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/pay_with_google_button_background_image_focused.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudpayments/SDK-Android/HEAD/app/src/main/res/drawable-xxhdpi/pay_with_google_button_background_image_focused.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/pay_with_google_button_background_image_pressed.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudpayments/SDK-Android/HEAD/app/src/main/res/drawable-xxhdpi/pay_with_google_button_background_image_pressed.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/pay_with_google_button_no_shadow_background_image.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudpayments/SDK-Android/HEAD/app/src/main/res/drawable-xhdpi/pay_with_google_button_no_shadow_background_image.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/pay_with_google_button_no_shadow_background_image.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudpayments/SDK-Android/HEAD/app/src/main/res/drawable-xxhdpi/pay_with_google_button_no_shadow_background_image.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/pay_with_google_button_background_image_focused.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudpayments/SDK-Android/HEAD/app/src/main/res/drawable-xxxhdpi/pay_with_google_button_background_image_focused.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/pay_with_google_button_background_image_pressed.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudpayments/SDK-Android/HEAD/app/src/main/res/drawable-xxxhdpi/pay_with_google_button_background_image_pressed.9.png -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/pay_with_google_button_no_shadow_background_image.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudpayments/SDK-Android/HEAD/app/src/main/res/drawable-xxxhdpi/pay_with_google_button_no_shadow_background_image.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/pay_with_google_button_no_shadow_background_image_focused.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudpayments/SDK-Android/HEAD/app/src/main/res/drawable-hdpi/pay_with_google_button_no_shadow_background_image_focused.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/pay_with_google_button_no_shadow_background_image_pressed.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudpayments/SDK-Android/HEAD/app/src/main/res/drawable-hdpi/pay_with_google_button_no_shadow_background_image_pressed.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/pay_with_google_button_no_shadow_background_image_focused.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudpayments/SDK-Android/HEAD/app/src/main/res/drawable-mdpi/pay_with_google_button_no_shadow_background_image_focused.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/pay_with_google_button_no_shadow_background_image_pressed.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudpayments/SDK-Android/HEAD/app/src/main/res/drawable-mdpi/pay_with_google_button_no_shadow_background_image_pressed.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/pay_with_google_button_no_shadow_background_image_focused.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudpayments/SDK-Android/HEAD/app/src/main/res/drawable-xhdpi/pay_with_google_button_no_shadow_background_image_focused.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/pay_with_google_button_no_shadow_background_image_pressed.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudpayments/SDK-Android/HEAD/app/src/main/res/drawable-xhdpi/pay_with_google_button_no_shadow_background_image_pressed.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/pay_with_google_button_no_shadow_background_image_focused.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudpayments/SDK-Android/HEAD/app/src/main/res/drawable-xxhdpi/pay_with_google_button_no_shadow_background_image_focused.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/pay_with_google_button_no_shadow_background_image_pressed.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudpayments/SDK-Android/HEAD/app/src/main/res/drawable-xxhdpi/pay_with_google_button_no_shadow_background_image_pressed.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/pay_with_google_button_no_shadow_background_image_focused.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudpayments/SDK-Android/HEAD/app/src/main/res/drawable-xxxhdpi/pay_with_google_button_no_shadow_background_image_focused.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/pay_with_google_button_no_shadow_background_image_pressed.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudpayments/SDK-Android/HEAD/app/src/main/res/drawable-xxxhdpi/pay_with_google_button_no_shadow_background_image_pressed.9.png -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #6494DA 4 | #393861 5 | #6494DA 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/java/ru/cloudpayments/demo/base/BaseAdapter.java: -------------------------------------------------------------------------------- 1 | package ru.cloudpayments.demo.base; 2 | 3 | import androidx.recyclerview.widget.RecyclerView; 4 | 5 | public abstract class BaseAdapter extends RecyclerView.Adapter { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /api/cp_config.php: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Mar 19 16:51:38 YEKT 2020 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip 7 | -------------------------------------------------------------------------------- /sdk/src/main/java/ru/cloudpayments/sdk/three_ds/ThreeDSDialogListener.java: -------------------------------------------------------------------------------- 1 | package ru.cloudpayments.sdk.three_ds; 2 | 3 | public interface ThreeDSDialogListener { 4 | 5 | void onAuthorizationCompleted(final String md, final String paRes); 6 | 7 | void onAuthorizationFailed(final String html); 8 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/filled_box.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/button_gradient_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | 9 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/button_add_to_cart_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | 9 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/menu/main.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 11 | -------------------------------------------------------------------------------- /app/src/main/java/ru/cloudpayments/demo/support/Constants.java: -------------------------------------------------------------------------------- 1 | package ru.cloudpayments.demo.support; 2 | 3 | public class Constants { 4 | 5 | public static final String CONSUMER_KEY = "ck_ddb320b48b89a170248545eb3bb8e822365aa917"; 6 | public static final String CONSUMER_SECRET = "cs_35ad6d0cf8e6b149e66968efdad87112ca2bc2d3"; 7 | 8 | public static final String MERCHANT_PUBLIC_ID = "test_api_00000000000000000000002"; // Test host 9 | } 10 | -------------------------------------------------------------------------------- /local.properties: -------------------------------------------------------------------------------- 1 | ## This file must *NOT* be checked into Version Control Systems, 2 | # as it contains information specific to your local configuration. 3 | # 4 | # Location of the SDK. This is only used by Gradle. 5 | # For customization when using a Version Control System, please read the 6 | # header note. 7 | #Fri Oct 16 17:38:33 SAMT 2020 8 | ndk.dir=/Users/antonignatov/Library/Android/sdk/ndk-bundle 9 | sdk.dir=/Users/iskhakov.s/Library/Android/sdk 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_email_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /sdk/src/main/res/layout/dialog_fragment_three_ds.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_person_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/java/ru/cloudpayments/demo/api/response/PayApiError.java: -------------------------------------------------------------------------------- 1 | package ru.cloudpayments.demo.api.response; 2 | 3 | public class PayApiError extends Throwable { 4 | 5 | private String message; 6 | 7 | @Override 8 | public String getMessage() { 9 | return message; 10 | } 11 | 12 | public void setMessage(String message) { 13 | this.message = message; 14 | } 15 | 16 | public PayApiError(String message) { 17 | this.message = message; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/splashscreen_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 9 | 10 | 11 | 12 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_credit_card_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /sdk/src/main/java/ru/cloudpayments/sdk/cp_card/api/models/BinInfo.java: -------------------------------------------------------------------------------- 1 | package ru.cloudpayments.sdk.cp_card.api.models; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | public class BinInfo { 6 | 7 | @SerializedName("LogoUrl") 8 | private String logoUrl; 9 | 10 | @SerializedName("BankName") 11 | private String bankName; 12 | 13 | public String getLogoUrl() { 14 | return logoUrl; 15 | } 16 | 17 | public String getBankName() { 18 | return bankName; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/ru/cloudpayments/demo/base/BaseListActivity.java: -------------------------------------------------------------------------------- 1 | package ru.cloudpayments.demo.base; 2 | 3 | import androidx.recyclerview.widget.RecyclerView; 4 | 5 | import butterknife.BindView; 6 | import ru.cloudpayments.demo.R; 7 | 8 | public abstract class BaseListActivity extends BaseActivity{ 9 | 10 | protected T adapter; 11 | 12 | // This fields are marked as public for ButterKnife normal binding 13 | @BindView(R.id.recycler_view) 14 | public RecyclerView recyclerView; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_date_range_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_phone_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/java/ru/cloudpayments/demo/api/interfaces/ShopMethods.java: -------------------------------------------------------------------------------- 1 | package ru.cloudpayments.demo.api.interfaces; 2 | 3 | import java.util.List; 4 | 5 | import io.reactivex.Observable; 6 | import retrofit2.http.GET; 7 | import retrofit2.http.Header; 8 | import retrofit2.http.QueryMap; 9 | import ru.cloudpayments.demo.api.ApiMap; 10 | import ru.cloudpayments.demo.models.Product; 11 | 12 | public interface ShopMethods { 13 | 14 | @GET("products") 15 | Observable> getProducts(@Header("Content-Type") String contentType, @Header("Authorization") String authKey, @QueryMap ApiMap args); 16 | 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_lock_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/layout/toolbar.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/java/ru/cloudpayments/demo/base/Base3DSDialog.java: -------------------------------------------------------------------------------- 1 | package ru.cloudpayments.demo.base; 2 | 3 | import android.app.Dialog; 4 | import android.content.Context; 5 | 6 | import ru.cloudpayments.demo.R; 7 | 8 | public class Base3DSDialog extends Dialog { 9 | 10 | public static Base3DSDialog create(Context context) { 11 | final Base3DSDialog dialog = new Base3DSDialog(context, R.style.Theme_CustomDialog); 12 | dialog.setContentView(R.layout.progress_dialog); 13 | return dialog; 14 | } 15 | 16 | public Base3DSDialog(Context context, int theme) { 17 | super(context, theme); 18 | } 19 | 20 | @Override 21 | public void onBackPressed() { 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/ru/cloudpayments/demo/api/models/Post3dsRequestArgs.java: -------------------------------------------------------------------------------- 1 | package ru.cloudpayments.demo.api.models; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | public class Post3dsRequestArgs { 6 | 7 | @SerializedName("transaction_id") 8 | private String transactionId; 9 | 10 | @SerializedName("pa_res") 11 | private String paRes; 12 | 13 | public String getTransactionId() { 14 | return transactionId; 15 | } 16 | 17 | public void setTransactionId(String transactionId) { 18 | this.transactionId = transactionId; 19 | } 20 | 21 | public String getPaRes() { 22 | return paRes; 23 | } 24 | 25 | public void setPaRes(String paRes) { 26 | this.paRes = paRes; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_shopping_cart_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /sdk/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /sdk/src/main/java/ru/cloudpayments/sdk/cp_card/api/models/BinInfoResponse.java: -------------------------------------------------------------------------------- 1 | package ru.cloudpayments.sdk.cp_card.api.models; 2 | 3 | import androidx.annotation.Nullable; 4 | 5 | import com.google.gson.annotations.SerializedName; 6 | 7 | public class BinInfoResponse { 8 | 9 | @Nullable 10 | @SerializedName("Model") 11 | private BinInfo binInfo; 12 | 13 | @SerializedName("Success") 14 | private boolean success; 15 | 16 | @Nullable 17 | public BinInfo getBinInfo() { 18 | return binInfo; 19 | } 20 | 21 | public void setBinInfo(@Nullable BinInfo binInfo) { 22 | this.binInfo = binInfo; 23 | } 24 | 25 | public boolean isSuccess() { 26 | return success; 27 | } 28 | 29 | public void setSuccess(boolean success) { 30 | this.success = success; 31 | } 32 | } 33 | 34 | 35 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | android.enableJetifier=true 13 | android.useAndroidX=true 14 | org.gradle.jvmargs=-Xmx1536m 15 | 16 | # When configured, Gradle will run in incubating parallel mode. 17 | # This option should only be used with decoupled projects. More details, visit 18 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 19 | # org.gradle.parallel=true 20 | -------------------------------------------------------------------------------- /app/src/main/java/ru/cloudpayments/demo/base/BaseViewHolder.java: -------------------------------------------------------------------------------- 1 | package ru.cloudpayments.demo.base; 2 | 3 | import android.content.Context; 4 | import androidx.annotation.LayoutRes; 5 | import androidx.recyclerview.widget.RecyclerView; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | 10 | import butterknife.ButterKnife; 11 | 12 | public class BaseViewHolder extends RecyclerView.ViewHolder { 13 | 14 | public BaseViewHolder(View itemView) { 15 | super(itemView); 16 | ButterKnife.bind(this, itemView); 17 | } 18 | 19 | protected static View generateView(ViewGroup parent, @LayoutRes int layoutId) { 20 | Context context = parent.getContext(); 21 | return LayoutInflater.from(context).inflate(layoutId, parent, false); 22 | } 23 | 24 | protected Context getContext() { 25 | return itemView.getContext(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /CloudPaymentsDemo.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/java/ru/cloudpayments/demo/models/Product.java: -------------------------------------------------------------------------------- 1 | package ru.cloudpayments.demo.models; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | import java.util.List; 6 | 7 | public class Product { 8 | 9 | @SerializedName("id") 10 | private String id; 11 | 12 | @SerializedName("name") 13 | private String name; 14 | 15 | @SerializedName("price") 16 | private String price; 17 | 18 | @SerializedName("images") 19 | private List images; 20 | 21 | public String getId() { 22 | return id; 23 | } 24 | 25 | public String getName() { 26 | return name; 27 | } 28 | 29 | public String getPrice() { 30 | return price; 31 | } 32 | 33 | public String getImageUrl() { 34 | return images.get(0).imageUrl; 35 | } 36 | 37 | public class Image { 38 | 39 | @SerializedName("src") 40 | private String imageUrl; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/pay_with_google_button_no_shadow_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 10 | 13 | 16 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /api/cp_post3ds.php: -------------------------------------------------------------------------------- 1 | $transactionId, 16 | 'PaRes'=>$paRes 17 | ); 18 | 19 | $ch = curl_init(); 20 | curl_setopt($ch, CURLOPT_URL, API_URL . 'post3ds'); 21 | curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); 22 | curl_setopt($ch, CURLOPT_USERPWD, MERCHANT_PUBLIC_ID . ":" . MERCHANT_API_PASS); 23 | curl_setopt($ch, CURLOPT_POST, true); 24 | curl_setopt($ch, CURLOPT_POSTFIELDS, $args); 25 | curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, API_TIMEOUT); 26 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 27 | 28 | $result = curl_exec($ch); 29 | echo $result; 30 | curl_close($ch); 31 | } 32 | ?> 33 | -------------------------------------------------------------------------------- /app/src/main/java/ru/cloudpayments/demo/api/interfaces/PayMethods.java: -------------------------------------------------------------------------------- 1 | package ru.cloudpayments.demo.api.interfaces; 2 | 3 | import io.reactivex.Observable; 4 | import retrofit2.http.Body; 5 | import retrofit2.http.Header; 6 | import retrofit2.http.POST; 7 | import ru.cloudpayments.demo.api.models.PayRequestArgs; 8 | import ru.cloudpayments.demo.api.models.Post3dsRequestArgs; 9 | import ru.cloudpayments.demo.api.models.Transaction; 10 | import ru.cloudpayments.demo.api.response.PayApiResponse; 11 | 12 | public interface PayMethods { 13 | 14 | @POST("cp_charge.php") 15 | Observable> charge(@Header("Content-Type") String contentType, @Body PayRequestArgs args); 16 | 17 | @POST("cp_auth.php") 18 | Observable> auth(@Header("Content-Type") String contentType, @Body PayRequestArgs args); 19 | 20 | @POST("cp_post3ds.php") 21 | Observable> post3ds(@Header("Content-Type") String contentType, @Body Post3dsRequestArgs args); 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/ru/cloudpayments/demo/managers/CartManager.java: -------------------------------------------------------------------------------- 1 | package ru.cloudpayments.demo.managers; 2 | 3 | import java.util.ArrayList; 4 | 5 | import ru.cloudpayments.demo.models.Product; 6 | 7 | public class CartManager { 8 | 9 | private static CartManager instance; 10 | 11 | private ArrayList products; 12 | 13 | private CartManager() { 14 | 15 | clear(); 16 | } 17 | 18 | public static synchronized CartManager getInstance(){ 19 | if (instance == null) { 20 | synchronized (CartManager.class) { 21 | instance = new CartManager(); 22 | } 23 | } 24 | return instance; 25 | } 26 | 27 | public void destroy() { 28 | 29 | products = null; 30 | instance = null; 31 | } 32 | 33 | public void clear() { 34 | 35 | products = new ArrayList<>(); 36 | } 37 | 38 | public ArrayList getProducts() { 39 | return products; 40 | } 41 | 42 | public void setProducts(ArrayList products) { 43 | this.products = products; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/ru/cloudpayments/demo/api/response/PayApiResponse.java: -------------------------------------------------------------------------------- 1 | package ru.cloudpayments.demo.api.response; 2 | 3 | import androidx.annotation.Nullable; 4 | import io.reactivex.Observable; 5 | 6 | import com.google.gson.annotations.SerializedName; 7 | 8 | public class PayApiResponse { 9 | 10 | @SerializedName("Success") 11 | private boolean success; 12 | 13 | @SerializedName("Message") 14 | private String message; 15 | 16 | @Nullable 17 | @SerializedName("Model") 18 | private T data; 19 | 20 | @Nullable 21 | public T getData() { 22 | return data; 23 | } 24 | 25 | public boolean isSuccess() { 26 | if (success == false && data == null) 27 | return false; 28 | else if (success == false && data != null) 29 | return true; 30 | else 31 | return success; 32 | } 33 | 34 | public Observable> handleError() { 35 | if (isSuccess()) { 36 | return Observable.just(this); 37 | } else { 38 | return Observable.error(new PayApiError(message)); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 16dp 21 | 22 | 5dp 23 | 10dp 24 | 30dp 25 | 26 | 300dp 27 | 48sp 28 | 200dp 29 | 30 | 31 | -------------------------------------------------------------------------------- /.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/pay_with_google_button_overlay.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/java/ru/cloudpayments/demo/api/ShopApi.java: -------------------------------------------------------------------------------- 1 | package ru.cloudpayments.demo.api; 2 | 3 | import android.util.Base64; 4 | 5 | import java.io.UnsupportedEncodingException; 6 | import java.util.List; 7 | 8 | import io.reactivex.Observable; 9 | import ru.cloudpayments.demo.models.Product; 10 | import ru.cloudpayments.demo.support.Constants; 11 | 12 | public class ShopApi { 13 | 14 | private static final String CONTENT_TYPE = "application/json"; 15 | 16 | public static Observable> getProducts() { 17 | 18 | ApiMap args = ApiMap 19 | .builder() 20 | .build(); 21 | 22 | return ShopApiFactory.getShopMethods() 23 | .getProducts(CONTENT_TYPE, getShopAuthToken(), args); 24 | } 25 | 26 | private static String getShopAuthToken() { 27 | byte[] data = new byte[0]; 28 | try { 29 | data = (Constants.CONSUMER_KEY + ":" + Constants.CONSUMER_SECRET).getBytes("UTF-8"); 30 | } catch (UnsupportedEncodingException e) { 31 | e.printStackTrace(); 32 | } 33 | return "Basic " + Base64.encodeToString(data, Base64.NO_WRAP); 34 | } 35 | } -------------------------------------------------------------------------------- /sdk/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'com.novoda.bintray-release' 3 | 4 | android { 5 | compileSdkVersion 29 6 | 7 | defaultConfig { 8 | minSdkVersion 15 9 | targetSdkVersion 29 10 | versionCode 8 11 | versionName "1.0.8" 12 | } 13 | 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | implementation fileTree(dir: 'libs', include: ['*.jar']) 24 | 25 | implementation 'androidx.appcompat:appcompat:1.1.0' 26 | 27 | implementation 'org.jsoup:jsoup:1.11.3' 28 | implementation 'com.google.code.gson:gson:2.8.5' 29 | 30 | implementation 'com.android.volley:volley:1.1.1' 31 | } 32 | 33 | publish { 34 | 35 | userOrg = 'cloudpayments' 36 | groupId = 'ru.cloudpayments.android' 37 | repoName = 'sdk' 38 | artifactId = 'sdk' 39 | publishVersion = '1.0.8' 40 | desc = 'CloudPayments SDK for Android' 41 | website = 'https://github.com/cloudpayments/SDK-Android' 42 | } 43 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v21/pay_with_google_button_no_shadow_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 10 | 13 | 14 | 17 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/layout/progress_dialog.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 16 | 17 | 25 | 26 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /api/cp_auth.php: -------------------------------------------------------------------------------- 1 | $amount, 22 | 'Currency'=>$currency, 23 | 'Name'=>$name, 24 | 'IpAddress'=>$ipAddress, 25 | 'CardCryptogramPacket'=>$cardCryptogramPacket, 26 | 'Description'=>$description, 27 | 'AccountId'=>$accountId, 28 | 'JsonData'=>$jsonData 29 | ); 30 | 31 | $ch = curl_init(); 32 | curl_setopt($ch, CURLOPT_URL, API_URL . 'auth'); 33 | curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); 34 | curl_setopt($ch, CURLOPT_USERPWD, MERCHANT_PUBLIC_ID . ":" . MERCHANT_API_PASS); 35 | curl_setopt($ch, CURLOPT_POST, true); 36 | curl_setopt($ch, CURLOPT_POSTFIELDS, $args); 37 | curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, API_TIMEOUT); 38 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 39 | 40 | $result = curl_exec($ch); 41 | echo $result; 42 | curl_close($ch); 43 | } 44 | ?> 45 | -------------------------------------------------------------------------------- /api/cp_charge.php: -------------------------------------------------------------------------------- 1 | $amount, 22 | 'Currency'=>$currency, 23 | 'Name'=>$name, 24 | 'IpAddress'=>$ipAddress, 25 | 'CardCryptogramPacket'=>$cardCryptogramPacket, 26 | 'Description'=>$description, 27 | 'AccountId'=>$accountId, 28 | 'JsonData'=>$jsonData 29 | ); 30 | 31 | $ch = curl_init(); 32 | curl_setopt($ch, CURLOPT_URL, API_URL . 'charge'); 33 | curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); 34 | curl_setopt($ch, CURLOPT_USERPWD, MERCHANT_PUBLIC_ID . ":" . MERCHANT_API_PASS); 35 | curl_setopt($ch, CURLOPT_POST, true); 36 | curl_setopt($ch, CURLOPT_POSTFIELDS, $args); 37 | curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, API_TIMEOUT); 38 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 39 | 40 | $result = curl_exec($ch); 41 | echo $result; 42 | curl_close($ch); 43 | } 44 | ?> -------------------------------------------------------------------------------- /app/src/main/res/drawable/pay_with_google_button_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 23 | 26 | 29 | 32 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /app/src/main/java/ru/cloudpayments/demo/screens/cart/CartAdapter.java: -------------------------------------------------------------------------------- 1 | package ru.cloudpayments.demo.screens.cart; 2 | 3 | import android.view.ViewGroup; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | import ru.cloudpayments.demo.base.BaseAdapter; 9 | import ru.cloudpayments.demo.models.Product; 10 | 11 | public class CartAdapter extends BaseAdapter { 12 | 13 | private List items = new ArrayList<>(); 14 | 15 | private OnClickListener listener; 16 | 17 | public void update(List items) { 18 | this.items = items; 19 | notifyDataSetChanged(); 20 | } 21 | 22 | @Override 23 | public CartHolder onCreateViewHolder(ViewGroup parent, int viewType) { 24 | return CartHolder.create(parent); 25 | } 26 | 27 | @Override 28 | public void onBindViewHolder(CartHolder holder, int position) { 29 | holder.bind(items.get(position)); 30 | 31 | holder.itemView.setOnClickListener(v -> { 32 | if (listener == null) { 33 | return; 34 | } 35 | listener.onProductClick(items.get(position)); 36 | }); 37 | } 38 | 39 | @Override 40 | public long getItemId(int position) { 41 | return 0; 42 | } 43 | 44 | @Override 45 | public int getItemCount() { 46 | return items.size(); 47 | } 48 | 49 | public void setListener(OnClickListener listener) { 50 | this.listener = listener; 51 | } 52 | 53 | interface OnClickListener { 54 | void onProductClick(Product item); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /app/src/main/java/ru/cloudpayments/demo/screens/main/ProductsAdapter.java: -------------------------------------------------------------------------------- 1 | package ru.cloudpayments.demo.screens.main; 2 | 3 | import android.view.ViewGroup; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | import ru.cloudpayments.demo.base.BaseAdapter; 9 | import ru.cloudpayments.demo.models.Product; 10 | 11 | public class ProductsAdapter extends BaseAdapter { 12 | 13 | private List items = new ArrayList<>(); 14 | 15 | private OnClickListener listener; 16 | 17 | public void update(List items) { 18 | this.items = items; 19 | notifyDataSetChanged(); 20 | } 21 | 22 | @Override 23 | public ProductHolder onCreateViewHolder(ViewGroup parent, int viewType) { 24 | return ProductHolder.create(parent); 25 | } 26 | 27 | @Override 28 | public void onBindViewHolder(ProductHolder holder, int position) { 29 | holder.bind(items.get(position)); 30 | 31 | holder.itemView.setOnClickListener(v -> { 32 | if (listener == null) { 33 | return; 34 | } 35 | listener.onProductClick(items.get(position)); 36 | }); 37 | } 38 | 39 | @Override 40 | public long getItemId(int position) { 41 | return 0; 42 | } 43 | 44 | @Override 45 | public int getItemCount() { 46 | return items.size(); 47 | } 48 | 49 | public void setListener(OnClickListener listener) { 50 | this.listener = listener; 51 | } 52 | 53 | interface OnClickListener { 54 | void onProductClick(Product item); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /app/src/main/java/ru/cloudpayments/demo/screens/cart/CartHolder.java: -------------------------------------------------------------------------------- 1 | package ru.cloudpayments.demo.screens.cart; 2 | 3 | import android.content.Context; 4 | import android.view.View; 5 | import android.view.ViewGroup; 6 | import android.widget.ImageView; 7 | import android.widget.TextView; 8 | 9 | import com.bumptech.glide.Glide; 10 | import com.bumptech.glide.load.resource.bitmap.CenterCrop; 11 | import com.bumptech.glide.request.RequestOptions; 12 | 13 | import butterknife.BindView; 14 | import ru.cloudpayments.demo.R; 15 | import ru.cloudpayments.demo.base.BaseViewHolder; 16 | import ru.cloudpayments.demo.models.Product; 17 | 18 | public class CartHolder extends BaseViewHolder { 19 | 20 | @BindView(R.id.image_product) 21 | ImageView imageViewProduct; 22 | 23 | @BindView(R.id.text_name) 24 | TextView textViewName; 25 | 26 | @BindView(R.id.text_price) 27 | TextView textViewPrice; 28 | 29 | public CartHolder(View itemView) { 30 | super(itemView); 31 | } 32 | 33 | public void bind(Product item) { 34 | 35 | Context context = itemView.getContext(); 36 | 37 | textViewName.setText(item.getName()); 38 | textViewPrice.setText(item.getPrice() + " " + context.getString(R.string.main_rub)); 39 | 40 | Glide 41 | .with(context) 42 | .load(item.getImageUrl()) 43 | .apply(RequestOptions.bitmapTransform(new CenterCrop())) 44 | .into(imageViewProduct); 45 | } 46 | 47 | public static CartHolder create(ViewGroup parent) { 48 | return new CartHolder(generateView(parent, R.layout.item_list_cart)); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/ru/cloudpayments/demo/screens/main/ProductHolder.java: -------------------------------------------------------------------------------- 1 | package ru.cloudpayments.demo.screens.main; 2 | 3 | import android.content.Context; 4 | import android.view.View; 5 | import android.view.ViewGroup; 6 | import android.widget.ImageView; 7 | import android.widget.TextView; 8 | 9 | import com.bumptech.glide.Glide; 10 | import com.bumptech.glide.load.resource.bitmap.CenterCrop; 11 | import com.bumptech.glide.request.RequestOptions; 12 | 13 | import butterknife.BindView; 14 | import ru.cloudpayments.demo.R; 15 | import ru.cloudpayments.demo.base.BaseViewHolder; 16 | import ru.cloudpayments.demo.models.Product; 17 | 18 | public class ProductHolder extends BaseViewHolder { 19 | 20 | @BindView(R.id.image_product) 21 | ImageView imageViewProduct; 22 | 23 | @BindView(R.id.text_name) 24 | TextView textViewName; 25 | 26 | @BindView(R.id.text_price) 27 | TextView textViewPrice; 28 | 29 | public ProductHolder(View itemView) { 30 | super(itemView); 31 | } 32 | 33 | public void bind(Product item) { 34 | 35 | Context context = itemView.getContext(); 36 | 37 | textViewName.setText(item.getName()); 38 | textViewPrice.setText(item.getPrice() + " " + context.getString(R.string.main_rub)); 39 | 40 | Glide 41 | .with(context) 42 | .load(item.getImageUrl()) 43 | .apply(RequestOptions.bitmapTransform(new CenterCrop())) 44 | .into(imageViewProduct); 45 | } 46 | 47 | public static ProductHolder create(ViewGroup parent) { 48 | return new ProductHolder(generateView(parent, R.layout.item_list_product)); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/ru/cloudpayments/demo/googlepay/ItemInfo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ru.cloudpayments.demo.googlepay; 18 | 19 | /** 20 | * Used for storing the (hard coded) info about the item we're selling. 21 | *

22 | * This POJO class is used only for example purposes - you don't need need it in your code. 23 | */ 24 | public class ItemInfo { 25 | private final String name; 26 | private final int imageResourceId; 27 | 28 | // Micros are used for prices to avoid rounding errors when converting between currencies. 29 | private final long priceMicros; 30 | 31 | public ItemInfo(String name, long price, int imageResourceId) { 32 | this.name = name; 33 | this.priceMicros = price; 34 | this.imageResourceId = imageResourceId; 35 | } 36 | 37 | public String getName() { 38 | return name; 39 | } 40 | 41 | public int getImageResourceId() { 42 | return imageResourceId; 43 | } 44 | 45 | public long getPriceMicros() { 46 | return priceMicros; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/java/ru/cloudpayments/demo/support/SideSpaceItemDecoration.java: -------------------------------------------------------------------------------- 1 | package ru.cloudpayments.demo.support; 2 | 3 | import android.content.Context; 4 | import android.graphics.Rect; 5 | 6 | import androidx.recyclerview.widget.RecyclerView; 7 | 8 | import android.view.View; 9 | 10 | public class SideSpaceItemDecoration extends RecyclerView.ItemDecoration { 11 | 12 | private float spacingInDP; 13 | private int spanCount; 14 | private boolean includeEdge; 15 | 16 | public SideSpaceItemDecoration(Context context, int spacing, int spanCount, boolean includeEdge) { 17 | 18 | spacingInDP = spacing * context.getResources().getDisplayMetrics().density; 19 | this.spanCount = spanCount; 20 | this.includeEdge = includeEdge; 21 | } 22 | 23 | @Override 24 | public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { 25 | int position = parent.getChildAdapterPosition(view); 26 | int column = position % spanCount; 27 | 28 | if (includeEdge) { 29 | outRect.left = (int) (spacingInDP - column * spacingInDP / spanCount); 30 | outRect.right = (int) ((column + 1) * spacingInDP / spanCount); 31 | 32 | if (position < spanCount) { 33 | outRect.top = (int) spacingInDP; 34 | } 35 | outRect.bottom = (int) spacingInDP; 36 | } else { 37 | outRect.left = (int) (column * spacingInDP / spanCount); 38 | outRect.right = (int) (spacingInDP - (column + 1) * spacingInDP / spanCount); 39 | if (position >= spanCount) { 40 | outRect.top = (int) spacingInDP; 41 | } 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v21/pay_with_google_button_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 20 | 21 | 22 | 26 | 29 | 30 | 33 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /app/src/main/java/ru/cloudpayments/demo/api/models/Transaction.java: -------------------------------------------------------------------------------- 1 | package ru.cloudpayments.demo.api.models; 2 | 3 | import androidx.annotation.Nullable; 4 | 5 | import com.google.gson.annotations.SerializedName; 6 | 7 | public class Transaction { 8 | 9 | @SerializedName("TransactionId") 10 | private String id; 11 | 12 | @Nullable 13 | @SerializedName("ReasonCode") 14 | private int reasonCode; 15 | 16 | @Nullable 17 | @SerializedName("CardHolderMessage") 18 | private String cardHolderMessage; 19 | 20 | // 3DS Begin 21 | @Nullable 22 | @SerializedName("PaReq") 23 | private String paReq; 24 | 25 | @Nullable 26 | @SerializedName("AcsUrl") 27 | private String acsUrl; 28 | // 3DS End 29 | 30 | public String getId() { 31 | return id; 32 | } 33 | 34 | public void setId(String id) { 35 | this.id = id; 36 | } 37 | 38 | @Nullable 39 | public int getReasonCode() { 40 | return reasonCode; 41 | } 42 | 43 | public void setReasonCode(@Nullable int reasonCode) { 44 | this.reasonCode = reasonCode; 45 | } 46 | 47 | @Nullable 48 | public String getCardHolderMessage() { 49 | return cardHolderMessage; 50 | } 51 | 52 | public void setCardHolderMessage(@Nullable String cardHolderMessage) { 53 | this.cardHolderMessage = cardHolderMessage; 54 | } 55 | 56 | @Nullable 57 | public String getPaReq() { 58 | return paReq; 59 | } 60 | 61 | public void setPaReq(@Nullable String paReq) { 62 | this.paReq = paReq; 63 | } 64 | 65 | @Nullable 66 | public String getAcsUrl() { 67 | return acsUrl; 68 | } 69 | 70 | public void setAcsUrl(@Nullable String acsUrl) { 71 | this.acsUrl = acsUrl; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.aar 4 | *.ap_ 5 | *.aab 6 | 7 | # Files for the ART/Dalvik VM 8 | *.dex 9 | 10 | # Java class files 11 | *.class 12 | 13 | # Generated files 14 | bin/ 15 | gen/ 16 | out/ 17 | # Uncomment the following line in case you need and you don't have the release build type files in your app 18 | # release/ 19 | 20 | # Gradle files 21 | .gradle/ 22 | build/ 23 | 24 | # Local configuration file (sdk path, etc) 25 | local.properties 26 | 27 | # Proguard folder generated by Eclipse 28 | proguard/ 29 | 30 | # Log Files 31 | *.log 32 | 33 | # Android Studio Navigation editor temp files 34 | .navigation/ 35 | 36 | # Android Studio captures folder 37 | captures/ 38 | 39 | # IntelliJ 40 | *.iml 41 | .idea/workspace.xml 42 | .idea/tasks.xml 43 | .idea/gradle.xml 44 | .idea/assetWizardSettings.xml 45 | .idea/dictionaries 46 | .idea/libraries 47 | # Android Studio 3 in .gitignore file. 48 | .idea/caches 49 | .idea/modules.xml 50 | # Comment next line if keeping position of elements in Navigation Editor is relevant for you 51 | .idea/navEditor.xml 52 | 53 | # Keystore files 54 | # Uncomment the following lines if you do not want to check your keystore files in. 55 | #*.jks 56 | #*.keystore 57 | 58 | # External native build folder generated in Android Studio 2.2 and later 59 | .externalNativeBuild 60 | .cxx/ 61 | 62 | # Google Services (e.g. APIs or Firebase) 63 | # google-services.json 64 | 65 | # Freeline 66 | freeline.py 67 | freeline/ 68 | freeline_project_description.json 69 | 70 | # fastlane 71 | fastlane/report.xml 72 | fastlane/Preview.html 73 | fastlane/screenshots 74 | fastlane/test_output 75 | fastlane/readme.md 76 | 77 | # Version control 78 | vcs.xml 79 | 80 | # lint 81 | lint/intermediates/ 82 | lint/generated/ 83 | lint/outputs/ 84 | lint/tmp/ 85 | # lint/reports/ 86 | 87 | # Android Profiling 88 | *.hprof 89 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 14 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 30 | 31 | 35 | 36 | 37 | 40 | 41 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/java/ru/cloudpayments/demo/api/ApiMap.java: -------------------------------------------------------------------------------- 1 | package ru.cloudpayments.demo.api; 2 | 3 | import java.io.UnsupportedEncodingException; 4 | import java.net.URLEncoder; 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | public final class ApiMap extends HashMap { 9 | 10 | private static final String TOKEN = "token"; 11 | 12 | private ApiMap() { } 13 | 14 | public static Builder builder() { 15 | return new Builder(); 16 | } 17 | 18 | private static String urlEncodeUTF8(String s) { 19 | try { 20 | return URLEncoder.encode(s, "UTF-8"); 21 | } catch (UnsupportedEncodingException e) { 22 | throw new UnsupportedOperationException(e); 23 | } 24 | } 25 | 26 | private static String urlEncodeUTF8(Map map) { 27 | StringBuilder sb = new StringBuilder(); 28 | for (Entry entry : map.entrySet()) { 29 | if (sb.length() > 0) { 30 | sb.append("&"); 31 | } 32 | sb.append(String.format("%s=%s", 33 | urlEncodeUTF8(entry.getKey().toString()), 34 | urlEncodeUTF8(entry.getValue().toString()) 35 | )); 36 | } 37 | return sb.toString(); 38 | } 39 | 40 | public static class Builder { 41 | 42 | private ApiMap apiMap = new ApiMap(); 43 | 44 | private Builder() { } 45 | 46 | public Builder withSession() { 47 | /*User user = RepositoryProvider.provideUserRepository().getCurrentUser(); 48 | if (user != null) { 49 | String token = user.getToken(); 50 | if (token != null) { 51 | apiMap.put(TOKEN, token); 52 | } 53 | }*/ 54 | 55 | return this; 56 | } 57 | 58 | public ApiMap build() { 59 | return apiMap; 60 | } 61 | 62 | public String buildIntoQuery() { 63 | return urlEncodeUTF8(apiMap); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /app/src/main/res/layout/pay_with_google_button_no_shadow.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 25 | 32 | 39 | 40 | 46 | 47 | -------------------------------------------------------------------------------- /app/src/main/res/layout/pay_with_google_button.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 26 | 33 | 40 | 41 | 47 | 48 | -------------------------------------------------------------------------------- /app/src/main/res/layout/pay_with_google_button_short_no_shadow.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 25 | 32 | 39 | 40 | 46 | 47 | -------------------------------------------------------------------------------- /app/src/main/res/layout/pay_with_google_button_short.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 26 | 33 | 40 | 41 | 47 | 48 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_list_cart.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 17 | 18 | 24 | 25 | 35 | 36 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /app/src/main/java/ru/cloudpayments/demo/api/PayApiFactory.java: -------------------------------------------------------------------------------- 1 | package ru.cloudpayments.demo.api; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.GsonBuilder; 5 | 6 | import java.util.concurrent.TimeUnit; 7 | 8 | import androidx.annotation.NonNull; 9 | import okhttp3.OkHttpClient; 10 | import okhttp3.logging.HttpLoggingInterceptor; 11 | import retrofit2.Retrofit; 12 | import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; 13 | import retrofit2.converter.gson.GsonConverterFactory; 14 | import ru.cloudpayments.demo.api.interfaces.PayMethods; 15 | 16 | public class PayApiFactory { 17 | private static final String HOST = "https://wp-demo.cloudpayments.ru/"; 18 | private static final String API_URL = ""; 19 | 20 | private static final int TIMEOUT = 10; 21 | private static final int WRITE_TIMEOUT = 20; 22 | private static final int CONNECT_TIMEOUT = 10; 23 | private static final HttpLoggingInterceptor LOGGING_INTERCEPTOR = new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY); 24 | 25 | public static final String API_ENDPOINT = HOST + API_URL; 26 | 27 | // API implementations 28 | public static PayMethods getPayMethods() { 29 | return getRetrofit().create(PayMethods.class); 30 | } 31 | // API implementations 32 | 33 | private static final OkHttpClient CLIENT = new OkHttpClient.Builder() 34 | .connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS) 35 | .writeTimeout(WRITE_TIMEOUT, TimeUnit.SECONDS) 36 | .readTimeout(TIMEOUT, TimeUnit.SECONDS) 37 | .addInterceptor(LOGGING_INTERCEPTOR) 38 | .build(); 39 | 40 | private static final Gson GSON = new GsonBuilder() 41 | .setLenient() 42 | .create(); 43 | 44 | @NonNull 45 | private static Retrofit getRetrofit() { 46 | return new Retrofit.Builder() 47 | .baseUrl(API_ENDPOINT) 48 | .addConverterFactory(GsonConverterFactory.create(GSON)) 49 | .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) 50 | .client(CLIENT) 51 | .build(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | 16 | 17 | 24 | 25 | 32 | 33 | 39 | 40 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /app/src/main/java/ru/cloudpayments/demo/api/ShopApiFactory.java: -------------------------------------------------------------------------------- 1 | package ru.cloudpayments.demo.api; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.GsonBuilder; 5 | 6 | import androidx.annotation.NonNull; 7 | 8 | import java.util.concurrent.TimeUnit; 9 | 10 | import okhttp3.OkHttpClient; 11 | import okhttp3.logging.HttpLoggingInterceptor; 12 | import retrofit2.Retrofit; 13 | import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; 14 | import retrofit2.converter.gson.GsonConverterFactory; 15 | import ru.cloudpayments.demo.api.interfaces.ShopMethods; 16 | 17 | public class ShopApiFactory { 18 | private static final String HOST = "https://wp-demo.cloudpayments.ru/index.php/wp-json/"; 19 | private static final String API_URL = "wc/v3/"; 20 | 21 | private static final int TIMEOUT = 10; 22 | private static final int WRITE_TIMEOUT = 20; 23 | private static final int CONNECT_TIMEOUT = 10; 24 | private static final HttpLoggingInterceptor LOGGING_INTERCEPTOR = new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY); 25 | 26 | public static final String API_ENDPOINT = HOST + API_URL; 27 | 28 | // API implementations 29 | public static ShopMethods getShopMethods() { 30 | return getRetrofit().create(ShopMethods.class); 31 | } 32 | // API implementations 33 | 34 | private static final OkHttpClient CLIENT = new OkHttpClient.Builder() 35 | .connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS) 36 | .writeTimeout(WRITE_TIMEOUT, TimeUnit.SECONDS) 37 | .readTimeout(TIMEOUT, TimeUnit.SECONDS) 38 | .addInterceptor(LOGGING_INTERCEPTOR) 39 | .build(); 40 | 41 | private static final Gson GSON = new GsonBuilder() 42 | .setLenient() 43 | .create(); 44 | 45 | @NonNull 46 | private static Retrofit getRetrofit() { 47 | return new Retrofit.Builder() 48 | .baseUrl(API_ENDPOINT) 49 | .addConverterFactory(GsonConverterFactory.create(GSON)) 50 | .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) 51 | .client(CLIENT) 52 | .build(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | 5 | compileSdkVersion 29 6 | defaultConfig { 7 | applicationId "ru.cloudpayments.demo" 8 | minSdkVersion 19 9 | targetSdkVersion 29 10 | versionCode 1 11 | versionName "1.0" 12 | } 13 | 14 | configurations { 15 | all*.exclude group: 'com.android.support', module: 'support-v13' 16 | } 17 | 18 | buildTypes { 19 | release { 20 | minifyEnabled false 21 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 22 | } 23 | } 24 | 25 | compileOptions { 26 | targetCompatibility 1.8 27 | sourceCompatibility 1.8 28 | } 29 | 30 | lintOptions { 31 | checkReleaseBuilds false 32 | abortOnError false 33 | } 34 | 35 | useLibrary 'org.apache.http.legacy' 36 | } 37 | 38 | dependencies { 39 | 40 | implementation 'androidx.appcompat:appcompat:1.1.0' 41 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3' 42 | implementation 'com.google.android.material:material:1.1.0' 43 | implementation 'androidx.cardview:cardview:1.0.0' 44 | 45 | // gPay 46 | implementation 'com.google.android.gms:play-services-wallet:18.0.0' 47 | 48 | // CloudPayments SDK 49 | implementation 'ru.cloudpayments.android:sdk:1.0.8' 50 | //implementation project(path: ':sdk') 51 | 52 | // views binding 53 | implementation 'com.jakewharton:butterknife:10.1.0' 54 | annotationProcessor 'com.jakewharton:butterknife-compiler:10.1.0' 55 | 56 | // material dialogs 57 | implementation 'com.afollestad.material-dialogs:core:0.9.6.0' 58 | 59 | // rx 60 | implementation 'io.reactivex.rxjava2:rxjava:2.2.9' 61 | implementation 'io.reactivex.rxjava2:rxandroid:2.1.1' 62 | 63 | // http 64 | implementation 'com.squareup.retrofit2:retrofit:2.5.0' 65 | implementation 'com.squareup.retrofit2:converter-gson:2.5.0' 66 | implementation 'com.squareup.retrofit2:adapter-rxjava2:2.5.0' 67 | implementation 'com.squareup.okhttp3:okhttp:3.14.1' 68 | implementation 'com.squareup.okhttp3:logging-interceptor:3.14.1' 69 | 70 | // event bus 71 | implementation 'org.greenrobot:eventbus:3.1.1' 72 | 73 | // image loading and caching 74 | implementation 'com.github.bumptech.glide:glide:4.9.0' 75 | } -------------------------------------------------------------------------------- /app/src/main/res/layout/item_list_product.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 17 | 18 | 25 | 26 | 35 | 36 | 44 | 45 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /sdk/src/main/java/ru/cloudpayments/sdk/cp_card/CPCardType.java: -------------------------------------------------------------------------------- 1 | package ru.cloudpayments.sdk.cp_card; 2 | 3 | public class CPCardType { 4 | 5 | public final static int UNKNOWN = -1; 6 | public final static int VISA = 0; 7 | public final static int MASTER_CARD = 1; 8 | public final static int MAESTRO = 2; 9 | public final static int MIR = 3; 10 | public final static int JCB = 4; 11 | 12 | public static String toString(int value) { 13 | switch (value) { 14 | case VISA: 15 | return "Visa"; 16 | case MASTER_CARD: 17 | return "MasterCard"; 18 | case MAESTRO: 19 | return "Maestro"; 20 | case MIR: 21 | return "MIR"; 22 | case JCB: 23 | return "JCB"; 24 | default: 25 | return "Unknown"; 26 | } 27 | } 28 | 29 | public static int fromString(String value) { 30 | if ("visa".equals(value.toLowerCase())) { 31 | return VISA; 32 | } else if ("mastercard".equals(value.toLowerCase())) { 33 | return MASTER_CARD; 34 | } else if ("maestro".equals(value.toLowerCase())) { 35 | return MAESTRO; 36 | } else if ("mir".equals(value.toLowerCase())) { 37 | return MIR; 38 | } else if ("jcb".equals(value.toLowerCase())) { 39 | return JCB; 40 | } else { 41 | return UNKNOWN; 42 | } 43 | } 44 | 45 | public static int getType(String creditCardNumberPart) { 46 | 47 | if (creditCardNumberPart == null || creditCardNumberPart.isEmpty()) 48 | return UNKNOWN; 49 | 50 | int first = Integer.valueOf(creditCardNumberPart.substring(0, 1)); 51 | 52 | if (first == 4) 53 | return VISA; 54 | 55 | if (first == 6) 56 | return MAESTRO; 57 | 58 | if (creditCardNumberPart.length() < 2) 59 | return UNKNOWN; 60 | 61 | int firstTwo = Integer.valueOf(creditCardNumberPart.substring(0, 2)); 62 | 63 | if (firstTwo == 35) 64 | return JCB; 65 | 66 | if (firstTwo == 50 || (firstTwo >= 56 && firstTwo <= 58)) 67 | return MAESTRO; 68 | 69 | if (firstTwo >= 51 && firstTwo <= 55) 70 | return MASTER_CARD; 71 | 72 | if (creditCardNumberPart.length() < 4) 73 | return UNKNOWN; 74 | 75 | int firstFour = Integer.valueOf(creditCardNumberPart.substring(0, 4)); 76 | 77 | if (firstFour >= 2200 && firstFour <= 2204) 78 | return MIR; 79 | 80 | if (firstFour >= 2221 && firstFour <= 2720) 81 | return MASTER_CARD; 82 | 83 | return UNKNOWN; 84 | } 85 | } -------------------------------------------------------------------------------- /app/src/main/java/ru/cloudpayments/demo/api/models/PayRequestArgs.java: -------------------------------------------------------------------------------- 1 | package ru.cloudpayments.demo.api.models; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | public class PayRequestArgs { 6 | 7 | @SerializedName("amount") 8 | private String amount; // Сумма платежа (Обязательный) 9 | 10 | @SerializedName("currency") 11 | private String currency; // Валюта (Обязательный) 12 | 13 | @SerializedName("name") 14 | private String name; // Имя держателя карты в латинице (Обязательный для всех платежей кроме Apple Pay и Google Pay) 15 | 16 | @SerializedName("card_cryptogram_packet") 17 | private String cardCryptogramPacket; // Криптограмма платежных данных (Обязательный) 18 | 19 | @SerializedName("invoice_id") 20 | private String invoiceId; // Номер счета или заказа в вашей системе (необязательный) 21 | 22 | @SerializedName("description") 23 | private String description; // Описание оплаты в свободной форме (необязательный) 24 | 25 | @SerializedName("account_id") 26 | private String accountId; // Идентификатор пользователя в вашей системе (необязательный) 27 | 28 | @SerializedName("json_data") 29 | private String jsonData; // Любые другие данные, которые будут связаны с транзакцией (необязательный) 30 | 31 | public String getAmount() { 32 | return amount; 33 | } 34 | 35 | public void setAmount(String amount) { 36 | this.amount = amount; 37 | } 38 | 39 | public String getCurrency() { 40 | return currency; 41 | } 42 | 43 | public void setCurrency(String currency) { 44 | this.currency = currency; 45 | } 46 | 47 | public String getName() { 48 | return name; 49 | } 50 | 51 | public void setName(String name) { 52 | this.name = name; 53 | } 54 | 55 | public String getCardCryptogramPacket() { 56 | return cardCryptogramPacket; 57 | } 58 | 59 | public void setCardCryptogramPacket(String cardCryptogramPacket) { 60 | this.cardCryptogramPacket = cardCryptogramPacket; 61 | } 62 | 63 | public String getInvoiceId() { 64 | return invoiceId; 65 | } 66 | 67 | public void setInvoiceId(String invoiceId) { 68 | this.invoiceId = invoiceId; 69 | } 70 | 71 | public String getDescription() { 72 | return description; 73 | } 74 | 75 | public void setDescription(String description) { 76 | this.description = description; 77 | } 78 | 79 | public String getAccountId() { 80 | return accountId; 81 | } 82 | 83 | public void setAccountId(String accountId) { 84 | this.accountId = accountId; 85 | } 86 | 87 | public String getJsonData() { 88 | return jsonData; 89 | } 90 | 91 | public void setJsonData(String jsonData) { 92 | this.jsonData = jsonData; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /sdk/src/main/java/ru/cloudpayments/sdk/cp_card/api/CPCardApi.java: -------------------------------------------------------------------------------- 1 | package ru.cloudpayments.sdk.cp_card.api; 2 | 3 | import android.content.Context; 4 | 5 | import com.android.volley.Request; 6 | import com.android.volley.RequestQueue; 7 | import com.android.volley.Response; 8 | import com.android.volley.VolleyError; 9 | import com.android.volley.toolbox.StringRequest; 10 | import com.android.volley.toolbox.Volley; 11 | import com.google.gson.Gson; 12 | import com.google.gson.GsonBuilder; 13 | 14 | import ru.cloudpayments.sdk.cp_card.api.models.BinInfo; 15 | import ru.cloudpayments.sdk.cp_card.api.models.BinInfoResponse; 16 | 17 | public class CPCardApi { 18 | 19 | public interface CompleteBinInfoListener { 20 | 21 | void onCompleted(final BinInfo binInfo); 22 | } 23 | 24 | public interface ErrorListener { 25 | 26 | void onError(final String message); 27 | } 28 | 29 | private final Context context; 30 | private final Gson gson; 31 | 32 | public CPCardApi(Context context) { 33 | this.context = context; 34 | this.gson = createGson(); 35 | } 36 | 37 | private Gson createGson() { 38 | return new GsonBuilder() 39 | .setLenient() 40 | .create(); 41 | } 42 | 43 | public void getBinInfo(String firstSixDigits, final CompleteBinInfoListener completeListener, final ErrorListener errorListener) { 44 | 45 | firstSixDigits = firstSixDigits.replace(" ", ""); 46 | 47 | if (firstSixDigits.length() < 6) { 48 | errorListener.onError("You must specify the first 6 digits of the card number"); 49 | return; 50 | } 51 | 52 | firstSixDigits = firstSixDigits.substring(0, 6); 53 | 54 | RequestQueue queue = Volley.newRequestQueue(context); 55 | String url ="https://api.cloudpayments.ru/bins/info/" + firstSixDigits; 56 | 57 | StringRequest stringRequest = new StringRequest(Request.Method.GET, url, 58 | new Response.Listener() { 59 | @Override 60 | public void onResponse(String response) { 61 | 62 | BinInfoResponse binInfoResponse = gson.fromJson(response, BinInfoResponse.class); 63 | 64 | if (binInfoResponse.isSuccess() && binInfoResponse.getBinInfo() != null) { 65 | completeListener.onCompleted(binInfoResponse.getBinInfo()); 66 | } else { 67 | errorListener.onError("Unable to determine bank"); 68 | } 69 | 70 | } 71 | }, new Response.ErrorListener() { 72 | @Override 73 | public void onErrorResponse(VolleyError error) { 74 | errorListener.onError(error.getMessage()); 75 | } 76 | }); 77 | 78 | queue.add(stringRequest); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /app/src/main/java/ru/cloudpayments/demo/screens/cart/CartActivity.java: -------------------------------------------------------------------------------- 1 | package ru.cloudpayments.demo.screens.cart; 2 | 3 | import android.content.Intent; 4 | import android.net.Uri; 5 | import android.os.Bundle; 6 | import androidx.recyclerview.widget.GridLayoutManager; 7 | import android.widget.TextView; 8 | 9 | import butterknife.BindView; 10 | import butterknife.OnClick; 11 | import ru.cloudpayments.demo.R; 12 | import ru.cloudpayments.demo.base.BaseListActivity; 13 | import ru.cloudpayments.demo.managers.CartManager; 14 | import ru.cloudpayments.demo.models.Product; 15 | import ru.cloudpayments.demo.screens.checkout.CheckoutActivity; 16 | import ru.cloudpayments.demo.support.SideSpaceItemDecoration; 17 | 18 | public class CartActivity extends BaseListActivity implements CartAdapter.OnClickListener { 19 | 20 | @BindView(R.id.text_total) 21 | TextView textViewTotal; 22 | 23 | @Override 24 | protected int getLayoutId() { 25 | return R.layout.activity_cart; 26 | } 27 | 28 | @Override 29 | protected void onCreate(Bundle savedInstanceState) { 30 | setTheme(R.style.AppTheme); 31 | super.onCreate(savedInstanceState); 32 | 33 | setTitle(R.string.cart_title); 34 | 35 | initList(); 36 | initTotal(); 37 | } 38 | 39 | private void initList() { 40 | GridLayoutManager layoutManager = new GridLayoutManager(this, 1); 41 | 42 | recyclerView.addItemDecoration(new SideSpaceItemDecoration(this, 16,1, true)); 43 | 44 | adapter = new CartAdapter(); 45 | adapter.setHasStableIds(true); 46 | adapter.setListener(this); 47 | 48 | recyclerView.setLayoutManager(layoutManager); 49 | recyclerView.setAdapter(adapter); 50 | 51 | adapter.update(CartManager.getInstance().getProducts()); 52 | } 53 | 54 | private void initTotal() { 55 | 56 | int total = 0; 57 | 58 | for (Product product : CartManager.getInstance().getProducts()) { 59 | total += Integer.parseInt(product.getPrice()); 60 | } 61 | 62 | textViewTotal.setText(getString(R.string.cart_total) + " " + total + " " + getString(R.string.main_rub)); 63 | } 64 | 65 | @OnClick(R.id.text_phone) 66 | void onPhoneClick() { 67 | String phone = getString(R.string.main_phone); 68 | Intent intent = new Intent(Intent.ACTION_DIAL); 69 | intent.setData(Uri.parse("tel:" + phone)); 70 | startActivity(intent); 71 | } 72 | 73 | @OnClick(R.id.text_email) 74 | void onEmailClick() { 75 | String email = getString(R.string.main_email); 76 | Intent emailIntent = new Intent(Intent.ACTION_SENDTO, Uri.parse("mailto:" + email)); 77 | startActivity(Intent.createChooser(emailIntent, getString(R.string.main_select_app))); 78 | } 79 | 80 | @Override 81 | public void onProductClick(Product item) { 82 | 83 | } 84 | 85 | @OnClick(R.id.button_go_to_payment) 86 | void onGoToPaymentClick() { 87 | startActivity(new Intent(this, CheckoutActivity.class)); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 25 | 26 | 35 | 36 | 44 | 45 | 56 | 57 | 64 | 65 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /app/src/main/java/ru/cloudpayments/demo/api/PayApi.java: -------------------------------------------------------------------------------- 1 | package ru.cloudpayments.demo.api; 2 | 3 | import io.reactivex.Observable; 4 | import ru.cloudpayments.demo.api.models.PayRequestArgs; 5 | import ru.cloudpayments.demo.api.models.Post3dsRequestArgs; 6 | import ru.cloudpayments.demo.api.models.Transaction; 7 | import ru.cloudpayments.demo.api.response.PayApiResponse; 8 | 9 | public class PayApi { 10 | 11 | private static final String CONTENT_TYPE = "application/json"; 12 | 13 | public static Observable charge(String cardCryptogramPacket, String cardHolderName, int amount) { 14 | 15 | // Параметры: 16 | PayRequestArgs args = new PayRequestArgs(); 17 | args.setAmount(Integer.toString(amount)); // Сумма платежа (Обязательный) 18 | args.setCurrency("RUB"); // Валюта (Обязательный) 19 | args.setName(cardHolderName); // Имя держателя карты в латинице (Обязательный для всех платежей кроме Apple Pay и Google Pay) 20 | args.setCardCryptogramPacket(cardCryptogramPacket); // Криптограмма платежных данных (Обязательный) 21 | args.setInvoiceId("1122"); // Номер счета или заказа в вашей системе (необязательный) 22 | args.setDescription("Оплата цветов"); // Описание оплаты в свободной форме (необязательный) 23 | args.setAccountId("123"); // Идентификатор пользователя в вашей системе (необязательный) 24 | args.setJsonData("{\"age\":27,\"name\":\"Ivan\",\"phone\":\"+79998881122\"}"); // Любые другие данные, которые будут связаны с транзакцией (необязательный) 25 | 26 | return PayApiFactory.getPayMethods() 27 | .charge(CONTENT_TYPE, args) 28 | .flatMap(PayApiResponse::handleError) 29 | .map(PayApiResponse::getData); 30 | } 31 | 32 | public static Observable auth(String cardCryptogramPacket, String cardHolderName, int amount) { 33 | 34 | // Параметры: 35 | PayRequestArgs args = new PayRequestArgs(); 36 | args.setAmount(Integer.toString(amount)); // Сумма платежа (Обязательный) 37 | args.setCurrency("RUB"); // Валюта (Обязательный) 38 | args.setName(cardHolderName); // Имя держателя карты в латинице (Обязательный для всех платежей кроме Apple Pay и Google Pay) 39 | args.setCardCryptogramPacket(cardCryptogramPacket); // Криптограмма платежных данных (Обязательный) 40 | args.setInvoiceId("1122"); // Номер счета или заказа в вашей системе (необязательный) 41 | args.setDescription("Оплата цветов"); // Описание оплаты в свободной форме (необязательный) 42 | args.setAccountId("123"); // Идентификатор пользователя в вашей системе (необязательный) 43 | args.setJsonData("{\"age\":27,\"name\":\"Ivan\",\"phone\":\"+79998881122\"}"); // Любые другие данные, которые будут связаны с транзакцией (необязательный) 44 | 45 | return PayApiFactory.getPayMethods() 46 | .auth(CONTENT_TYPE, args) 47 | .flatMap(PayApiResponse::handleError) 48 | .map(PayApiResponse::getData); 49 | } 50 | 51 | public static Observable post3ds(String transactionId, String paRes) { 52 | 53 | Post3dsRequestArgs args = new Post3dsRequestArgs(); 54 | args.setTransactionId(transactionId); 55 | args.setPaRes(paRes); 56 | 57 | return PayApiFactory.getPayMethods() 58 | .post3ds(CONTENT_TYPE, args) 59 | .flatMap(PayApiResponse::handleError) 60 | .map(PayApiResponse::getData); 61 | } 62 | } -------------------------------------------------------------------------------- /app/src/main/java/ru/cloudpayments/demo/googlepay/ConstantsGPay.java: -------------------------------------------------------------------------------- 1 | package ru.cloudpayments.demo.googlepay; 2 | 3 | import android.util.Pair; 4 | 5 | import com.google.android.gms.wallet.WalletConstants; 6 | 7 | import java.util.Arrays; 8 | import java.util.List; 9 | 10 | import ru.cloudpayments.demo.support.Constants; 11 | 12 | public class ConstantsGPay { 13 | // This file contains several constants you must edit before proceeding. Once you're done, 14 | // remove this static block and run the sample. 15 | // Before you start, please take a look at PaymentsUtil.java to see where the constants are used 16 | // and to potentially remove ones not relevant to your integration. 17 | // Required changes: 18 | // 1. Update SUPPORTED_NETWORKS and SUPPORTED_METHODS if required (consult your processor if 19 | // unsure). 20 | // 2. Update CURRENCY_CODE to the currency you use. 21 | // 3. Update SHIPPING_SUPPORTED_COUNTRIES to list the countries where you currently ship. If 22 | // this is not applicable to your app, remove the relevant bits from PaymentsUtil.java. 23 | // 4. If you're integrating with your processor / gateway directly, update 24 | // GATEWAY_TOKENIZATION_NAME and GATEWAY_TOKENIZATION_PARAMETERS per the instructions they 25 | // provided. You don't need to update DIRECT_TOKENIZATION_PUBLIC_KEY. 26 | // 5. If you're using direct integration, please consult the documentation to learn about 27 | // next steps. 28 | 29 | // Changing this to ENVIRONMENT_PRODUCTION will make the API return real card information. 30 | // Please refer to the documentation to read about the required steps needed to enable 31 | // ENVIRONMENT_PRODUCTION. 32 | public static final int PAYMENTS_ENVIRONMENT = WalletConstants.ENVIRONMENT_TEST; 33 | 34 | // The allowed networks to be requested from the API. If the user has cards from networks not 35 | // specified here in their account, these will not be offered for them to choose in the popup. 36 | public static final List SUPPORTED_NETWORKS = Arrays.asList( 37 | WalletConstants.CARD_NETWORK_VISA, 38 | WalletConstants.CARD_NETWORK_MASTERCARD 39 | ); 40 | 41 | public static final List SUPPORTED_METHODS = Arrays.asList( 42 | // PAYMENT_METHOD_CARD returns to any card the user has stored in their Google Account. 43 | WalletConstants.PAYMENT_METHOD_CARD, 44 | 45 | // PAYMENT_METHOD_TOKENIZED_CARD refers to cards added to Android Pay, assuming Android 46 | // Pay is installed. 47 | // Please keep in mind cards may exist in Android Pay without being added to the Google 48 | // Account. 49 | WalletConstants.PAYMENT_METHOD_TOKENIZED_CARD 50 | ); 51 | 52 | // Required by the API, but not visible to the user. 53 | public static final String CURRENCY_CODE = "RUB"; 54 | 55 | // The name of your payment processor / gateway. Please refer to their documentation for 56 | // more information. 57 | public static final String GATEWAY_TOKENIZATION_NAME = "cloudpayments"; 58 | 59 | // Custom parameters required by the processor / gateway. 60 | // In many cases, your processor / gateway will only require a gatewayMerchantId. 61 | // Please refer to your processor's documentation for more information. The number of parameters 62 | // required and their names vary depending on the processor. 63 | public static final List> GATEWAY_TOKENIZATION_PARAMETERS = Arrays.asList( 64 | Pair.create("gatewayMerchantId", Constants.MERCHANT_PUBLIC_ID) 65 | ); 66 | 67 | private ConstantsGPay() { 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /app/src/main/java/ru/cloudpayments/demo/screens/main/MainActivity.java: -------------------------------------------------------------------------------- 1 | package ru.cloudpayments.demo.screens.main; 2 | 3 | import android.content.Intent; 4 | import android.net.Uri; 5 | import android.os.Bundle; 6 | import android.view.Menu; 7 | import android.view.MenuItem; 8 | 9 | import androidx.recyclerview.widget.GridLayoutManager; 10 | 11 | import butterknife.OnClick; 12 | import io.reactivex.android.schedulers.AndroidSchedulers; 13 | import io.reactivex.schedulers.Schedulers; 14 | import ru.cloudpayments.demo.R; 15 | import ru.cloudpayments.demo.api.ShopApi; 16 | import ru.cloudpayments.demo.base.BaseListActivity; 17 | import ru.cloudpayments.demo.managers.CartManager; 18 | import ru.cloudpayments.demo.models.Product; 19 | import ru.cloudpayments.demo.screens.cart.CartActivity; 20 | import ru.cloudpayments.demo.support.SideSpaceItemDecoration; 21 | 22 | public class MainActivity extends BaseListActivity implements ProductsAdapter.OnClickListener { 23 | 24 | @Override 25 | protected int getLayoutId() { 26 | return R.layout.activity_main; 27 | } 28 | 29 | @Override 30 | protected void onCreate(Bundle savedInstanceState) { 31 | setTheme(R.style.AppTheme); 32 | super.onCreate(savedInstanceState); 33 | 34 | getSupportActionBar().setDisplayHomeAsUpEnabled(false); 35 | 36 | setTitle(R.string.main_title); 37 | 38 | initList(); 39 | 40 | getProducts(); 41 | } 42 | 43 | private void initList() { 44 | GridLayoutManager layoutManager = new GridLayoutManager(this, 2); 45 | 46 | recyclerView.addItemDecoration(new SideSpaceItemDecoration(this, 16,2, true)); 47 | 48 | adapter = new ProductsAdapter(); 49 | adapter.setHasStableIds(true); 50 | adapter.setListener(this); 51 | 52 | recyclerView.setLayoutManager(layoutManager); 53 | recyclerView.setAdapter(adapter); 54 | } 55 | 56 | @OnClick(R.id.text_phone) 57 | void onPhoneClick() { 58 | String phone = getString(R.string.main_phone); 59 | Intent intent = new Intent(Intent.ACTION_DIAL); 60 | intent.setData(Uri.parse("tel:" + phone)); 61 | startActivity(intent); 62 | } 63 | 64 | @OnClick(R.id.text_email) 65 | void onEmailClick() { 66 | String email = getString(R.string.main_email); 67 | Intent emailIntent = new Intent(Intent.ACTION_SENDTO, Uri.parse("mailto:" + email)); 68 | startActivity(Intent.createChooser(emailIntent, getString(R.string.main_select_app))); 69 | } 70 | 71 | @Override 72 | public boolean onCreateOptionsMenu(Menu menu) { 73 | getMenuInflater().inflate(R.menu.main, menu); 74 | return super.onCreateOptionsMenu(menu); 75 | } 76 | 77 | @Override 78 | public boolean onOptionsItemSelected(MenuItem item) { 79 | switch (item.getItemId()) { 80 | case R.id.action_cart: { 81 | if (CartManager.getInstance().getProducts().isEmpty()) { 82 | showToast(R.string.main_cart_is_empty); 83 | } else { 84 | startActivity(new Intent(this, CartActivity.class)); 85 | } 86 | } 87 | } 88 | 89 | return super.onOptionsItemSelected(item); 90 | } 91 | 92 | @Override 93 | public void onProductClick(Product item) { 94 | CartManager.getInstance().getProducts().add(item); 95 | showToast(R.string.main_product_added_to_cart); 96 | } 97 | 98 | private void getProducts() { 99 | compositeDisposable.add(ShopApi 100 | .getProducts() 101 | .subscribeOn(Schedulers.io()) 102 | .observeOn(AndroidSchedulers.mainThread()) 103 | .doOnSubscribe(disposable -> showLoading()) 104 | .doOnEach(notification -> hideLoading()) 105 | .subscribe(products -> { 106 | adapter.update(products); 107 | }, this::handleError)); 108 | } 109 | 110 | 111 | } 112 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/pay_with_google_button_short_content.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 23 | 28 | 33 | 38 | 43 | 48 | 49 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_cart.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 22 | 23 | 33 | 34 | 46 | 47 |