├── .DS_Store ├── .github └── ISSUE_TEMPLATE │ └── bug_report.md ├── .gitignore ├── README _JAVA.md ├── README.md ├── Sample ├── app │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src │ │ ├── androidTest │ │ └── java │ │ │ └── com │ │ │ └── zarinpal │ │ │ └── sample │ │ │ └── inappbilling │ │ │ └── ExampleInstrumentedTest.kt │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ │ └── com │ │ │ │ └── zarinpal │ │ │ │ └── sample │ │ │ │ └── inappbilling │ │ │ │ └── MainActivity.kt │ │ └── res │ │ │ ├── drawable-v24 │ │ │ └── ic_launcher_foreground.xml │ │ │ ├── drawable │ │ │ └── ic_launcher_background.xml │ │ │ ├── layout │ │ │ └── activity_main.xml │ │ │ ├── mipmap-anydpi-v26 │ │ │ ├── ic_launcher.xml │ │ │ └── ic_launcher_round.xml │ │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.webp │ │ │ └── ic_launcher_round.webp │ │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.webp │ │ │ └── ic_launcher_round.webp │ │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.webp │ │ │ └── ic_launcher_round.webp │ │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.webp │ │ │ └── ic_launcher_round.webp │ │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.webp │ │ │ └── ic_launcher_round.webp │ │ │ ├── values-night │ │ │ └── themes.xml │ │ │ └── values │ │ │ ├── colors.xml │ │ │ ├── strings.xml │ │ │ └── themes.xml │ │ └── test │ │ └── java │ │ └── com │ │ └── zarinpal │ │ └── sample │ │ └── inappbilling │ │ └── ExampleUnitTest.kt ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle └── new_logo.svg /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZarinPal/Android-SDK/cbe60546b927180e9fcbb131a5b0923624d6c2dd/.DS_Store -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: ImanX 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **Information** 14 | - Android OS Version: 15 | - Library Version: 16 | 17 | **Additional context** 18 | Add any other context about the problem here. 19 | 20 | **Your Suggestion for fixing 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | local.properties 16 | -------------------------------------------------------------------------------- /README _JAVA.md: -------------------------------------------------------------------------------- 1 | ZarinPal In App Billing - Purchase SDK | MPG 2 | ============================================ 3 | ZarinPal Purchase SDK Provides payment methods on your Android Application. 4 | 5 | 6 | 7 | Introduction 8 | ============= 9 | ZarinPal in-app purchases are the simplest solution to selling digital products or content on Android apps. So many app developers who want to sell digital goods or offer premium membership to users can simply use the it, in-app billing process for smooth and easy checkouts. 10 | 11 | 12 |

13 | sample 14 |

15 | 16 | 17 | Requirements 18 | ============ 19 | 20 | * Android 5.0 (API level 21) and above 21 | * Android Gradle Plugin 3.5.1 22 | * Gradle 5.4.1+ 23 | * AndroidX (as of v11.0.0) 24 | 25 | Installation 26 | ============ 27 | 28 | **Step 1** 29 | 30 | Add this to your root build.gradle at the end of repositories. 31 | ```gradle 32 | allprojects { 33 | ext.zarinpalSdkVersion = (LATEST_VERSION_REALEASE) //inform of Releases: https://github.com/ZarinPal/Android-SDK/releases 34 | repositories { 35 | ... 36 | mavenCentral() 37 | } 38 | ``` 39 | 40 | **Step 2** 41 | 42 | Add the dependency: 43 | ```gradle 44 | dependencies { 45 | implementation 'com.zarinpal:payment-provider:ext.zarinpalSdkVersion' 46 | } 47 | ``` 48 | 49 | 50 | If your project and business trusted to ZarinPal, SDK ables to providing **Mobile Payment Gateway** on your App so You should add the **MPG** dependency: 51 | ```gradle 52 | dependencies { 53 | implementation 'com.zarinpal:payment-provider:ext.zarinpalSdkVersion' 54 | implementation 'com.zarinpal:mpg:ext.zarinpalSdkVersion' 55 | } 56 | ``` 57 | 58 | How to use 59 | ========== 60 | 61 | * add Permissions in your `Manifest.xml`: 62 | ```xml 63 | 64 | 65 | ``` 66 | 67 | Initialize the billing client 68 | ============================= 69 | 70 | **Step 1** 71 | 72 | * `ZarinPalClientBilling` provides to create the billing client instance: 73 | ```java 74 | 75 | BillingClientStateListener listener = new BillingClientStateListener() { 76 | @Override 77 | public void onClientSetupFinished(@NotNull ClientState state) { 78 | //Observing client states 79 | 80 | } 81 | 82 | @Override 83 | public void onClientServiceDisconnected() { 84 | Log.v("TAG_INAPP","Billing client Disconnected"); 85 | //When Service disconnect 86 | } 87 | }; 88 | 89 | ZarinPalBillingClient client = ZarinPalBillingClient.newBuilder(this) 90 | .enableShowInvoice() 91 | .setListener(listener) 92 | .setNightMode(AppCompatDelegate.MODE_NIGHT_YES) 93 | .build(); 94 | 95 | 96 | ``` 97 | 98 | **Step 2** 99 | 100 | For start purchase you need a `Purchase` instance, `Purchase` has 3 type of Payment: 101 | 102 | * as **Payment Request** by `asPaymentRequest()` 103 | * as **Authority ID** by `asAuthority()` 104 | * as **Sku ID** by `asSku()` 105 | 106 | If you would create payment Authority on Client, You must use `asPayementRequest()`, this method needs below parameters: 107 | 108 | **Require Parameters:** 109 | 110 | * Merchant id: An unique ID of your business payment gateway. 111 | * Amount: Amount of Purchase. 112 | * Callback URL: A valid `URI` or `URL` Address for sending result purchase. 113 | * Description: A Content for showing payer. 114 | 115 | **Optional Parameters:** 116 | 117 | * Mobile: Valid Mobile number of payer. 118 | * Email: Valid Email Address of payer. 119 | 120 | ```java 121 | Purchase purchase = Purchase.newBuilder().asPaymentRequest( 122 | "MERCHANT_ID", 123 | 1000L, 124 | "http:\\YOUR_SEVER_URL.com", 125 | "1000IRR Purchase" 126 | ).build(); 127 | ``` 128 | 129 | Maybe You had `Authority`, here You must use `asAuthority()` 130 | ```java 131 | Purchase purchase = Purchase.newBuilder() 132 | .asAuthority("AUTHORITY_RESOLVED") 133 | .build(); 134 | ``` 135 | for `Sku` purchase: 136 | ```java 137 | Purchase purchase = Purchase.newBuilder() 138 | .asSku("SKU_ID") // SKU_ID is an Id that you've generated on ZarinPal panel. 139 | .build(); 140 | ``` 141 | 142 | **Step 3** 143 | 144 | You must call `purchase` method to begin flow payment: 145 | ```java 146 | client.launchBillingFlow(purchase, new FutureCompletionListener() { 147 | @Override 148 | public void onComplete(TaskResult task) { 149 | if (task.isSuccess()) { 150 | Receipt receipt = task.getSuccess(); 151 | Log.v("ZP_RECEIPT", receipt.getTransactionID()); 152 | 153 | //here you can send receipt data to your server 154 | //sentToServer(receipt) 155 | 156 | } else { 157 | task.getFailure().printStackTrace(); 158 | } 159 | } 160 | }); 161 | ``` 162 | 163 | **Step 4** 164 | 165 | Finally if your eligible to have payment process through **MPG** You should adding `usesCleartextTraffic` to application tag in your `Manifest.xml` 166 | ```xml 167 | 168 | 173 | ``` 174 | 175 | SKU Query 176 | ========= 177 | 178 | The ZarinPal Library stores the query results in a List of SkuPurchased objects. You can then call `querySkuPurchased` and you appear sku purchased with inforamtion in your view and provide service. 179 | 180 | ```java 181 | List skus = Arrays.asList("SKU_ID_000", "SKU_ID_001"); 182 | SkuQueryParams skuQuery = SkuQueryParams.newBuilder("MERCHANT_ID") 183 | .setSkuList(skus) 184 | .orderByMobile("0935******") 185 | .build(); 186 | 187 | 188 | client.querySkuPurchased(skuQuery, new FutureCompletionListener>() { 189 | @Override 190 | public void onComplete(TaskResult> task) { 191 | if (task.isSuccess()) { 192 | List skuPurchaseList = task.getSuccess(); 193 | for (SkuPurchased it : skuPurchaseList) { 194 | Log.v("ZP_SKU_PURCHASED", "${it.authority} ${it.productId}"); 195 | } 196 | } else { 197 | task.getFailure().printStackTrace(); 198 | } 199 | } 200 | }); 201 | ```` 202 | 203 | Features 204 | ======== 205 | 206 | **Dark Mode** 207 | 208 | ```java 209 | client.setNightMode(AppCompatDelegate.MODE_NIGHT_YES) 210 | ``` 211 | 212 | **Appear Invoice** 213 | 214 | ```java 215 | client.enableShowInvoice() 216 | ``` 217 | 218 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ZarinPal In App Billing - Purchase SDK | MPG 2 | ============================================ 3 | ZarinPal Purchase SDK Provides payment methods on your Android Application. [Java Readme](https://github.com/ZarinPal/Android-SDK/blob/master/README%20_JAVA.md) here if You want to develop it. 4 | 5 | 6 | 7 | Introduction 8 | ============= 9 | ZarinPal in-app purchases are the simplest solution to selling digital products or content on Android apps. So many app developers who want to sell digital goods or offer premium membership to users can simply use the it, in-app billing process for smooth and easy checkouts. 10 | 11 | 12 |

13 | sample 14 |

15 | 16 | 17 | Requirements 18 | ============ 19 | 20 | * Android 5.0 (API level 21) and above 21 | * Android Gradle Plugin 3.5.1 22 | * Gradle 5.4.1+ 23 | * AndroidX (as of v11.0.0) 24 | 25 | Installation 26 | ============ 27 | 28 | **Step 1** 29 | 30 | Add this to your root build.gradle at the end of repositories. 31 | ```gradle 32 | allprojects { 33 | ext.zarinpalSdkVersion = (LATEST_VERSION_REALEASE) //inform of Releases: https://github.com/ZarinPal/Android-SDK/releases 34 | repositories { 35 | ... 36 | mavenCentral() 37 | } 38 | ``` 39 | 40 | **Step 2** 41 | 42 | Add the dependency: 43 | ```gradle 44 | dependencies { 45 | implementation 'com.zarinpal:payment-provider:ext.zarinpalSdkVersion' 46 | } 47 | ``` 48 | 49 | 50 | If your project and business trusted to ZarinPal, SDK ables to providing **Mobile Payment Gateway** on your App so You should add the **MPG** dependency: 51 | ```gradle 52 | dependencies { 53 | implementation 'com.zarinpal:payment-provider:ext.zarinpalSdkVersion' 54 | implementation 'com.zarinpal:mpg:ext.zarinpalSdkVersion' 55 | } 56 | ``` 57 | 58 | How to use 59 | ========== 60 | 61 | * add Permissions in your `Manifest.xml`: 62 | ```xml 63 | 64 | 65 | ``` 66 | 67 | Initialize the billing client 68 | ============================= 69 | 70 | **Step 1** 71 | 72 | * `ZarinPalClientBilling` provides to create the billing client instance: 73 | ```kotlin 74 | val client = ZarinPalBillingClient.newBuilder(this) 75 | .enableShowInvoice() 76 | .setListener(stateListener) 77 | .setNightMode(AppCompatDelegate.MODE_NIGHT_YES) 78 | .build() 79 | 80 | private val stateListener = object : BillingClientStateListener { 81 | override fun onClientSetupFinished(state: ClientState) { 82 | //Observing client states 83 | } 84 | 85 | override fun onClientServiceDisconnected() { 86 | Log.v("TAG_INAPP","Billing client Disconnected") 87 | //When Service disconnect 88 | } 89 | } 90 | 91 | ``` 92 | 93 | **Step 2** 94 | 95 | For start purchase you need a `Purchase` instance, `Purchase` has 3 type of Payment: 96 | 97 | * as **Payment Request** by `asPaymentRequest()` 98 | * as **Authority ID** by `asAuthority()` 99 | * as **Sku ID** by `asSku()` 100 | 101 | If you would create payment Authority on Client, You must use `asPayementRequest()`, this method needs below parameters: 102 | 103 | **Require Parameters:** 104 | 105 | * Merchant id: An unique ID of your business payment gateway. 106 | * Amount: Amount of Purchase. 107 | * Callback URL: A valid `URL` Address for sending result purchase. 108 | * Description: A Content for showing payer. 109 | 110 | **Optional Parameters:** 111 | 112 | * Mobile: Valid Mobile number of payer. 113 | * Email: Valid Email Address of payer. 114 | 115 | ```kotlin 116 | val purchase = Purchase.newBuilder() 117 | .asPaymentRequest( 118 | "MERCHANT_ID", 119 | 1000, 120 | "http:\\YOUR_SEVER_URL.com", 121 | "1000IRR Purchase" 122 | ).build() 123 | ``` 124 | 125 | Maybe You had `Authority`, here You must use `asAuthority()` 126 | ```kotlin 127 | val purchase = Purchase .newBuilder() 128 | .asAuthority("AUTHORITY_RESOLVED") 129 | .build() 130 | ``` 131 | for `Sku` purchase: 132 | ```kotlin 133 | val purchase = Purchase.newBuilder() 134 | .asSku("SKU_ID") // SKU_ID is an Id that you've generated on ZarinPal panel. 135 | .build() 136 | ``` 137 | 138 | **Step 3** 139 | 140 | You must call `purchase` method to begin flow payment: 141 | ```kotlin 142 | client.launchBillingFlow(purchase, object : FutureCompletionListener { 143 | override fun onComplete(task: TaskResult) { 144 | if (task.isSuccess) { 145 | val receipt = task.success 146 | Log.v("ZP_RECEIPT", receipt?.transactionID) 147 | 148 | //here you can send receipt data to your server 149 | //sentToServer(receipt) 150 | 151 | } else { 152 | task.failure?.printStackTrace() 153 | } 154 | } 155 | }) 156 | ``` 157 | 158 | **Step 4** 159 | 160 | Finally if your eligible to have payment process through **MPG** You should adding `usesCleartextTraffic` to application tag in your `Manifest.xml` 161 | ```xml 162 | 163 | 168 | ``` 169 | 170 | SKU Query 171 | ========= 172 | 173 | The ZarinPal Library stores the query results in a List of SkuPurchased objects. You can then call `querySkuPurchased` and you appear sku purchased with inforamtion in your view and provide service. 174 | 175 | ```kotlin 176 | val skuQuery = SkuQueryParams.newBuilder("MERCHANT_ID") 177 | .setSkuList(listOf("SKU_ID_000", "SKU_ID_001")) 178 | .orderByMobile("0935******") 179 | .build() 180 | 181 | 182 | client.querySkuPurchased(skuQuery, object : FutureCompletionListener> { 183 | override fun onComplete(task: TaskResult>) { 184 | if (task.isSuccess){ 185 | val skuPurchaseList = task.success 186 | skuPurchaseList?.forEach { 187 | Log.v("ZP_SKU_PURCHASED", "${it.authority} ${it.productId}") 188 | } 189 | }else{ 190 | task.failure?.printStackTrace() 191 | } 192 | } 193 | }) 194 | ```` 195 | 196 | KTX 197 | ==== 198 | a Kotlin extensions for the ZarinPal SDK for Android and Utility Library. These extensions provide Kotlin language features in `Coroutines` async method: 199 | 200 | ```gradle 201 | dependencies { 202 | implementation 'com.zarinpal:payment-provider-ktx:ext.zarinpalSdkVersion' 203 | } 204 | ``` 205 | 206 | and to invoke `purchase` suspendable method in coroutine scope to start purchase flow: 207 | ```kotlin 208 | CoroutineScope(Dispatchers.IO).launch { 209 | try { 210 | val receipt = client.launchBillingFlow(purchase) 211 | Log.v("ZP_RECEIPT", receipt.transactionID) 212 | } catch (ex: Exception) { 213 | ex.printStackTrace() 214 | } 215 | } 216 | ``` 217 | 218 | invoke `querySkuPurchased`suspendable method in coroutine scope to start purchase flow: 219 | ```kotlin 220 | CoroutineScope(Dispatchers.IO).launch { 221 | try { 222 | val skuPurchaseList = client.querySkuPurchased(skuQuery) 223 | skuPurchaseList?.forEach { 224 | Log.v("ZP_SKU_PURCHASED", "${it.authority} ${it.productId}") 225 | } 226 | } catch (ex: Exception) { 227 | ex.printStackTrace() 228 | } 229 | } 230 | ``` 231 | 232 | Contract 233 | ======== 234 | A contract is a middlware between ZarinPal SDK and your server that provides a new payment provider as credit or digital wallet. 235 | ```gradle 236 | dependencies { 237 | implementation 'com.zarinpal:contract:ext.zarinpalSdkVersion' 238 | } 239 | ``` 240 | 241 | Features 242 | ======== 243 | 244 | **Dark Mode** 245 | 246 | ```kotlin 247 | client.setNightMode(AppCompatDelegate.MODE_NIGHT_YES) 248 | ``` 249 | 250 | **Appear Invoice** 251 | 252 | ```kotlin 253 | client.enableShowInvoice() 254 | ``` 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | Releases 263 | ======== 264 | 265 | * The Changelog provides a summary of changes in each release 266 | 267 | * The migration guide provides instructions on upgrading from old SDK. 268 | 269 | 270 | Proguard 271 | ======== 272 | 273 | The ZarinPal Android SDK will configure your app’s procured (ruls or text file link) 274 | 275 | Developed By 276 | ============ 277 | 278 | The Product developed by ZarinPal Team also You can Communicate and open issue 279 | 280 | -------------------------------------------------------------------------------- /Sample/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /Sample/app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.application' 3 | id 'kotlin-android' 4 | } 5 | 6 | 7 | project.ext { 8 | zarinpalSdkVersion = "0.5.3" 9 | } 10 | 11 | android { 12 | compileSdk 31 13 | 14 | defaultConfig { 15 | applicationId "com.zarinpal.sample.inappbilling" 16 | minSdk 21 17 | targetSdk 31 18 | versionCode 1 19 | versionName "1.0" 20 | 21 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 22 | } 23 | 24 | buildTypes { 25 | release { 26 | minifyEnabled false 27 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 28 | } 29 | } 30 | compileOptions { 31 | sourceCompatibility JavaVersion.VERSION_1_8 32 | targetCompatibility JavaVersion.VERSION_1_8 33 | } 34 | kotlinOptions { 35 | jvmTarget = '1.8' 36 | } 37 | 38 | viewBinding { 39 | enabled = true 40 | } 41 | 42 | } 43 | 44 | dependencies { 45 | 46 | implementation 'androidx.core:core-ktx:1.7.0' 47 | implementation 'androidx.appcompat:appcompat:1.4.1' 48 | implementation 'com.google.android.material:material:1.5.0' 49 | implementation "com.zarinpal:payment-provider:" + project.ext.zarinpalSdkVersion 50 | 51 | //If you have access to mpg by ZarinPal. 52 | implementation "com.zarinpal:mpg:" + project.ext.zarinpalSdkVersion 53 | 54 | } -------------------------------------------------------------------------------- /Sample/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 -------------------------------------------------------------------------------- /Sample/app/src/androidTest/java/com/zarinpal/sample/inappbilling/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.zarinpal.sample.inappbilling 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 22 | assertEquals("com.zarinpal.sample.inappbilling", appContext.packageName) 23 | } 24 | } -------------------------------------------------------------------------------- /Sample/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /Sample/app/src/main/java/com/zarinpal/sample/inappbilling/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.zarinpal.sample.inappbilling 2 | 3 | import androidx.appcompat.app.AppCompatActivity 4 | import android.os.Bundle 5 | import android.util.Log 6 | import android.view.View 7 | import android.widget.TextView 8 | import android.widget.Toast 9 | import androidx.appcompat.app.AppCompatDelegate 10 | import com.zarinpal.ZarinPalBillingClient 11 | import com.zarinpal.billing.purchase.Purchase 12 | import com.zarinpal.client.BillingClientStateListener 13 | import com.zarinpal.client.ClientState 14 | import com.zarinpal.provider.core.future.FutureCompletionListener 15 | import com.zarinpal.provider.core.future.TaskResult 16 | import com.zarinpal.provider.model.response.Receipt 17 | import com.zarinpal.sample.inappbilling.databinding.ActivityMainBinding 18 | 19 | class MainActivity : AppCompatActivity() { 20 | 21 | private var client: ZarinPalBillingClient? = null 22 | 23 | companion object { 24 | const val TAG = "InAppBilling Sample: " 25 | } 26 | 27 | override fun onCreate(savedInstanceState: Bundle?) { 28 | super.onCreate(savedInstanceState) 29 | setContentView(R.layout.activity_main) 30 | 31 | val txtReceipt = findViewById(R.id.txt_receipt) 32 | 33 | val billingClientStateListener = object : BillingClientStateListener { 34 | override fun onClientServiceDisconnected() { 35 | Log.d(TAG, "onClientServiceDisconnected") 36 | } 37 | 38 | override fun onClientSetupFinished(state: ClientState) { 39 | Log.d(TAG, "onClientSetupFinished ${state.name}") 40 | 41 | } 42 | } 43 | 44 | 45 | val purchaseCompletedListener = object : FutureCompletionListener { 46 | override fun onComplete(task: TaskResult) { 47 | Log.d(TAG, "onComplete Receipt is ${task.isSuccess}") 48 | 49 | if (task.isSuccess) { 50 | txtReceipt.text = "Receipt: \n" + 51 | "Transaction id: ${task.success?.transactionID}\n" + 52 | "Amount: ${task.success?.amount}\n" + 53 | "Date: ${task.success?.date}\n" + 54 | "Status: ${task.success?.isSuccess}\n" 55 | } else { 56 | 57 | txtReceipt.text = "Receipt failed: \n" + 58 | "${task.failure?.message}" 59 | } 60 | 61 | } 62 | } 63 | 64 | 65 | 66 | client = ZarinPalBillingClient.newBuilder(this) 67 | .setNightMode(AppCompatDelegate.MODE_NIGHT_YES) 68 | .enableShowInvoice() 69 | .setListener(billingClientStateListener) 70 | .build() 71 | 72 | 73 | findViewById(R.id.btn_payment_request).setOnClickListener { 74 | client?.launchBillingFlow(getPurchaseAsPaymentRequest(), purchaseCompletedListener) 75 | } 76 | 77 | findViewById(R.id.btn_authority).setOnClickListener { 78 | client?.launchBillingFlow(getPurchaseAsAuthority(), purchaseCompletedListener) 79 | } 80 | 81 | findViewById(R.id.btn_sku).setOnClickListener { 82 | client?.launchBillingFlow(getPurchaseAsSku(), purchaseCompletedListener) 83 | } 84 | 85 | } 86 | 87 | private fun getPurchaseAsPaymentRequest(): Purchase { 88 | val merchantId = "6c64a645-1b28-4956-b32e-7b777864121a" 89 | val amount = 1000L 90 | val description = "Payment Request via ZarinPal SDK" 91 | val callback = "https://google.com" // Your Server address 92 | 93 | 94 | return Purchase.newBuilder() 95 | .asPaymentRequest(merchantId, amount, callback, description) 96 | .build() 97 | 98 | } 99 | 100 | 101 | private fun getPurchaseAsAuthority(): Purchase { 102 | 103 | val authority = "" // The authority that resolved from ZarinPal 104 | return Purchase.newBuilder() 105 | .asAuthority(authority) 106 | .build() 107 | 108 | } 109 | 110 | private fun getPurchaseAsSku(): Purchase { 111 | val sku = "" // sku created from ZarinPal 112 | return Purchase.newBuilder() 113 | .asSku(sku) 114 | .build() 115 | } 116 | } -------------------------------------------------------------------------------- /Sample/app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /Sample/app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /Sample/app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 |