├── android ├── settings.gradle ├── gradle.properties ├── .gitignore ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties ├── src │ └── main │ │ ├── AndroidManifest.xml │ │ └── kotlin │ │ └── cu │ │ └── fluttercuba │ │ └── apklis_payment_checker │ │ ├── ApklisPaymentCheckerPlugin.kt │ │ └── Verify.kt └── build.gradle ├── example ├── README.md ├── android │ ├── gradle.properties │ ├── app │ │ ├── src │ │ │ ├── main │ │ │ │ ├── res │ │ │ │ │ ├── mipmap-hdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-mdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-xhdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── drawable │ │ │ │ │ │ └── launch_background.xml │ │ │ │ │ └── values │ │ │ │ │ │ └── styles.xml │ │ │ │ ├── kotlin │ │ │ │ │ └── cu │ │ │ │ │ │ └── fluttercuba │ │ │ │ │ │ └── apklis_payment_checker_example │ │ │ │ │ │ └── MainActivity.kt │ │ │ │ └── AndroidManifest.xml │ │ │ ├── debug │ │ │ │ └── AndroidManifest.xml │ │ │ └── profile │ │ │ │ └── AndroidManifest.xml │ │ └── build.gradle │ ├── gradle │ │ └── wrapper │ │ │ └── gradle-wrapper.properties │ ├── .gitignore │ ├── build.gradle │ └── settings.gradle ├── .metadata ├── analysis_options.yaml ├── pubspec.yaml ├── .gitignore └── lib │ └── main.dart ├── .metadata ├── .gitignore ├── test ├── apklis_payment_status_test.dart ├── apklis_info_test.dart └── apklis_payment_checker_test.dart ├── pubspec.yaml ├── analysis_options.yaml ├── .github ├── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md └── workflows │ ├── publish.yml │ └── tests.yml ├── lib ├── apklis_payment_status.dart ├── apklis_info.dart └── apklis_payment_checker.dart ├── CHANGELOG.md ├── LICENSE ├── README.md └── CODE_OF_CONDUCT.md /android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'apklis_payment_checker' 2 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # Apklis Payment Checker Example for Flutter 2 | 3 | Demonstrates how to use the `apklis_payment_checker` plugin. 4 | -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | -------------------------------------------------------------------------------- /example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | android.enableR8=true 5 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercuba/apklis-payment-checker-flutter/HEAD/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercuba/apklis-payment-checker-flutter/HEAD/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercuba/apklis-payment-checker-flutter/HEAD/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercuba/apklis-payment-checker-flutter/HEAD/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercuba/apklis-payment-checker-flutter/HEAD/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip 6 | -------------------------------------------------------------------------------- /example/android/app/src/main/kotlin/cu/fluttercuba/apklis_payment_checker_example/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package cu.fluttercuba.apklis_payment_checker_example 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() { 6 | } 7 | -------------------------------------------------------------------------------- /example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 23 08:50:38 CEST 2017 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-8.10.2-all.zip 7 | -------------------------------------------------------------------------------- /example/android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app 11 | key.properties 12 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 1aafb3a8b9b0c36241c5f5b34ee914770f015818 8 | channel: stable 9 | 10 | project_type: plugin 11 | -------------------------------------------------------------------------------- /example/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 1aafb3a8b9b0c36241c5f5b34ee914770f015818 8 | channel: stable 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | 2 | allprojects { 3 | repositories { 4 | google() 5 | jcenter() 6 | } 7 | } 8 | 9 | rootProject.buildDir = '../build' 10 | subprojects { 11 | project.buildDir = "${rootProject.buildDir}/${project.name}" 12 | project.evaluationDependsOn(':app') 13 | } 14 | 15 | tasks.register("clean", Delete) { 16 | delete rootProject.buildDir 17 | } 18 | -------------------------------------------------------------------------------- /example/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .dart_tool/ 3 | 4 | .packages 5 | .pub/ 6 | 7 | build/ 8 | 9 | # Added manually 10 | 11 | # https://dart.dev/guides/libraries/private-files#the-rules 12 | doc/api/ 13 | 14 | # https://dart.dev/guides/libraries/private-files#pubspeclock 15 | # Except for application packages 16 | pubspec.lock 17 | 18 | # IntelliJ 19 | *.iml 20 | *.ipr 21 | *.iws 22 | .idea/ 23 | 24 | # VSCode 25 | .code 26 | coverage/ 27 | -------------------------------------------------------------------------------- /android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /example/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:lint/analysis_options.yaml 2 | 3 | analyzer: 4 | exclude: 5 | #- '**.freezed.dart' 6 | 7 | linter: 8 | rules: 9 | # Util classes are awesome! 10 | # avoid_classes_with_only_static_members: false 11 | 12 | # Make constructors the first thing in every class 13 | # sort_constructors_first: true 14 | 15 | # Choose wisely, but you don't have to 16 | # prefer_double_quotes: true 17 | # prefer_single_quotes: true -------------------------------------------------------------------------------- /example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: apklis_payment_checker_example 2 | description: Demonstrates how to use the apklis_payment_checker plugin. 3 | 4 | publish_to: "none" 5 | 6 | environment: 7 | sdk: ">=3.2.0 <4.0.0" 8 | 9 | dependencies: 10 | apklis_payment_checker: 11 | path: ../ 12 | cupertino_icons: ^1.0.0 13 | flutter: 14 | sdk: flutter 15 | 16 | dev_dependencies: 17 | flutter_test: 18 | sdk: flutter 19 | lint: ^1.10.0 20 | 21 | flutter: 22 | uses-material-design: true 23 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /test/apklis_payment_status_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:apklis_payment_checker/apklis_payment_status.dart'; 2 | import 'package:flutter_test/flutter_test.dart'; 3 | 4 | void main() { 5 | group('ApklisPaymentStatus', () { 6 | test('support equality', () { 7 | final paymentStatus1 = 8 | ApklisPaymentStatus(paid: true, username: 'username'); 9 | final paymentStatus2 = 10 | ApklisPaymentStatus(paid: true, username: 'username'); 11 | 12 | expect(paymentStatus1, equals(paymentStatus2)); 13 | expect(paymentStatus1.hashCode, equals(paymentStatus2.hashCode)); 14 | }); 15 | }); 16 | } 17 | -------------------------------------------------------------------------------- /test/apklis_info_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:apklis_payment_checker/apklis_info.dart'; 2 | import 'package:flutter_test/flutter_test.dart'; 3 | 4 | void main() { 5 | group('ApklisInfo', () { 6 | test('support equality', () { 7 | final apklisInfo1 = ApklisInfo( 8 | isInstalled: true, 9 | versionCode: 1, 10 | versionName: '1.0.0', 11 | ); 12 | final apklisInfo2 = ApklisInfo( 13 | isInstalled: true, 14 | versionCode: 1, 15 | versionName: '1.0.0', 16 | ); 17 | 18 | expect(apklisInfo1, equals(apklisInfo2)); 19 | expect(apklisInfo1.hashCode, equals(apklisInfo2.hashCode)); 20 | }); 21 | }); 22 | } 23 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: apklis_payment_checker 2 | description: Plugin de Flutter para el chequeo de pagos de Apklis. Basado en el repositorio para Kotlin y Java https://github.com/Z17-CU/apklischeckpayment 3 | version: 1.1.0 4 | homepage: https://github.com/fluttercuba/apklis-payment-checker-flutter 5 | 6 | environment: 7 | sdk: ">=3.2.0 <4.0.0" 8 | flutter: ">=3.16.0" 9 | 10 | dependencies: 11 | flutter: 12 | sdk: flutter 13 | 14 | dev_dependencies: 15 | flutter_test: 16 | sdk: flutter 17 | lint: ^2.8.0 18 | 19 | flutter: 20 | plugin: 21 | platforms: 22 | android: 23 | package: cu.fluttercuba.apklis_payment_checker 24 | pluginClass: ApklisPaymentCheckerPlugin 25 | -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:lint/analysis_options.yaml 2 | 3 | # You might want to exclude auto-generated files from dart analysis 4 | analyzer: 5 | exclude: 6 | #- '**.freezed.dart' 7 | 8 | # You can customize the lint rules set to your own liking. A list of all rules 9 | # can be found at https://dart-lang.github.io/linter/lints/options/options.html 10 | linter: 11 | rules: 12 | # Util classes are awesome! 13 | # avoid_classes_with_only_static_members: false 14 | 15 | # Make constructors the first thing in every class 16 | # sort_constructors_first: true 17 | 18 | # Choose wisely, but you don't have to 19 | # prefer_double_quotes: true 20 | # prefer_single_quotes: true -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Solicitud de característica 3 | about: Sugerir una idea para este proyecto 4 | title: '[FEATURE] ' 5 | labels: 'feature' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **¿Su solicitud de característica está relacionada con un problema? Por favor describa.** 11 | Una descripción clara y concisa de cuál es el problema. Ex. Siempre me frustra cuando [...] 12 | 13 | **Describe la solución que te gustaría** 14 | Una descripción clara y concisa de lo que quieres que suceda. 15 | 16 | **Describe las alternativas que has considerado** 17 | Una descripción clara y concisa de cualquier solución o característica alternativa que haya considerado. 18 | 19 | **Contexto adicional** 20 | Agregue cualquier otro contexto o capturas de pantalla sobre la solicitud de función aquí. 21 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | **/ios/Flutter/.last_build_id 26 | .dart_tool/ 27 | .flutter-plugins 28 | .flutter-plugins-dependencies 29 | .packages 30 | .pub-cache/ 31 | .pub/ 32 | /build/ 33 | 34 | # Web related 35 | lib/generated_plugin_registrant.dart 36 | 37 | # Symbolication related 38 | app.*.symbols 39 | 40 | # Obfuscation related 41 | app.*.map.json 42 | -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | def flutterSdkPath = { 3 | def properties = new Properties() 4 | file("local.properties").withInputStream { properties.load(it) } 5 | def flutterSdkPath = properties.getProperty("flutter.sdk") 6 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 7 | return flutterSdkPath 8 | }() 9 | 10 | includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") 11 | 12 | repositories { 13 | google() 14 | mavenCentral() 15 | gradlePluginPortal() 16 | } 17 | } 18 | 19 | plugins { 20 | id "dev.flutter.flutter-plugin-loader" version "1.0.0" 21 | id 'com.android.library' version '8.8.2' apply false 22 | id 'org.jetbrains.kotlin.android' version '2.1.10' apply false 23 | } 24 | 25 | include ":app" -------------------------------------------------------------------------------- /lib/apklis_payment_status.dart: -------------------------------------------------------------------------------- 1 | /// La clase ApklisPaymentStatus registra el estado de un pago. 2 | /// 3 | /// Registra si esta pagado o no. 4 | /// Registra el nombre de usuario que realiza la acción de chequeo. 5 | class ApklisPaymentStatus { 6 | /// El [paid] almacena el estado del Payment en true | false 7 | final bool paid; 8 | 9 | /// El [username] almacena el nombre de usuario. 10 | final String? username; 11 | 12 | /// Para crear un instancia de la clase [ApklisPaymentStatus] 13 | ApklisPaymentStatus({ 14 | required this.paid, 15 | required this.username, 16 | }); 17 | 18 | @override 19 | bool operator ==(Object other) { 20 | if (identical(this, other)) return true; 21 | 22 | return other is ApklisPaymentStatus && 23 | other.paid == paid && 24 | other.username == username; 25 | } 26 | 27 | @override 28 | int get hashCode => paid.hashCode ^ username.hashCode; 29 | } 30 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | # .github/workflows/publish.yml 2 | name: Publish to pub.dev 3 | 4 | on: 5 | push: 6 | tags: 7 | # must align with the tag-pattern configured on pub.dev, often just replace 8 | # {{version}} with [0-9]+.[0-9]+.[0-9]+ 9 | # - 'v[0-9]+.[0-9]+.[0-9]+' # tag-pattern on pub.dev: 'v{{version}}' 10 | - 'v*.*.*' 11 | # If you prefer tags like '1.2.3', without the 'v' prefix, then use: 12 | # - '[0-9]+.[0-9]+.[0-9]+' # tag-pattern on pub.dev: '{{version}}' 13 | # If your repository contains multiple packages consider a pattern like: 14 | # - 'my_package_name-v[0-9]+.[0-9]+.[0-9]+' 15 | 16 | # Publish using the reusable workflow from dart-lang. 17 | jobs: 18 | publish: 19 | permissions: 20 | id-token: write # Required for authentication using OIDC 21 | uses: dart-lang/setup-dart/.github/workflows/publish.yml@v1 22 | # with: 23 | # working-directory: path/to/package/within/repository -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Historial de Cambios 2 | 3 | ## 1.1.0 4 | 5 | * Actualizada versión mínima de Flutter a ">=3.16.0" y Dart a ">=3.2.0 <4.0.0" 6 | * Actualizado el Apklis payment provider en Android 7 | * Actualizadas las versiones de AGP y Gradle 8 | 9 | ## 1.1.0-dev.4 10 | 11 | * Actulizada versión mínima de Flutter a ">=3.16.0" y Dart a ">=3.2.0 <4.0.0" 12 | 13 | ## 1.1.0-dev 14 | 15 | * Actulizado el Apklis payment provider en Android 16 | * Actulizadas las versiones de AGP y Gradle 17 | 18 | ## 1.0.0 19 | 20 | * Soporte para null-safety 21 | 22 | ## 0.3.1 23 | 24 | * Añadir comentarios para la generación automática de la documentación 25 | 26 | ## 0.3.0 27 | 28 | * Implementar método para saber si Apklis está instalada en el dispositivo (En caso positivo, saber también el número y nombre de la versión) 29 | 30 | ## 0.2.0 31 | 32 | * Utilizar por defecto el nombre del paquete de la aplicación 33 | 34 | ## 0.1.1 35 | 36 | * Poner de homepage el enlace al repositorio 37 | * Añadir un badge de la última versión disponible en pub.dev 38 | 39 | ## 0.1.0 40 | 41 | * Implementar la primera versión beta 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Flutter Cuba 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Informe de error 3 | about: Crea un informe de error para ayudarnos a mejorar 4 | title: '[BUG] ' 5 | labels: 'bug' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe el error** 11 | Una descripción clara y concisa de cuál es el error. 12 | 13 | **Reproducir** 14 | Pasos para reproducir el comportamiento: 15 | 1. Vaya a '...' 16 | 2. Haga clic en '....' 17 | 3. Desplácese hacia abajo hasta '....' 18 | 4. Ver error 19 | 20 | **Comportamiento esperado** 21 | Una descripción clara y concisa de lo que esperaba que sucediera. 22 | 23 | **Capturas de pantalla** 24 | Si corresponde, agregue capturas de pantalla para ayudar a explicar su problema. 25 | 26 | **Escritorio (complete la siguiente información):** 27 | - SO: [p. Ej. iOS] 28 | - Navegador [p. Ej. cromo, safari] 29 | - Versión [p. Ej. 22] 30 | 31 | **Smartphone (complete la siguiente información):** 32 | - Dispositivo: [p. Ej. iphone 6] 33 | - SO: [p. Ej. iOS8.1] 34 | - Navegador [p. Ej. navegador de valores, safari] 35 | - Versión [p. Ej. 22] 36 | 37 | **Contexto adicional** 38 | Agregue aquí cualquier otro contexto sobre el problema. 39 | -------------------------------------------------------------------------------- /lib/apklis_info.dart: -------------------------------------------------------------------------------- 1 | /// La clase ApklisInfo registra la información de la aplicación Apklis. 2 | /// 3 | /// Registra si se encuentra instalada o no. 4 | /// Registra el código de la versión. 5 | /// Registra el nombre de la versión. 6 | class ApklisInfo { 7 | /// El [isInstalled] almacena el valor en `true` si esta instalada 8 | /// y `false` en caso contrario. 9 | final bool isInstalled; 10 | 11 | /// El [versionCode] almacena el valor del código de la versión 12 | final int? versionCode; 13 | 14 | /// El [versionName] almacena el valor del nombre de la versión 15 | final String? versionName; 16 | 17 | /// Para crear una instancia de la clase [ApklisInfo] 18 | ApklisInfo({ 19 | required this.isInstalled, 20 | required this.versionCode, 21 | required this.versionName, 22 | }); 23 | 24 | @override 25 | bool operator ==(Object other) { 26 | if (identical(this, other)) return true; 27 | 28 | return other is ApklisInfo && 29 | other.isInstalled == isInstalled && 30 | other.versionCode == versionCode && 31 | other.versionName == versionName; 32 | } 33 | 34 | @override 35 | int get hashCode => 36 | isInstalled.hashCode ^ versionCode.hashCode ^ versionName.hashCode; 37 | } 38 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | group 'cu.fluttercuba.apklis_payment_checker' 2 | version '1.0-SNAPSHOT' 3 | 4 | buildscript { 5 | ext.kotlin_version = '1.7.10' 6 | repositories { 7 | google() 8 | mavenCentral() 9 | } 10 | 11 | dependencies { 12 | classpath 'com.android.tools.build:gradle:4.1.3' 13 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 14 | } 15 | } 16 | 17 | rootProject.allprojects { 18 | repositories { 19 | google() 20 | mavenCentral() 21 | } 22 | } 23 | 24 | apply plugin: 'com.android.library' 25 | apply plugin: 'kotlin-android' 26 | 27 | android { 28 | namespace="cu.fluttercuba.apklis_payment_checker" 29 | compileSdkVersion 34 30 | 31 | compileOptions { 32 | sourceCompatibility JavaVersion.VERSION_17 33 | targetCompatibility JavaVersion.VERSION_17 34 | } 35 | 36 | sourceSets { 37 | main.java.srcDirs += 'src/main/kotlin' 38 | } 39 | defaultConfig { 40 | minSdkVersion 16 41 | } 42 | lintOptions { 43 | disable 'InvalidPackage' 44 | } 45 | } 46 | 47 | dependencies { 48 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 49 | implementation 'androidx.annotation:annotation:1.4.0' 50 | } 51 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 17 | 20 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 32 | 33 | -------------------------------------------------------------------------------- /example/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id "com.android.application" 3 | id "kotlin-android" 4 | id "dev.flutter.flutter-gradle-plugin" 5 | } 6 | 7 | def localProperties = new Properties() 8 | def localPropertiesFile = rootProject.file('local.properties') 9 | if (localPropertiesFile.exists()) { 10 | localPropertiesFile.withReader('UTF-8') { reader -> 11 | localProperties.load(reader) 12 | } 13 | } 14 | 15 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 16 | if (flutterVersionCode == null) { 17 | flutterVersionCode = '1' 18 | } 19 | 20 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 21 | if (flutterVersionName == null) { 22 | flutterVersionName = '1.0' 23 | } 24 | 25 | android { 26 | namespace="cu.fluttercuba.apklis_payment_checker_example" 27 | compileSdkVersion 34 28 | 29 | compileOptions { 30 | sourceCompatibility JavaVersion.VERSION_17 31 | targetCompatibility JavaVersion.VERSION_17 32 | } 33 | 34 | sourceSets { 35 | main.java.srcDirs += 'src/main/kotlin' 36 | } 37 | 38 | lintOptions { 39 | disable 'InvalidPackage' 40 | } 41 | 42 | defaultConfig { 43 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 44 | applicationId "cu.fluttercuba.apklis_payment_checker_example" 45 | minSdkVersion flutter.minSdkVersion 46 | targetSdkVersion 31 47 | versionCode flutterVersionCode.toInteger() 48 | versionName flutterVersionName 49 | } 50 | 51 | buildTypes { 52 | release { 53 | // TODO: Add your own signing config for the release build. 54 | // Signing with the debug keys for now, so `flutter run --release` works. 55 | signingConfig signingConfigs.debug 56 | } 57 | } 58 | } 59 | 60 | flutter { 61 | source '../..' 62 | } 63 | -------------------------------------------------------------------------------- /lib/apklis_payment_checker.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:apklis_payment_checker/apklis_info.dart'; 4 | import 'package:apklis_payment_checker/apklis_payment_status.dart'; 5 | import 'package:flutter/services.dart'; 6 | 7 | // ignore: avoid_classes_with_only_static_members 8 | /// {@template apklis_payment_checker} 9 | /// La clase ApklisPaymentChecker registra las funcionalidades de Apklis. 10 | /// 11 | /// Registra la función para obtener el nombre del paquete. 12 | /// Registra la función para comprobar si esta pagado o no. 13 | /// Registra la función para obtener la información de Apklis. 14 | /// {@endtemplate} 15 | class ApklisPaymentChecker { 16 | /// Establece la comunicacion entre codigo de Kotlin/Android y Flutter/Dart. 17 | static const _channel = MethodChannel('apklis_payment_checker'); 18 | 19 | /// Devuelve `String` con el nombre del paquete. 20 | static Future getPackageName() async { 21 | final Map? map = await _channel.invokeMapMethod('getPackageName'); 22 | 23 | final String packageName = map!['packageName'] as String; 24 | 25 | return packageName; 26 | } 27 | 28 | /// Devuelve `Future` con la información del estado de pago. 29 | static Future isPurchased([String? packageId]) async { 30 | packageId ??= await getPackageName(); 31 | final Map? map = await _channel.invokeMapMethod('isPurchased', packageId); 32 | if (map == null) { 33 | return ApklisPaymentStatus(paid: false, username: null); 34 | } 35 | 36 | final paid = map['paid'] as bool; 37 | final username = map['username'] as String?; 38 | 39 | return ApklisPaymentStatus(paid: paid, username: username); 40 | } 41 | 42 | /// Devuelve `Future` con la información de Apklis. 43 | static Future getApklisInfo() async { 44 | final Map? map = await _channel.invokeMapMethod('getApklisInfo'); 45 | 46 | final isIntalled = map!['isIntalled'] as bool; 47 | 48 | if (isIntalled) { 49 | final versionCode = map['versionCode'] as int?; 50 | final versionName = map['versionName'] as String?; 51 | 52 | return ApklisInfo( 53 | isInstalled: isIntalled, 54 | versionCode: versionCode, 55 | versionName: versionName, 56 | ); 57 | } 58 | 59 | return ApklisInfo( 60 | isInstalled: false, 61 | versionCode: null, 62 | versionName: null, 63 | ); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /android/src/main/kotlin/cu/fluttercuba/apklis_payment_checker/ApklisPaymentCheckerPlugin.kt: -------------------------------------------------------------------------------- 1 | package cu.fluttercuba.apklis_payment_checker 2 | 3 | import android.content.Context 4 | import androidx.annotation.NonNull 5 | import io.flutter.embedding.engine.plugins.FlutterPlugin 6 | import io.flutter.plugin.common.MethodCall 7 | import io.flutter.plugin.common.MethodChannel 8 | import io.flutter.plugin.common.MethodChannel.MethodCallHandler 9 | import io.flutter.plugin.common.MethodChannel.Result 10 | 11 | /** ApklisPaymentCheckerPlugin */ 12 | class ApklisPaymentCheckerPlugin : FlutterPlugin, MethodCallHandler { 13 | /// The MethodChannel that will the communication between Flutter and native Android 14 | /// 15 | /// This local reference serves to register the plugin with the Flutter Engine and unregister it 16 | /// when the Flutter Engine is detached from the Activity 17 | private lateinit var channel: MethodChannel 18 | private lateinit var context: Context 19 | 20 | override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) { 21 | channel = MethodChannel(flutterPluginBinding.binaryMessenger, "apklis_payment_checker") 22 | channel.setMethodCallHandler(this) 23 | context = flutterPluginBinding.applicationContext 24 | } 25 | 26 | override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) { 27 | when (call.method) { 28 | "getPackageName" -> { 29 | val hashMap = HashMap() 30 | hashMap["packageName"] = context.packageName 31 | return result.success(hashMap) 32 | } 33 | "isPurchased" -> { 34 | val packageId = call.arguments() 35 | val response = packageId?.let { Verify.isPurchased(context, it) } 36 | val hashMap = HashMap() 37 | hashMap["paid"] = response?.first ?: false 38 | hashMap["username"] = response?.second 39 | return result.success(hashMap) 40 | } 41 | "getApklisInfo" -> { 42 | val response = Verify.getApklisInfo(context) 43 | val hashMap = HashMap() 44 | hashMap["isIntalled" ] = response.first 45 | hashMap["versionCode"] = response.second 46 | hashMap["versionName"] = response.third 47 | return result.success(hashMap) 48 | } 49 | else -> { 50 | result.notImplemented() 51 | } 52 | } 53 | } 54 | 55 | override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) { 56 | channel.setMethodCallHandler(null) 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | name: tests 2 | on: [push, pull_request, workflow_dispatch] 3 | jobs: 4 | tests: 5 | runs-on: ubuntu-latest 6 | steps: 7 | - name: Setup Action 8 | uses: actions/checkout@v2 9 | - name: Setup Java 10 | uses: actions/setup-java@v1 11 | with: 12 | java-version: '12.x' 13 | - name: Setup Flutter 14 | uses: subosito/flutter-action@v1 15 | with: 16 | channel: 'stable' 17 | - name: Run Tests 18 | run: | 19 | flutter pub get 20 | flutter test 21 | - name: Run Analysis 22 | uses: axel-op/dart-package-analyzer@v3 23 | id: analysis 24 | with: 25 | githubToken: ${{ secrets.GITHUB_TOKEN }} 26 | - name: Check Scores 27 | env: 28 | TOTAL: ${{ steps.analysis.outputs.total }} 29 | TOTAL_MAX: ${{ steps.analysis.outputs.total_max }} 30 | CONVENTIONS: ${{ steps.analysis.outputs.conventions }} 31 | CONVENTIONS_MAX: ${{ steps.analysis.outputs.conventions_max }} 32 | DOCUMENTATION: ${{ steps.analysis.outputs.documentation }} 33 | DOCUMENTATION_MAX: ${{ steps.analysis.outputs.documentation_max }} 34 | PLATFORMS: ${{ steps.analysis.outputs.platforms }} 35 | PLATFORMS_MAX: ${{ steps.analysis.outputs.platforms_max }} 36 | ANALYSIS: ${{ steps.analysis.outputs.analysis }} 37 | ANALYSIS_MAX: ${{ steps.analysis.outputs.analysis_max }} 38 | DEPENDENCIES: ${{ steps.analysis.outputs.dependencies }} 39 | DEPENDENCIES_MAX: ${{ steps.analysis.outputs.dependencies_max }} 40 | NULL_SAFETY: ${{ steps.analysis.outputs.null_safety }} 41 | NULL_SAFETY_MAX: ${{ steps.analysis.outputs.null_safety_max }} 42 | run: | 43 | # if (( $TOTAL < $TOTAL_MAX )) 44 | # then 45 | # exit 1 46 | # fi 47 | if (( $CONVENTIONS < $CONVENTIONS_MAX )) 48 | then 49 | echo Fail conventions section 50 | exit 1 51 | fi 52 | if (( $DOCUMENTATION < $DOCUMENTATION_MAX )) 53 | then 54 | echo Fail documentation section 55 | exit 1 56 | fi 57 | # if (( $PLATFORMS < $PLATFORMS_MAX )) 58 | # then 59 | # echo Fail platforms section 60 | # exit 1 61 | # fi 62 | if (( $ANALYSIS < $ANALYSIS_MAX )) 63 | then 64 | echo Fail analysis section 65 | exit 1 66 | fi 67 | if (( $DEPENDENCIES < $DEPENDENCIES_MAX )) 68 | then 69 | echo Fail dependencies section 70 | exit 1 71 | fi 72 | if (( $NULL_SAFETY < $NULL_SAFETY_MAX )) 73 | then 74 | echo Fail null_safety section 75 | exit 1 76 | fi 77 | -------------------------------------------------------------------------------- /android/src/main/kotlin/cu/fluttercuba/apklis_payment_checker/Verify.kt: -------------------------------------------------------------------------------- 1 | package cu.fluttercuba.apklis_payment_checker 2 | 3 | import android.content.Context 4 | import android.content.pm.PackageManager 5 | import android.net.Uri 6 | import android.os.RemoteException 7 | 8 | // Code from https://github.com/Z17-CU/apklischeckpayment 9 | class Verify { 10 | companion object { 11 | 12 | private const val APKLIS_PROVIDER = "content://cu.uci.android.apklis.PaymentProvider/app/" 13 | private const val APKLIS_PAID = "paid" 14 | private const val APKLIS_USER_NAME = "user_name" 15 | 16 | fun isPurchased(context: Context, packageId: String): Pair { 17 | var paid = false 18 | var userName: String? = null 19 | val providerURI: Uri = Uri.parse("$APKLIS_PROVIDER$packageId") 20 | try { 21 | val contentResolver = 22 | context.contentResolver.acquireContentProviderClient(providerURI) 23 | val cursor = contentResolver?.query(providerURI, null, null, null, null) 24 | cursor?.let { 25 | if (it.moveToFirst()) { 26 | paid = it.getInt(it.getColumnIndexOrThrow(APKLIS_PAID)) > 0 27 | userName = it.getString(it.getColumnIndexOrThrow(APKLIS_USER_NAME)) 28 | } 29 | } 30 | if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) { 31 | contentResolver?.close() 32 | } else { 33 | contentResolver?.release() 34 | } 35 | cursor?.close() 36 | } catch (e: RemoteException) { 37 | e.printStackTrace() 38 | } catch (e: IllegalArgumentException) { 39 | return Pair(false, null) 40 | } 41 | return Pair(paid, userName) 42 | } 43 | 44 | fun getApklisInfo(context: Context): Triple { 45 | var isInstaller: Boolean 46 | var versionCode: Int? = null 47 | var versionName: String? = null 48 | 49 | val packageManager: PackageManager = context.packageManager 50 | try { 51 | isInstaller = true 52 | val info = packageManager.getPackageInfo( 53 | "cu.uci.android.apklis", 54 | PackageManager.GET_ACTIVITIES 55 | ) 56 | versionName = info.versionName 57 | 58 | versionCode = if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.P) { 59 | info.longVersionCode.toInt() 60 | } else { 61 | info.versionCode 62 | } 63 | 64 | } catch (e: PackageManager.NameNotFoundException) { 65 | isInstaller = false 66 | } 67 | 68 | return Triple(isInstaller, versionCode, versionName) 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Apklis Payment Checker para Flutter 2 | 3 | [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT) 4 | [![Pub Version](https://img.shields.io/pub/v/apklis_payment_checker)](https://pub.dev/packages/apklis_payment_checker) 5 | [![tests](https://github.com/fluttercuba/apklis-payment-checker-flutter/workflows/tests/badge.svg?branch=main)](https://github.com/fluttercuba/apklis-payment-checker-flutter/actions?query=workflow%3Atests) 6 | [![Last commit](https://img.shields.io/github/last-commit/fluttercuba/apklis-payment-checker-flutter.svg?style=flat)](https://github.com/fluttercuba/apklis-payment-checker-flutter/commits) 7 | [![GitHub commit activity](https://img.shields.io/github/commit-activity/m/fluttercuba/apklis-payment-checker-flutter)](https://github.com/fluttercuba/apklis-payment-checker-flutter/commits) 8 | [![Github Stars](https://img.shields.io/github/stars/fluttercuba/apklis-payment-checker-flutter?style=flat&logo=github)](https://github.com/fluttercuba/apklis-payment-checker-flutter/stargazers) 9 | [![Github Forks](https://img.shields.io/github/forks/fluttercuba/apklis-payment-checker-flutter?style=flat&logo=github)](https://github.com/fluttercuba/apklis-payment-checker-flutter/network/members) 10 | [![Github Watchers](https://img.shields.io/github/watchers/fluttercuba/apklis-payment-checker-flutter?style=flat&logo=github)](https://github.com/fluttercuba/apklis-payment-checker-flutter) 11 | [![GitHub contributors](https://img.shields.io/github/contributors/fluttercuba/apklis-payment-checker-flutter)](https://github.com/fluttercuba/apklis-payment-checker-flutter/graphs/contributors) 12 | [![style: lint](https://img.shields.io/badge/style-lint-4BC0F5.svg)](https://pub.dev/packages/lint) 13 | 14 | Plugin de Flutter para el chequeo de pagos de Apklis 15 | 16 | Disponible en Pub.dev: 17 | 18 | ## Instalación 19 | 20 | Añade el plugin a las dependencias de tu proyecto: 21 | 22 | ```yaml 23 | dependencies: 24 | apklis_payment_checker: ^1.0.0 25 | ``` 26 | 27 | 🚧 Si tu app se orienta a Android 11 (nivel de API 30) o versiones posteriores debes agregar las siguientes líneas en el archivo `AndroidManifest.xml`: 28 | 29 | 1. Agrega el permiso ``: 30 | 31 | ```xml 32 | 33 | 34 | 35 | 36 | ... 37 | 38 | ``` 39 | 40 | 2. Agrega la bandera `android:exported="true"` al `activity` de la aplicación: 41 | 42 | ```xml 43 | ... 44 | 48 | ... 49 | ``` 50 | 51 | Ver el [archivo](https://github.com/fluttercuba/apklis-payment-checker-flutter/blob/main/example/android/app/src/main/AndroidManifest.xml) `AndroidManifest.xml` del ejemplo de este repositorio. 52 | 53 | ## Uso 54 | 55 | ```dart 56 | var status = await ApklisPaymentChecker.isPurchased(); 57 | print(status.paid); 58 | print(status.username); 59 | ``` 60 | 61 | Si se desea usar un nombre de paquete diferente al de la aplicación el método `isPurchased` puede recibirlo como parámetro: 62 | 63 | ```dart 64 | final packageId = 'com.example.nova.prosalud'; 65 | var status = await ApklisPaymentChecker.isPurchased(packageId); 66 | print(status.paid); 67 | print(status.username); 68 | ``` 69 | 70 | Para conocer información sobre Apklis: 71 | 72 | ```dart 73 | var apklisInfo = await ApklisPaymentChecker.getApklistInfo(); 74 | print(apklisInfo.isInstalled); 75 | print(apklisInfo.versionName); 76 | print(apklisInfo.versionCode); 77 | ``` 78 | 79 | Ejemplo completo disponible en: 80 | -------------------------------------------------------------------------------- /test/apklis_payment_checker_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:apklis_payment_checker/apklis_info.dart'; 2 | import 'package:apklis_payment_checker/apklis_payment_checker.dart'; 3 | import 'package:apklis_payment_checker/apklis_payment_status.dart'; 4 | import 'package:flutter/services.dart'; 5 | import 'package:flutter_test/flutter_test.dart'; 6 | 7 | void main() { 8 | const MethodChannel channel = MethodChannel('apklis_payment_checker'); 9 | 10 | const packageId = 'com.example.nova.prosalud'; 11 | 12 | TestWidgetsFlutterBinding.ensureInitialized(); 13 | 14 | tearDown(() { 15 | TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger 16 | .setMockMethodCallHandler(channel, null); 17 | }); 18 | 19 | test('channel have one instance', () { 20 | expect(channel, equals(const MethodChannel('apklis_payment_checker'))); 21 | }); 22 | // TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger 23 | test('getPackageName', () async { 24 | TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger 25 | .setMockMethodCallHandler( 26 | channel, 27 | (MethodCall methodCall) async { 28 | return { 29 | 'packageName': packageId, 30 | }; 31 | }, 32 | ); 33 | 34 | final packageName = await ApklisPaymentChecker.getPackageName(); 35 | 36 | expect(packageName, equals(packageId)); 37 | }); 38 | 39 | group('check isPunchased', () { 40 | test('when the packageId parameter is null and the app is not paid', 41 | () async { 42 | TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger 43 | .setMockMethodCallHandler( 44 | channel, 45 | (MethodCall methodCall) async { 46 | if (methodCall.method == 'getPackageName') { 47 | return { 48 | 'packageName': packageId, 49 | }; 50 | } 51 | return { 52 | 'paid': false, 53 | 'username': null, 54 | }; 55 | }, 56 | ); 57 | 58 | final status = await ApklisPaymentChecker.isPurchased(); 59 | 60 | expect( 61 | status, 62 | equals(ApklisPaymentStatus(paid: false, username: null)), 63 | ); 64 | }); 65 | 66 | test('when the app is not paid', () async { 67 | TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger 68 | .setMockMethodCallHandler( 69 | channel, 70 | (MethodCall methodCall) async { 71 | return { 72 | 'paid': false, 73 | 'username': null, 74 | }; 75 | }, 76 | ); 77 | 78 | final status = await ApklisPaymentChecker.isPurchased(packageId); 79 | 80 | expect( 81 | status, 82 | equals(ApklisPaymentStatus(paid: false, username: null)), 83 | ); 84 | }); 85 | 86 | test('when channel return null', () async { 87 | TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger 88 | .setMockMethodCallHandler( 89 | channel, 90 | (MethodCall methodCall) async { 91 | return null; 92 | }, 93 | ); 94 | 95 | final status = await ApklisPaymentChecker.isPurchased(packageId); 96 | 97 | expect( 98 | status, 99 | equals(ApklisPaymentStatus(paid: false, username: null)), 100 | ); 101 | }); 102 | 103 | test('when the app is paid', () async { 104 | TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger 105 | .setMockMethodCallHandler( 106 | channel, 107 | (MethodCall methodCall) async { 108 | return { 109 | 'paid': true, 110 | 'username': 'example', 111 | }; 112 | }, 113 | ); 114 | 115 | final status = await ApklisPaymentChecker.isPurchased(packageId); 116 | 117 | expect( 118 | status, 119 | equals(ApklisPaymentStatus(paid: true, username: 'example')), 120 | ); 121 | }); 122 | }); 123 | 124 | group('getApklisInfo', () { 125 | test('when the Apklis app is not intalled', () async { 126 | TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger 127 | .setMockMethodCallHandler( 128 | channel, 129 | (MethodCall methodCall) async { 130 | return { 131 | 'isIntalled': false, 132 | 'versionCode': null, 133 | 'versionName': null, 134 | }; 135 | }, 136 | ); 137 | 138 | final info = await ApklisPaymentChecker.getApklisInfo(); 139 | 140 | expect( 141 | info, 142 | equals( 143 | ApklisInfo( 144 | isInstalled: false, 145 | versionCode: null, 146 | versionName: null, 147 | ), 148 | ), 149 | ); 150 | }); 151 | 152 | test('when the Apklis app is installed but no user is logged in', () async { 153 | TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger 154 | .setMockMethodCallHandler( 155 | channel, 156 | (MethodCall methodCall) async { 157 | return { 158 | 'isIntalled': true, 159 | 'versionCode': null, 160 | 'versionName': null, 161 | }; 162 | }, 163 | ); 164 | 165 | final info = await ApklisPaymentChecker.getApklisInfo(); 166 | 167 | expect( 168 | info, 169 | equals( 170 | ApklisInfo( 171 | isInstalled: true, 172 | versionCode: null, 173 | versionName: null, 174 | ), 175 | ), 176 | ); 177 | }); 178 | }); 179 | } 180 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | 2 | # Código de Conducta convenido para Contribuyentes 3 | 4 | ## Nuestro compromiso 5 | 6 | Nosotros, como miembros, contribuyentes y administradores nos comprometemos a hacer de la participación en nuestra comunidad una experiencia libre de acoso para todo el mundo, independientemente de la edad, dimensión corporal, minusvalía visible o invisible, etnicidad, características sexuales, identidad y expresión de género, nivel de experiencia, educación, nivel socio-económico, nacionalidad, apariencia personal, raza, religión, o identidad u orientación sexual. 7 | 8 | Nos comprometemos a actuar e interactuar de maneras que contribuyan a una comunidad abierta, acogedora, diversa, inclusiva y sana. 9 | 10 | ## Nuestros estándares 11 | 12 | Ejemplos de comportamiento que contribuyen a crear un ambiente positivo para nuestra comunidad: 13 | 14 | * Demostrar empatía y amabilidad ante otras personas 15 | * Respeto a diferentes opiniones, puntos de vista y experiencias 16 | * Dar y aceptar adecuadamente retroalimentación constructiva 17 | * Aceptar la responsabilidad y disculparse ante quienes se vean afectados por nuestros errores, aprendiendo de la experiencia 18 | * Centrarse en lo que sea mejor no sólo para nosotros como individuos, sino para la comunidad en general 19 | 20 | Ejemplos de comportamiento inaceptable: 21 | 22 | * El uso de lenguaje o imágenes sexualizadas, y aproximaciones o 23 | atenciones sexuales de cualquier tipo 24 | * Comentarios despectivos (_trolling_), insultantes o derogatorios, y ataques personales o políticos 25 | * El acoso en público o privado 26 | * Publicar información privada de otras personas, tales como direcciones físicas o de correo 27 | electrónico, sin su permiso explícito 28 | * Otras conductas que puedan ser razonablemente consideradas como inapropiadas en un 29 | entorno profesional 30 | 31 | ## Aplicación de las responsabilidades 32 | 33 | Los administradores de la comunidad son responsables de aclarar y hacer cumplir nuestros estándares de comportamiento aceptable y tomarán acciones apropiadas y correctivas de forma justa en respuesta a cualquier comportamiento que consideren inapropiado, amenazante, ofensivo o dañino. 34 | 35 | Los administradores de la comunidad tendrán el derecho y la responsabilidad de eliminar, editar o rechazar comentarios, _commits_, código, ediciones de páginas de wiki, _issues_ y otras contribuciones que no se alineen con este Código de Conducta, y comunicarán las razones para sus decisiones de moderación cuando sea apropiado. 36 | 37 | ## Alcance 38 | 39 | Este código de conducta aplica tanto a espacios del proyecto como a espacios públicos donde un individuo esté en representación del proyecto o comunidad. Ejemplos de esto incluyen el uso de la cuenta oficial de correo electrónico, publicaciones a través de las redes sociales oficiales, o presentaciones con personas designadas en eventos en línea o no. 40 | 41 | ## Aplicación 42 | 43 | Instancias de comportamiento abusivo, acosador o inaceptable de otro modo podrán ser reportadas a los administradores de la comunidad responsables del cumplimiento a través de [INSERTAR MÉTODO DE CONTACTO]. Todas las quejas serán evaluadas e investigadas de una manera puntual y justa. 44 | 45 | Todos los administradores de la comunidad están obligados a respetar la privacidad y la seguridad de quienes reporten incidentes. 46 | 47 | ## Guías de Aplicación 48 | 49 | Los administradores de la comunidad seguirán estas Guías de Impacto en la Comunidad para determinar las consecuencias de cualquier acción que juzguen como un incumplimiento de este Código de Conducta: 50 | 51 | ### 1. Corrección 52 | 53 | **Impacto en la Comunidad**: El uso de lenguaje inapropiado u otro comportamiento considerado no profesional o no acogedor en la comunidad. 54 | 55 | **Consecuencia**: Un aviso escrito y privado por parte de los administradores de la comunidad, proporcionando claridad alrededor de la naturaleza de este incumplimiento y una explicación de por qué el comportamiento es inaceptable. Una disculpa pública podría ser solicitada. 56 | 57 | ### 2. Aviso 58 | 59 | **Impacto en la Comunidad**: Un incumplimiento causado por un único incidente o por una cadena de acciones. 60 | 61 | **Consecuencia**: Un aviso con consecuencias por comportamiento prolongado. No se interactúa con las personas involucradas, incluyendo interacción no solicitada con quienes se encuentran aplicando el Código de Conducta, por un periodo especificado de tiempo. Esto incluye evitar las interacciones en espacios de la comunidad, así como a través de canales externos como las redes sociales. Incumplir estos términos puede conducir a una expulsión temporal o permanente. 62 | 63 | ### 3. Expulsión temporal 64 | 65 | **Impacto en la Comunidad**: Una serie de incumplimientos de los estándares de la comunidad, incluyendo comportamiento inapropiado continuo. 66 | 67 | **Consecuencia**: Una expulsión temporal de cualquier forma de interacción o comunicación pública con la comunidad durante un intervalo de tiempo especificado. No se permite interactuar de manera pública o privada con las personas involucradas, incluyendo interacciones no solicitadas con quienes se encuentran aplicando el Código de Conducta, durante este periodo. Incumplir estos términos puede conducir a una expulsión permanente. 68 | 69 | ### 4. Expulsión permanente 70 | 71 | **Impacto en la Comunidad**: Demostrar un patrón sistemático de incumplimientos de los estándares de la comunidad, incluyendo conductas inapropiadas prolongadas en el tiempo, acoso de individuos, o agresiones o menosprecio a grupos de individuos. 72 | 73 | **Consecuencia**: Una expulsión permanente de cualquier tipo de interacción pública con la comunidad del proyecto. 74 | 75 | ## Atribución 76 | 77 | Este Código de Conducta es una adaptación del [Contributor Covenant][homepage], versión 2.0, 78 | disponible en https://www.contributor-covenant.org/es/version/2/0/code_of_conduct.html 79 | 80 | Las Guías de Impacto en la Comunidad están inspiradas en la [escalera de aplicación del código de conducta de Mozilla](https://github.com/mozilla/diversity). 81 | 82 | [homepage]: https://www.contributor-covenant.org 83 | 84 | Para respuestas a las preguntas frecuentes de este código de conducta, consulta las FAQ en 85 | https://www.contributor-covenant.org/faq. Hay traducciones disponibles en https://www.contributor-covenant.org/translations 86 | -------------------------------------------------------------------------------- /example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:developer'; 3 | 4 | import 'package:apklis_payment_checker/apklis_info.dart'; 5 | import 'package:apklis_payment_checker/apklis_payment_checker.dart'; 6 | import 'package:apklis_payment_checker/apklis_payment_status.dart'; 7 | import 'package:flutter/material.dart'; 8 | import 'package:flutter/services.dart'; 9 | 10 | void main() { 11 | runApp(ExampleApp()); 12 | } 13 | 14 | class ExampleApp extends StatefulWidget { 15 | @override 16 | ExampleAppState createState() => ExampleAppState(); 17 | } 18 | 19 | class ExampleAppState extends State { 20 | final keyForm = GlobalKey(); 21 | final controller = TextEditingController(); 22 | ApklisPaymentStatus? status; 23 | ApklisInfo? apklisInfo; 24 | 25 | @override 26 | void initState() { 27 | super.initState(); 28 | setPackageName(); 29 | } 30 | 31 | @override 32 | void dispose() { 33 | controller.dispose(); 34 | super.dispose(); 35 | } 36 | 37 | Future setPackageName() async { 38 | try { 39 | final packageName = await ApklisPaymentChecker.getPackageName(); 40 | setState(() => controller.text = packageName); 41 | } on PlatformException catch (e) { 42 | log(e.toString()); 43 | } 44 | } 45 | 46 | Future requestPaymentStatus(String packageId) async { 47 | try { 48 | final status = await ApklisPaymentChecker.isPurchased(packageId); 49 | setState(() => this.status = status); 50 | } on PlatformException catch (e) { 51 | log(e.toString()); 52 | } 53 | } 54 | 55 | Future getApklisInfo() async { 56 | final apklisInfo = await ApklisPaymentChecker.getApklisInfo(); 57 | setState(() => this.apklisInfo = apklisInfo); 58 | } 59 | 60 | @override 61 | Widget build(BuildContext context) { 62 | return MaterialApp( 63 | home: Scaffold( 64 | appBar: AppBar( 65 | centerTitle: true, 66 | title: const Text('Apklis Payment Checker'), 67 | ), 68 | body: Form( 69 | key: keyForm, 70 | autovalidateMode: AutovalidateMode.always, 71 | child: Column( 72 | children: [ 73 | Container( 74 | margin: 75 | const EdgeInsets.symmetric(vertical: 15, horizontal: 10), 76 | child: Row( 77 | children: [ 78 | Expanded( 79 | child: TextFormField( 80 | controller: controller, 81 | decoration: const InputDecoration( 82 | border: OutlineInputBorder( 83 | borderRadius: BorderRadius.all( 84 | Radius.circular(10.0), 85 | ), 86 | ), 87 | labelText: 'Package Id', 88 | hintText: 'com.example.nova.prosalud', 89 | ), 90 | keyboardType: TextInputType.text, 91 | validator: (value) { 92 | if (value == null || value.isEmpty) { 93 | return 'Is required'; 94 | } 95 | return null; 96 | }, 97 | ), 98 | ), 99 | ], 100 | ), 101 | ), 102 | if (status != null && apklisInfo != null) 103 | Column( 104 | children: [ 105 | Container( 106 | margin: const EdgeInsets.all(5), 107 | child: const Text('Apklis is installed:'), 108 | ), 109 | Container( 110 | margin: const EdgeInsets.all(5), 111 | child: Text( 112 | apklisInfo?.isInstalled.toString() ?? 'false', 113 | style: const TextStyle( 114 | fontWeight: FontWeight.bold, 115 | fontSize: 20, 116 | ), 117 | ), 118 | ), 119 | if (apklisInfo?.isInstalled ?? false) 120 | Column( 121 | children: [ 122 | Container( 123 | margin: const EdgeInsets.all(5), 124 | child: const Text('Apklis version code:'), 125 | ), 126 | Container( 127 | margin: const EdgeInsets.all(5), 128 | child: Text( 129 | apklisInfo?.versionCode.toString() ?? '', 130 | style: const TextStyle( 131 | fontWeight: FontWeight.bold, 132 | fontSize: 20, 133 | ), 134 | ), 135 | ), 136 | Container( 137 | margin: const EdgeInsets.all(5), 138 | child: const Text('Apklis version name:'), 139 | ), 140 | Container( 141 | margin: const EdgeInsets.all(5), 142 | child: Text( 143 | apklisInfo?.versionName ?? 'Unknown', 144 | style: const TextStyle( 145 | fontWeight: FontWeight.bold, 146 | fontSize: 20, 147 | ), 148 | ), 149 | ), 150 | Container( 151 | margin: const EdgeInsets.all(5), 152 | child: const Text('Username registered in Apklis:'), 153 | ), 154 | Container( 155 | margin: const EdgeInsets.all(5), 156 | child: Text( 157 | status?.username ?? 'Unknow', 158 | style: const TextStyle( 159 | fontWeight: FontWeight.bold, 160 | fontSize: 20, 161 | ), 162 | ), 163 | ), 164 | Container( 165 | margin: const EdgeInsets.all(5), 166 | child: const Text('App payment status:'), 167 | ), 168 | Container( 169 | margin: const EdgeInsets.all(5), 170 | child: Text( 171 | status?.paid.toString() ?? 'Unknow', 172 | style: const TextStyle( 173 | fontWeight: FontWeight.bold, 174 | fontSize: 20, 175 | ), 176 | ), 177 | ), 178 | ], 179 | ), 180 | ], 181 | ), 182 | ], 183 | ), 184 | ), 185 | floatingActionButton: FloatingActionButton( 186 | child: const Icon(Icons.search), 187 | onPressed: () { 188 | if (keyForm.currentState?.validate() ?? false) { 189 | final packageId = controller.text.trim(); 190 | requestPaymentStatus(packageId); 191 | getApklisInfo(); 192 | } 193 | }, 194 | ), 195 | ), 196 | ); 197 | } 198 | } 199 | --------------------------------------------------------------------------------