| @@ -0,0 +1,7 @@ | |||||
| .DS_Store | |||||
| .dart_tool/ | |||||
| .packages | |||||
| .pub/ | |||||
| build/ | |||||
| @@ -0,0 +1,10 @@ | |||||
| # This file tracks properties of this Flutter project. | |||||
| # Used by Flutter tool to assess capabilities and perform upgrades etc. | |||||
| # | |||||
| # This file should be version controlled and should not be manually edited. | |||||
| version: | |||||
| revision: c969b8af7b48bd0f4e3329ed3f112f41136d8bcd | |||||
| channel: master | |||||
| project_type: plugin | |||||
| @@ -0,0 +1,3 @@ | |||||
| ## 0.0.1 | |||||
| * TODO: Describe initial release. | |||||
| @@ -0,0 +1 @@ | |||||
| TODO: Add your license here. | |||||
| @@ -0,0 +1,8 @@ | |||||
| # myketpayment | |||||
| Add myket in app purchase for appeto team | |||||
| ## Getting Started | |||||
| add following permission to your Androidmanifest.xml | |||||
| <uses-permission android:name="ir.mservices.market.BILLING" /> | |||||
| @@ -0,0 +1,8 @@ | |||||
| *.iml | |||||
| .gradle | |||||
| /local.properties | |||||
| /.idea/workspace.xml | |||||
| /.idea/libraries | |||||
| .DS_Store | |||||
| /build | |||||
| /captures | |||||
| @@ -0,0 +1,33 @@ | |||||
| group 'ir.appeto.myketpayment' | |||||
| version '1.0' | |||||
| buildscript { | |||||
| repositories { | |||||
| google() | |||||
| jcenter() | |||||
| } | |||||
| dependencies { | |||||
| classpath 'com.android.tools.build:gradle:3.5.0' | |||||
| } | |||||
| } | |||||
| rootProject.allprojects { | |||||
| repositories { | |||||
| google() | |||||
| jcenter() | |||||
| } | |||||
| } | |||||
| apply plugin: 'com.android.library' | |||||
| android { | |||||
| compileSdkVersion 28 | |||||
| defaultConfig { | |||||
| minSdkVersion 16 | |||||
| } | |||||
| lintOptions { | |||||
| disable 'InvalidPackage' | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,4 @@ | |||||
| org.gradle.jvmargs=-Xmx1536M | |||||
| android.enableR8=true | |||||
| android.useAndroidX=true | |||||
| android.enableJetifier=true | |||||
| @@ -0,0 +1,5 @@ | |||||
| distributionBase=GRADLE_USER_HOME | |||||
| distributionPath=wrapper/dists | |||||
| zipStoreBase=GRADLE_USER_HOME | |||||
| zipStorePath=wrapper/dists | |||||
| distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip | |||||
| @@ -0,0 +1 @@ | |||||
| rootProject.name = 'myketpayment' | |||||
| @@ -0,0 +1,4 @@ | |||||
| <manifest xmlns:android="http://schemas.android.com/apk/res/android" | |||||
| package="ir.appeto.myketpayment"> | |||||
| <uses-permission android:name="ir.mservices.market.BILLING" /> | |||||
| </manifest> | |||||
| @@ -0,0 +1,185 @@ | |||||
| /* | |||||
| * Copyright (C) 2012 The Android Open Source Project | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| */ | |||||
| package com.android.vending.billing; | |||||
| import android.os.Bundle; | |||||
| /** | |||||
| * InAppBillingService is the service that provides in-app billing version 3 and beyond. | |||||
| * This service provides the following features: | |||||
| * 1. Provides a new API to get details of in-app items published for the app including | |||||
| * price, type, title and description. | |||||
| * 2. The purchase flow is synchronous and purchase information is available immediately | |||||
| * after it completes. | |||||
| * 3. Purchase information of in-app purchases is maintained within the Google Play system | |||||
| * till the purchase is consumed. | |||||
| * 4. An API to consume a purchase of an inapp item. All purchases of one-time | |||||
| * in-app items are consumable and thereafter can be purchased again. | |||||
| * 5. An API to get current purchases of the user immediately. This will not contain any | |||||
| * consumed purchases. | |||||
| * | |||||
| * All calls will give a response code with the following possible values | |||||
| * RESULT_OK = 0 - success | |||||
| * RESULT_USER_CANCELED = 1 - user pressed back or canceled a dialog | |||||
| * RESULT_BILLING_UNAVAILABLE = 3 - this billing API version is not supported for the type requested | |||||
| * RESULT_ITEM_UNAVAILABLE = 4 - requested SKU is not available for purchase | |||||
| * RESULT_DEVELOPER_ERROR = 5 - invalid arguments provided to the API | |||||
| * RESULT_ERROR = 6 - Fatal error during the API action | |||||
| * RESULT_ITEM_ALREADY_OWNED = 7 - Failure to purchase since item is already owned | |||||
| * RESULT_ITEM_NOT_OWNED = 8 - Failure to consume since item is not owned | |||||
| */ | |||||
| interface IInAppBillingService { | |||||
| /** | |||||
| * Checks support for the requested billing API version, package and in-app type. | |||||
| * Minimum API version supported by this interface is 3. | |||||
| * @param apiVersion the billing version which the app is using | |||||
| * @param packageName the package name of the calling app | |||||
| * @param type type of the in-app item being purchased "inapp" for one-time purchases | |||||
| * and "subs" for subscription. | |||||
| * @return RESULT_OK(0) on success, corresponding result code on failures | |||||
| */ | |||||
| int isBillingSupported(int apiVersion, String packageName, String type); | |||||
| /** | |||||
| * Provides details of a list of SKUs | |||||
| * Given a list of SKUs of a valid type in the skusBundle, this returns a bundle | |||||
| * with a list JSON strings containing the productId, price, title and description. | |||||
| * This API can be called with a maximum of 20 SKUs. | |||||
| * @param apiVersion billing API version that the Third-party is using | |||||
| * @param packageName the package name of the calling app | |||||
| * @param skusBundle bundle containing a StringArrayList of SKUs with key "ITEM_ID_LIST" | |||||
| * @return Bundle containing the following key-value pairs | |||||
| * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on | |||||
| * failure as listed above. | |||||
| * "DETAILS_LIST" with a StringArrayList containing purchase information | |||||
| * in JSON format similar to: | |||||
| * '{ "productId" : "exampleSku", "type" : "inapp", "price" : "$5.00", | |||||
| * "title : "Example Title", "description" : "This is an example description" }' | |||||
| */ | |||||
| Bundle getSkuDetails(int apiVersion, String packageName, String type, in Bundle skusBundle); | |||||
| /** | |||||
| * Returns a pending intent to launch the purchase flow for an in-app item by providing a SKU, | |||||
| * the type, a unique purchase token and an optional developer payload. | |||||
| * @param apiVersion billing API version that the app is using | |||||
| * @param packageName package name of the calling app | |||||
| * @param sku the SKU of the in-app item as published in the developer console | |||||
| * @param type the type of the in-app item ("inapp" for one-time purchases | |||||
| * and "subs" for subscription). | |||||
| * @param developerPayload optional argument to be sent back with the purchase information | |||||
| * @return Bundle containing the following key-value pairs | |||||
| * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on | |||||
| * failure as listed above. | |||||
| * "BUY_INTENT" - PendingIntent to start the purchase flow | |||||
| * | |||||
| * The Pending intent should be launched with startIntentSenderForResult. When purchase flow | |||||
| * has completed, the onActivityResult() will give a resultCode of OK or CANCELED. | |||||
| * If the purchase is successful, the result data will contain the following key-value pairs | |||||
| * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on | |||||
| * failure as listed above. | |||||
| * "INAPP_PURCHASE_DATA" - String in JSON format similar to | |||||
| * '{"orderId":"12999763169054705758.1371079406387615", | |||||
| * "packageName":"com.example.app", | |||||
| * "productId":"exampleSku", | |||||
| * "purchaseTime":1345678900000, | |||||
| * "purchaseToken" : "122333444455555", | |||||
| * "developerPayload":"example developer payload" }' | |||||
| * "INAPP_DATA_SIGNATURE" - String containing the signature of the purchase data that | |||||
| * was signed with the private key of the developer | |||||
| * TODO: change this to app-specific keys. | |||||
| */ | |||||
| Bundle getBuyIntent(int apiVersion, String packageName, String sku, String type, | |||||
| String developerPayload); | |||||
| /** | |||||
| * Returns the current SKUs owned by the user of the type and package name specified along with | |||||
| * purchase information and a signature of the data to be validated. | |||||
| * This will return all SKUs that have been purchased in V3 and managed items purchased using | |||||
| * V1 and V2 that have not been consumed. | |||||
| * @param apiVersion billing API version that the app is using | |||||
| * @param packageName package name of the calling app | |||||
| * @param type the type of the in-app items being requested | |||||
| * ("inapp" for one-time purchases and "subs" for subscription). | |||||
| * @param continuationToken to be set as null for the first call, if the number of owned | |||||
| * skus are too many, a continuationToken is returned in the response bundle. | |||||
| * This method can be called again with the continuation token to get the next set of | |||||
| * owned skus. | |||||
| * @return Bundle containing the following key-value pairs | |||||
| * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on | |||||
| * failure as listed above. | |||||
| * "INAPP_PURCHASE_ITEM_LIST" - StringArrayList containing the list of SKUs | |||||
| * "INAPP_PURCHASE_DATA_LIST" - StringArrayList containing the purchase information | |||||
| * "INAPP_DATA_SIGNATURE_LIST"- StringArrayList containing the signatures | |||||
| * of the purchase information | |||||
| * "INAPP_CONTINUATION_TOKEN" - String containing a continuation token for the | |||||
| * next set of in-app purchases. Only set if the | |||||
| * user has more owned skus than the current list. | |||||
| */ | |||||
| Bundle getPurchases(int apiVersion, String packageName, String type, String continuationToken); | |||||
| /** | |||||
| * Consume the last purchase of the given SKU. This will result in this item being removed | |||||
| * from all subsequent responses to getPurchases() and allow re-purchase of this item. | |||||
| * @param apiVersion billing API version that the app is using | |||||
| * @param packageName package name of the calling app | |||||
| * @param purchaseToken token in the purchase information JSON that identifies the purchase | |||||
| * to be consumed | |||||
| * @return 0 if consumption succeeded. Appropriate error values for failures. | |||||
| */ | |||||
| int consumePurchase(int apiVersion, String packageName, String purchaseToken); | |||||
| /** | |||||
| * Returns an intent to launch the purchase flow for an in-app item by providing a SKU, | |||||
| * the type, a unique purchase token and an optional developer payload. | |||||
| * @param apiVersion billing API version that the app is using | |||||
| * @param packageName package name of the calling app | |||||
| * @param sku the SKU of the in-app item as published in the developer console | |||||
| * @param type the type of the in-app item ("inapp" for one-time purchases | |||||
| * and "subs" for subscription). | |||||
| * @param developerPayload optional argument to be sent back with the purchase information | |||||
| * @return Bundle containing the following key-value pairs | |||||
| * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on | |||||
| * failure as listed above. | |||||
| * "BUY_INTENT" - Intent to start the purchase flow | |||||
| * | |||||
| * The intent should be launched with startActivityForResult. When purchase flow | |||||
| * has completed, the onActivityResult() will give a resultCode of OK or CANCELED. | |||||
| * If the purchase is successful, the result data will contain the following key-value pairs | |||||
| * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on | |||||
| * failure as listed above. | |||||
| * "INAPP_PURCHASE_DATA" - String in JSON format similar to | |||||
| * '{"orderId":"12999763169054705758.1371079406387615", | |||||
| * "packageName":"com.example.app", | |||||
| * "productId":"exampleSku", | |||||
| * "purchaseTime":1345678900000, | |||||
| * "purchaseToken" : "122333444455555", | |||||
| * "developerPayload":"example developer payload" }' | |||||
| * "INAPP_DATA_SIGNATURE" - String containing the signature of the purchase data that | |||||
| * was signed with the private key of the developer | |||||
| * TODO: change this to app-specific keys. | |||||
| */ | |||||
| Bundle getBuyIntentV2(int apiVersion, String packageName, String sku, String type, | |||||
| String developerPayload); | |||||
| /** | |||||
| * Returns the config of purchase. | |||||
| * | |||||
| * @return Bundle containing the following key-value pair | |||||
| * "INTENT_V2_SUPPORT" with boolean value | |||||
| */ | |||||
| Bundle getPurchaseConfig(int apiVersion); | |||||
| } | |||||
| @@ -0,0 +1,315 @@ | |||||
| package ir.appeto.myketpayment; | |||||
| import android.app.Activity; | |||||
| import android.content.Intent; | |||||
| import android.util.Log; | |||||
| import androidx.annotation.NonNull; | |||||
| import java.util.HashMap; | |||||
| import java.util.Map; | |||||
| import io.flutter.embedding.engine.plugins.FlutterPlugin; | |||||
| import io.flutter.embedding.engine.plugins.activity.ActivityAware; | |||||
| import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding; | |||||
| import io.flutter.plugin.common.MethodCall; | |||||
| import io.flutter.plugin.common.MethodChannel; | |||||
| import io.flutter.plugin.common.MethodChannel.MethodCallHandler; | |||||
| import io.flutter.plugin.common.MethodChannel.Result; | |||||
| import io.flutter.plugin.common.PluginRegistry; | |||||
| import io.flutter.plugin.common.PluginRegistry.Registrar; | |||||
| import ir.appeto.myketpayment.util.IabHelper; | |||||
| import ir.appeto.myketpayment.util.IabResult; | |||||
| import ir.appeto.myketpayment.util.Inventory; | |||||
| import ir.appeto.myketpayment.util.Purchase; | |||||
| /** MyketpaymentPlugin */ | |||||
| public class MyketpaymentPlugin implements FlutterPlugin, MethodCallHandler, ActivityAware { | |||||
| /// The MethodChannel that will the communication between Flutter and native Android | |||||
| /// | |||||
| /// This local reference serves to register the plugin with the Flutter Engine and unregister it | |||||
| /// when the Flutter Engine is detached from the Activity | |||||
| private MethodChannel channel; | |||||
| IabHelper mHelper; | |||||
| Result _result; | |||||
| static Activity _activity; | |||||
| private static final String TAG = "PIA"; | |||||
| static final int RC_REQUEST = 10001; | |||||
| public String payload; | |||||
| public String sku; | |||||
| public boolean consume; | |||||
| @Override | |||||
| public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) { | |||||
| channel = new MethodChannel(flutterPluginBinding.getFlutterEngine().getDartExecutor(), "myketpayment"); | |||||
| channel.setMethodCallHandler(this); | |||||
| } | |||||
| // This static function is optional and equivalent to onAttachedToEngine. It supports the old | |||||
| // pre-Flutter-1.12 Android projects. You are encouraged to continue supporting | |||||
| // plugin registration via this function while apps migrate to use the new Android APIs | |||||
| // post-flutter-1.12 via https://flutter.dev/go/android-project-migration. | |||||
| // | |||||
| // It is encouraged to share logic between onAttachedToEngine and registerWith to keep | |||||
| // them functionally equivalent. Only one of onAttachedToEngine or registerWith will be called | |||||
| // depending on the user's project. onAttachedToEngine or registerWith must both be defined | |||||
| // in the same class. | |||||
| public static void registerWith(Registrar registrar) { | |||||
| final MethodChannel channel = new MethodChannel(registrar.messenger(), "myketpayment"); | |||||
| channel.setMethodCallHandler(new MyketpaymentPlugin()); | |||||
| } | |||||
| @Override | |||||
| public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) { | |||||
| _result = result; | |||||
| if (call.method.equals("setup")) { | |||||
| setup(call, result); | |||||
| } | |||||
| else if (call.method.equals("buy")) { | |||||
| buy(call, result); | |||||
| } | |||||
| else { | |||||
| result.notImplemented(); | |||||
| } | |||||
| } | |||||
| public void setup(@NonNull MethodCall call, @NonNull Result result) { | |||||
| Log.d(TAG, call.argument("rsa").toString()); | |||||
| // Create the helper, passing it our context and the public key to verify signatures with | |||||
| String base64EncodedPublicKey = call.argument("rsa").toString(); | |||||
| Log.d(TAG, "Creating IAB helper."); | |||||
| mHelper = new IabHelper(_activity.getApplicationContext(), base64EncodedPublicKey); | |||||
| // enable debug logging (for a production application, you should set this to false). | |||||
| mHelper.enableDebugLogging(false); | |||||
| // Start setup. This is asynchronous and the specified listener | |||||
| // will be called once setup completes. | |||||
| Log.d("PIA", "Starting setup."); | |||||
| mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() { | |||||
| public void onIabSetupFinished(IabResult mResult) { | |||||
| Log.d(TAG, "Setup finished."); | |||||
| if (!mResult.isSuccess()) { | |||||
| // Oh noes, there was a problem. | |||||
| Log.d(TAG, "Problem setting up in-app billing: " + mResult); | |||||
| _result.success(false); | |||||
| return; | |||||
| } | |||||
| // Have we been disposed of in the meantime? If so, quit. | |||||
| if (mHelper == null) { | |||||
| _result.success(false); | |||||
| return; | |||||
| } | |||||
| // IAB is fully set up. Now, let's get an inventory of stuff we own. | |||||
| Log.d(TAG, "Setup successful. Querying inventory."); | |||||
| mHelper.queryInventoryAsync(mGotInventoryListener); | |||||
| } | |||||
| }); | |||||
| } | |||||
| public void buy(@NonNull MethodCall call, @NonNull Result result) { | |||||
| sku = call.argument("sku").toString(); | |||||
| payload = call.argument("payload").toString(); | |||||
| consume = call.argument("consume"); | |||||
| Log.d(TAG, "consume: " + consume); | |||||
| mHelper.flagEndAsync(); | |||||
| mHelper.launchPurchaseFlow(_activity, sku, RC_REQUEST, | |||||
| mPurchaseFinishedListener, payload); | |||||
| } | |||||
| // Listener that's called when we finish querying the items and subscriptions we own | |||||
| IabHelper.QueryInventoryFinishedListener mGotInventoryListener = new IabHelper.QueryInventoryFinishedListener() { | |||||
| @Override | |||||
| public void onQueryInventoryFinished(IabResult result, Inventory inventory) { | |||||
| Log.d(TAG, "Query inventory finished."); | |||||
| // Have we been disposed of in the meantime? If so, quit. | |||||
| if (mHelper == null) { | |||||
| _result.success(false); | |||||
| return; | |||||
| } | |||||
| // Is it a failure? | |||||
| if (result.isFailure()) { | |||||
| Log.d(TAG, "Failed to query inventory: " + result); | |||||
| _result.success(false); | |||||
| return; | |||||
| } | |||||
| Log.d(TAG, "Query inventory was successful."); | |||||
| _result.success(true); | |||||
| } | |||||
| }; | |||||
| // Callback for when a purchase is finished | |||||
| IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener() { | |||||
| public void onIabPurchaseFinished(IabResult result, Purchase purchase) { | |||||
| Log.d(TAG, "Purchase finished: " + result + ", purchase: " + purchase); | |||||
| // if we were disposed of in the meantime, quit. | |||||
| if (mHelper == null) return; | |||||
| if (result.isFailure()) { | |||||
| Map<String, Object> response = new HashMap<String, Object>(); | |||||
| response.put("purchased", false); | |||||
| Log.d(TAG, "Error purchasing: " + result); | |||||
| _result.success(response); | |||||
| return; | |||||
| } | |||||
| if (!verifyDeveloperPayload(purchase)) { | |||||
| Log.d(TAG, "Error purchasing. Authenticity verification failed."); | |||||
| return; | |||||
| } | |||||
| Log.d(TAG, "Purchase successful."); | |||||
| if(consume) { | |||||
| mHelper.consumeAsync(purchase, mConsumeFinishedListener); | |||||
| } | |||||
| else { | |||||
| returnResponse(purchase); | |||||
| } | |||||
| /*if (purchase.getSku().equals(SKU_GAS)) { | |||||
| // bought 1/4 tank of gas. So consume it. | |||||
| Log.d(TAG, "Purchase is gas. Starting gas consumption."); | |||||
| mHelper.consumeAsync(purchase, mConsumeFinishedListener); | |||||
| } | |||||
| else if (purchase.getSku().equals(SKU_PREMIUM)) { | |||||
| // bought the premium upgrade! | |||||
| Log.d(TAG, "Purchase is premium upgrade. Congratulating user."); | |||||
| } | |||||
| else if (purchase.getSku().equals(SKU_INFINITE_GAS)) { | |||||
| // bought the infinite gas subscription | |||||
| Log.d(TAG, "Infinite gas subscription purchased."); | |||||
| }*/ | |||||
| } | |||||
| }; | |||||
| // Called when consumption is complete | |||||
| IabHelper.OnConsumeFinishedListener mConsumeFinishedListener = new IabHelper.OnConsumeFinishedListener() { | |||||
| public void onConsumeFinished(Purchase purchase, IabResult result) { | |||||
| Log.d(TAG, "Consumption finished. Purchase: " + purchase + ", result: " + result); | |||||
| // if we were disposed of in the meantime, quit. | |||||
| if (mHelper == null) return; | |||||
| // We know this is the "gas" sku because it's the only one we consume, | |||||
| // so we don't check which sku was consumed. If you have more than one | |||||
| // sku, you probably should check... | |||||
| if (result.isSuccess()) { | |||||
| // successfully consumed, so we apply the effects of the item in our | |||||
| // game world's logic, which in our case means filling the gas tank a bit | |||||
| Log.d(TAG, "Consumption successful. Provisioning."); | |||||
| } | |||||
| else { | |||||
| Log.d(TAG, "Error while consuming: " + result); | |||||
| } | |||||
| Log.d(TAG, "End consumption flow."); | |||||
| returnResponse(purchase); | |||||
| } | |||||
| }; | |||||
| void returnResponse(Purchase purchase) { | |||||
| Map<String, Object> response = new HashMap<String, Object>(); | |||||
| response.put("purchased", true); | |||||
| response.put("orderId", purchase.getOrderId()); | |||||
| response.put("packageName", purchase.getPackageName()); | |||||
| response.put("sku", purchase.getSku()); | |||||
| response.put("token", purchase.getToken()); | |||||
| response.put("purchaseTime", purchase.getPurchaseTime()); | |||||
| _result.success(response); | |||||
| } | |||||
| /** Verifies the developer payload of a purchase. */ | |||||
| boolean verifyDeveloperPayload(Purchase p) { | |||||
| String payload = p.getDeveloperPayload(); | |||||
| /* | |||||
| * TODO: verify that the developer payload of the purchase is correct. It will be | |||||
| * the same one that you sent when initiating the purchase. | |||||
| * | |||||
| * WARNING: Locally generating a random string when starting a purchase and | |||||
| * verifying it here might seem like a good approach, but this will fail in the | |||||
| * case where the user purchases an item on one device and then uses your app on | |||||
| * a different device, because on the other device you will not have access to the | |||||
| * random string you originally generated. | |||||
| * | |||||
| * So a good developer payload has these characteristics: | |||||
| * | |||||
| * 1. If two different users purchase an item, the payload is different between them, | |||||
| * so that one user's purchase can't be replayed to another user. | |||||
| * | |||||
| * 2. The payload must be such that you can verify it even when the app wasn't the | |||||
| * one who initiated the purchase flow (so that items purchased by the user on | |||||
| * one device work on other devices owned by the user). | |||||
| * | |||||
| * Using your own server to store and verify developer payloads across app | |||||
| * installations is recommended. | |||||
| */ | |||||
| return true; | |||||
| } | |||||
| @Override | |||||
| public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { | |||||
| channel.setMethodCallHandler(null); | |||||
| } | |||||
| @Override | |||||
| public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) { | |||||
| _activity = binding.getActivity(); | |||||
| binding.addActivityResultListener(new PluginRegistry.ActivityResultListener() { | |||||
| @Override | |||||
| public boolean onActivityResult(int requestCode, int resultCode, Intent data) { | |||||
| Log.d(TAG, "onActivityResult(" + requestCode + "," + resultCode + "," + data); | |||||
| if (mHelper == null) return false; | |||||
| // Pass on the activity result to the helper for handling | |||||
| if (!mHelper.handleActivityResult(requestCode, resultCode, data)) { | |||||
| // not handled, so handle it ourselves (here's where you'd | |||||
| // perform any handling of activity results not related to in-app | |||||
| // billing... | |||||
| } | |||||
| else { | |||||
| Log.d(TAG, "onActivityResult handled by IABUtil."); | |||||
| } | |||||
| return true; | |||||
| } | |||||
| }); | |||||
| } | |||||
| @Override | |||||
| public void onDetachedFromActivityForConfigChanges() { | |||||
| } | |||||
| @Override | |||||
| public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) { | |||||
| } | |||||
| @Override | |||||
| public void onDetachedFromActivity() { | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,570 @@ | |||||
| // Portions copyright 2002, Google, Inc. | |||||
| // | |||||
| // Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| // you may not use this file except in compliance with the License. | |||||
| // You may obtain a copy of the License at | |||||
| // | |||||
| // http://www.apache.org/licenses/LICENSE-2.0 | |||||
| // | |||||
| // Unless required by applicable law or agreed to in writing, software | |||||
| // distributed under the License is distributed on an "AS IS" BASIS, | |||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| // See the License for the specific language governing permissions and | |||||
| // limitations under the License. | |||||
| package ir.appeto.myketpayment.util; | |||||
| // This code was converted from code at http://iharder.sourceforge.net/base64/ | |||||
| // Lots of extraneous features were removed. | |||||
| /* The original code said: | |||||
| * <p> | |||||
| * I am placing this code in the Public Domain. Do with it as you will. | |||||
| * This software comes with no guarantees or warranties but with | |||||
| * plenty of well-wishing instead! | |||||
| * Please visit | |||||
| * <a href="http://iharder.net/xmlizable">http://iharder.net/xmlizable</a> | |||||
| * periodically to check for updates or to contribute improvements. | |||||
| * </p> | |||||
| * | |||||
| * @author Robert Harder | |||||
| * @author rharder@usa.net | |||||
| * @version 1.3 | |||||
| */ | |||||
| /** | |||||
| * Base64 converter class. This code is not a complete MIME encoder; | |||||
| * it simply converts binary data to base64 data and back. | |||||
| * | |||||
| * <p>Note {@link CharBase64} is a GWT-compatible implementation of this | |||||
| * class. | |||||
| */ | |||||
| public class Base64 { | |||||
| /** Specify encoding (value is {@code true}). */ | |||||
| public final static boolean ENCODE = true; | |||||
| /** Specify decoding (value is {@code false}). */ | |||||
| public final static boolean DECODE = false; | |||||
| /** The equals sign (=) as a byte. */ | |||||
| private final static byte EQUALS_SIGN = (byte) '='; | |||||
| /** The new line character (\n) as a byte. */ | |||||
| private final static byte NEW_LINE = (byte) '\n'; | |||||
| /** | |||||
| * The 64 valid Base64 values. | |||||
| */ | |||||
| private final static byte[] ALPHABET = | |||||
| {(byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D', (byte) 'E', (byte) 'F', | |||||
| (byte) 'G', (byte) 'H', (byte) 'I', (byte) 'J', (byte) 'K', | |||||
| (byte) 'L', (byte) 'M', (byte) 'N', (byte) 'O', (byte) 'P', | |||||
| (byte) 'Q', (byte) 'R', (byte) 'S', (byte) 'T', (byte) 'U', | |||||
| (byte) 'V', (byte) 'W', (byte) 'X', (byte) 'Y', (byte) 'Z', | |||||
| (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e', | |||||
| (byte) 'f', (byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j', | |||||
| (byte) 'k', (byte) 'l', (byte) 'm', (byte) 'n', (byte) 'o', | |||||
| (byte) 'p', (byte) 'q', (byte) 'r', (byte) 's', (byte) 't', | |||||
| (byte) 'u', (byte) 'v', (byte) 'w', (byte) 'x', (byte) 'y', | |||||
| (byte) 'z', (byte) '0', (byte) '1', (byte) '2', (byte) '3', | |||||
| (byte) '4', (byte) '5', (byte) '6', (byte) '7', (byte) '8', | |||||
| (byte) '9', (byte) '+', (byte) '/'}; | |||||
| /** | |||||
| * The 64 valid web safe Base64 values. | |||||
| */ | |||||
| private final static byte[] WEBSAFE_ALPHABET = | |||||
| {(byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D', (byte) 'E', (byte) 'F', | |||||
| (byte) 'G', (byte) 'H', (byte) 'I', (byte) 'J', (byte) 'K', | |||||
| (byte) 'L', (byte) 'M', (byte) 'N', (byte) 'O', (byte) 'P', | |||||
| (byte) 'Q', (byte) 'R', (byte) 'S', (byte) 'T', (byte) 'U', | |||||
| (byte) 'V', (byte) 'W', (byte) 'X', (byte) 'Y', (byte) 'Z', | |||||
| (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e', | |||||
| (byte) 'f', (byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j', | |||||
| (byte) 'k', (byte) 'l', (byte) 'm', (byte) 'n', (byte) 'o', | |||||
| (byte) 'p', (byte) 'q', (byte) 'r', (byte) 's', (byte) 't', | |||||
| (byte) 'u', (byte) 'v', (byte) 'w', (byte) 'x', (byte) 'y', | |||||
| (byte) 'z', (byte) '0', (byte) '1', (byte) '2', (byte) '3', | |||||
| (byte) '4', (byte) '5', (byte) '6', (byte) '7', (byte) '8', | |||||
| (byte) '9', (byte) '-', (byte) '_'}; | |||||
| /** | |||||
| * Translates a Base64 value to either its 6-bit reconstruction value | |||||
| * or a negative number indicating some other meaning. | |||||
| **/ | |||||
| private final static byte[] DECODABET = {-9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 0 - 8 | |||||
| -5, -5, // Whitespace: Tab and Linefeed | |||||
| -9, -9, // Decimal 11 - 12 | |||||
| -5, // Whitespace: Carriage Return | |||||
| -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 14 - 26 | |||||
| -9, -9, -9, -9, -9, // Decimal 27 - 31 | |||||
| -5, // Whitespace: Space | |||||
| -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 33 - 42 | |||||
| 62, // Plus sign at decimal 43 | |||||
| -9, -9, -9, // Decimal 44 - 46 | |||||
| 63, // Slash at decimal 47 | |||||
| 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // Numbers zero through nine | |||||
| -9, -9, -9, // Decimal 58 - 60 | |||||
| -1, // Equals sign at decimal 61 | |||||
| -9, -9, -9, // Decimal 62 - 64 | |||||
| 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, // Letters 'A' through 'N' | |||||
| 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // Letters 'O' through 'Z' | |||||
| -9, -9, -9, -9, -9, -9, // Decimal 91 - 96 | |||||
| 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, // Letters 'a' through 'm' | |||||
| 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // Letters 'n' through 'z' | |||||
| -9, -9, -9, -9, -9 // Decimal 123 - 127 | |||||
| /* ,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 128 - 139 | |||||
| -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152 | |||||
| -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165 | |||||
| -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178 | |||||
| -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191 | |||||
| -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204 | |||||
| -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217 | |||||
| -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230 | |||||
| -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243 | |||||
| -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */ | |||||
| }; | |||||
| /** The web safe decodabet */ | |||||
| private final static byte[] WEBSAFE_DECODABET = | |||||
| {-9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 0 - 8 | |||||
| -5, -5, // Whitespace: Tab and Linefeed | |||||
| -9, -9, // Decimal 11 - 12 | |||||
| -5, // Whitespace: Carriage Return | |||||
| -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 14 - 26 | |||||
| -9, -9, -9, -9, -9, // Decimal 27 - 31 | |||||
| -5, // Whitespace: Space | |||||
| -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 33 - 44 | |||||
| 62, // Dash '-' sign at decimal 45 | |||||
| -9, -9, // Decimal 46-47 | |||||
| 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // Numbers zero through nine | |||||
| -9, -9, -9, // Decimal 58 - 60 | |||||
| -1, // Equals sign at decimal 61 | |||||
| -9, -9, -9, // Decimal 62 - 64 | |||||
| 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, // Letters 'A' through 'N' | |||||
| 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // Letters 'O' through 'Z' | |||||
| -9, -9, -9, -9, // Decimal 91-94 | |||||
| 63, // Underscore '_' at decimal 95 | |||||
| -9, // Decimal 96 | |||||
| 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, // Letters 'a' through 'm' | |||||
| 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // Letters 'n' through 'z' | |||||
| -9, -9, -9, -9, -9 // Decimal 123 - 127 | |||||
| /* ,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 128 - 139 | |||||
| -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152 | |||||
| -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165 | |||||
| -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178 | |||||
| -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191 | |||||
| -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204 | |||||
| -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217 | |||||
| -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230 | |||||
| -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243 | |||||
| -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */ | |||||
| }; | |||||
| // Indicates white space in encoding | |||||
| private final static byte WHITE_SPACE_ENC = -5; | |||||
| // Indicates equals sign in encoding | |||||
| private final static byte EQUALS_SIGN_ENC = -1; | |||||
| /** Defeats instantiation. */ | |||||
| private Base64() { | |||||
| } | |||||
| /* ******** E N C O D I N G M E T H O D S ******** */ | |||||
| /** | |||||
| * Encodes up to three bytes of the array <var>source</var> | |||||
| * and writes the resulting four Base64 bytes to <var>destination</var>. | |||||
| * The source and destination arrays can be manipulated | |||||
| * anywhere along their length by specifying | |||||
| * <var>srcOffset</var> and <var>destOffset</var>. | |||||
| * This method does not check to make sure your arrays | |||||
| * are large enough to accommodate <var>srcOffset</var> + 3 for | |||||
| * the <var>source</var> array or <var>destOffset</var> + 4 for | |||||
| * the <var>destination</var> array. | |||||
| * The actual number of significant bytes in your array is | |||||
| * given by <var>numSigBytes</var>. | |||||
| * | |||||
| * @param source the array to convert | |||||
| * @param srcOffset the index where conversion begins | |||||
| * @param numSigBytes the number of significant bytes in your array | |||||
| * @param destination the array to hold the conversion | |||||
| * @param destOffset the index where output will be put | |||||
| * @param alphabet is the encoding alphabet | |||||
| * @return the <var>destination</var> array | |||||
| * @since 1.3 | |||||
| */ | |||||
| private static byte[] encode3to4(byte[] source, int srcOffset, | |||||
| int numSigBytes, byte[] destination, int destOffset, byte[] alphabet) { | |||||
| // 1 2 3 | |||||
| // 01234567890123456789012345678901 Bit position | |||||
| // --------000000001111111122222222 Array position from threeBytes | |||||
| // --------| || || || | Six bit groups to index alphabet | |||||
| // >>18 >>12 >> 6 >> 0 Right shift necessary | |||||
| // 0x3f 0x3f 0x3f Additional AND | |||||
| // Create buffer with zero-padding if there are only one or two | |||||
| // significant bytes passed in the array. | |||||
| // We have to shift left 24 in order to flush out the 1's that appear | |||||
| // when Java treats a value as negative that is cast from a byte to an int. | |||||
| int inBuff = | |||||
| (numSigBytes > 0 ? ((source[srcOffset] << 24) >>> 8) : 0) | |||||
| | (numSigBytes > 1 ? ((source[srcOffset + 1] << 24) >>> 16) : 0) | |||||
| | (numSigBytes > 2 ? ((source[srcOffset + 2] << 24) >>> 24) : 0); | |||||
| switch (numSigBytes) { | |||||
| case 3: | |||||
| destination[destOffset] = alphabet[(inBuff >>> 18)]; | |||||
| destination[destOffset + 1] = alphabet[(inBuff >>> 12) & 0x3f]; | |||||
| destination[destOffset + 2] = alphabet[(inBuff >>> 6) & 0x3f]; | |||||
| destination[destOffset + 3] = alphabet[(inBuff) & 0x3f]; | |||||
| return destination; | |||||
| case 2: | |||||
| destination[destOffset] = alphabet[(inBuff >>> 18)]; | |||||
| destination[destOffset + 1] = alphabet[(inBuff >>> 12) & 0x3f]; | |||||
| destination[destOffset + 2] = alphabet[(inBuff >>> 6) & 0x3f]; | |||||
| destination[destOffset + 3] = EQUALS_SIGN; | |||||
| return destination; | |||||
| case 1: | |||||
| destination[destOffset] = alphabet[(inBuff >>> 18)]; | |||||
| destination[destOffset + 1] = alphabet[(inBuff >>> 12) & 0x3f]; | |||||
| destination[destOffset + 2] = EQUALS_SIGN; | |||||
| destination[destOffset + 3] = EQUALS_SIGN; | |||||
| return destination; | |||||
| default: | |||||
| return destination; | |||||
| } // end switch | |||||
| } // end encode3to4 | |||||
| /** | |||||
| * Encodes a byte array into Base64 notation. | |||||
| * Equivalent to calling | |||||
| * {@code encodeBytes(source, 0, source.length)} | |||||
| * | |||||
| * @param source The data to convert | |||||
| * @since 1.4 | |||||
| */ | |||||
| public static String encode(byte[] source) { | |||||
| return encode(source, 0, source.length, ALPHABET, true); | |||||
| } | |||||
| /** | |||||
| * Encodes a byte array into web safe Base64 notation. | |||||
| * | |||||
| * @param source The data to convert | |||||
| * @param doPadding is {@code true} to pad result with '=' chars | |||||
| * if it does not fall on 3 byte boundaries | |||||
| */ | |||||
| public static String encodeWebSafe(byte[] source, boolean doPadding) { | |||||
| return encode(source, 0, source.length, WEBSAFE_ALPHABET, doPadding); | |||||
| } | |||||
| /** | |||||
| * Encodes a byte array into Base64 notation. | |||||
| * | |||||
| * @param source the data to convert | |||||
| * @param off offset in array where conversion should begin | |||||
| * @param len length of data to convert | |||||
| * @param alphabet the encoding alphabet | |||||
| * @param doPadding is {@code true} to pad result with '=' chars | |||||
| * if it does not fall on 3 byte boundaries | |||||
| * @since 1.4 | |||||
| */ | |||||
| public static String encode(byte[] source, int off, int len, byte[] alphabet, | |||||
| boolean doPadding) { | |||||
| byte[] outBuff = encode(source, off, len, alphabet, Integer.MAX_VALUE); | |||||
| int outLen = outBuff.length; | |||||
| // If doPadding is false, set length to truncate '=' | |||||
| // padding characters | |||||
| while (doPadding == false && outLen > 0) { | |||||
| if (outBuff[outLen - 1] != '=') { | |||||
| break; | |||||
| } | |||||
| outLen -= 1; | |||||
| } | |||||
| return new String(outBuff, 0, outLen); | |||||
| } | |||||
| /** | |||||
| * Encodes a byte array into Base64 notation. | |||||
| * | |||||
| * @param source the data to convert | |||||
| * @param off offset in array where conversion should begin | |||||
| * @param len length of data to convert | |||||
| * @param alphabet is the encoding alphabet | |||||
| * @param maxLineLength maximum length of one line. | |||||
| * @return the BASE64-encoded byte array | |||||
| */ | |||||
| public static byte[] encode(byte[] source, int off, int len, byte[] alphabet, | |||||
| int maxLineLength) { | |||||
| int lenDiv3 = (len + 2) / 3; // ceil(len / 3) | |||||
| int len43 = lenDiv3 * 4; | |||||
| byte[] outBuff = new byte[len43 // Main 4:3 | |||||
| + (len43 / maxLineLength)]; // New lines | |||||
| int d = 0; | |||||
| int e = 0; | |||||
| int len2 = len - 2; | |||||
| int lineLength = 0; | |||||
| for (; d < len2; d += 3, e += 4) { | |||||
| // The following block of code is the same as | |||||
| // encode3to4( source, d + off, 3, outBuff, e, alphabet ); | |||||
| // but inlined for faster encoding (~20% improvement) | |||||
| int inBuff = | |||||
| ((source[d + off] << 24) >>> 8) | |||||
| | ((source[d + 1 + off] << 24) >>> 16) | |||||
| | ((source[d + 2 + off] << 24) >>> 24); | |||||
| outBuff[e] = alphabet[(inBuff >>> 18)]; | |||||
| outBuff[e + 1] = alphabet[(inBuff >>> 12) & 0x3f]; | |||||
| outBuff[e + 2] = alphabet[(inBuff >>> 6) & 0x3f]; | |||||
| outBuff[e + 3] = alphabet[(inBuff) & 0x3f]; | |||||
| lineLength += 4; | |||||
| if (lineLength == maxLineLength) { | |||||
| outBuff[e + 4] = NEW_LINE; | |||||
| e++; | |||||
| lineLength = 0; | |||||
| } // end if: end of line | |||||
| } // end for: each piece of array | |||||
| if (d < len) { | |||||
| encode3to4(source, d + off, len - d, outBuff, e, alphabet); | |||||
| lineLength += 4; | |||||
| if (lineLength == maxLineLength) { | |||||
| // Add a last newline | |||||
| outBuff[e + 4] = NEW_LINE; | |||||
| e++; | |||||
| } | |||||
| e += 4; | |||||
| } | |||||
| assert (e == outBuff.length); | |||||
| return outBuff; | |||||
| } | |||||
| /* ******** D E C O D I N G M E T H O D S ******** */ | |||||
| /** | |||||
| * Decodes four bytes from array <var>source</var> | |||||
| * and writes the resulting bytes (up to three of them) | |||||
| * to <var>destination</var>. | |||||
| * The source and destination arrays can be manipulated | |||||
| * anywhere along their length by specifying | |||||
| * <var>srcOffset</var> and <var>destOffset</var>. | |||||
| * This method does not check to make sure your arrays | |||||
| * are large enough to accommodate <var>srcOffset</var> + 4 for | |||||
| * the <var>source</var> array or <var>destOffset</var> + 3 for | |||||
| * the <var>destination</var> array. | |||||
| * This method returns the actual number of bytes that | |||||
| * were converted from the Base64 encoding. | |||||
| * | |||||
| * | |||||
| * @param source the array to convert | |||||
| * @param srcOffset the index where conversion begins | |||||
| * @param destination the array to hold the conversion | |||||
| * @param destOffset the index where output will be put | |||||
| * @param decodabet the decodabet for decoding Base64 content | |||||
| * @return the number of decoded bytes converted | |||||
| * @since 1.3 | |||||
| */ | |||||
| private static int decode4to3(byte[] source, int srcOffset, | |||||
| byte[] destination, int destOffset, byte[] decodabet) { | |||||
| // Example: Dk== | |||||
| if (source[srcOffset + 2] == EQUALS_SIGN) { | |||||
| int outBuff = | |||||
| ((decodabet[source[srcOffset]] << 24) >>> 6) | |||||
| | ((decodabet[source[srcOffset + 1]] << 24) >>> 12); | |||||
| destination[destOffset] = (byte) (outBuff >>> 16); | |||||
| return 1; | |||||
| } else if (source[srcOffset + 3] == EQUALS_SIGN) { | |||||
| // Example: DkL= | |||||
| int outBuff = | |||||
| ((decodabet[source[srcOffset]] << 24) >>> 6) | |||||
| | ((decodabet[source[srcOffset + 1]] << 24) >>> 12) | |||||
| | ((decodabet[source[srcOffset + 2]] << 24) >>> 18); | |||||
| destination[destOffset] = (byte) (outBuff >>> 16); | |||||
| destination[destOffset + 1] = (byte) (outBuff >>> 8); | |||||
| return 2; | |||||
| } else { | |||||
| // Example: DkLE | |||||
| int outBuff = | |||||
| ((decodabet[source[srcOffset]] << 24) >>> 6) | |||||
| | ((decodabet[source[srcOffset + 1]] << 24) >>> 12) | |||||
| | ((decodabet[source[srcOffset + 2]] << 24) >>> 18) | |||||
| | ((decodabet[source[srcOffset + 3]] << 24) >>> 24); | |||||
| destination[destOffset] = (byte) (outBuff >> 16); | |||||
| destination[destOffset + 1] = (byte) (outBuff >> 8); | |||||
| destination[destOffset + 2] = (byte) (outBuff); | |||||
| return 3; | |||||
| } | |||||
| } // end decodeToBytes | |||||
| /** | |||||
| * Decodes data from Base64 notation. | |||||
| * | |||||
| * @param s the string to decode (decoded in default encoding) | |||||
| * @return the decoded data | |||||
| * @since 1.4 | |||||
| */ | |||||
| public static byte[] decode(String s) throws Base64DecoderException { | |||||
| byte[] bytes = s.getBytes(); | |||||
| return decode(bytes, 0, bytes.length); | |||||
| } | |||||
| /** | |||||
| * Decodes data from web safe Base64 notation. | |||||
| * Web safe encoding uses '-' instead of '+', '_' instead of '/' | |||||
| * | |||||
| * @param s the string to decode (decoded in default encoding) | |||||
| * @return the decoded data | |||||
| */ | |||||
| public static byte[] decodeWebSafe(String s) throws Base64DecoderException { | |||||
| byte[] bytes = s.getBytes(); | |||||
| return decodeWebSafe(bytes, 0, bytes.length); | |||||
| } | |||||
| /** | |||||
| * Decodes Base64 content in byte array format and returns | |||||
| * the decoded byte array. | |||||
| * | |||||
| * @param source The Base64 encoded data | |||||
| * @return decoded data | |||||
| * @since 1.3 | |||||
| * @throws Base64DecoderException | |||||
| */ | |||||
| public static byte[] decode(byte[] source) throws Base64DecoderException { | |||||
| return decode(source, 0, source.length); | |||||
| } | |||||
| /** | |||||
| * Decodes web safe Base64 content in byte array format and returns | |||||
| * the decoded data. | |||||
| * Web safe encoding uses '-' instead of '+', '_' instead of '/' | |||||
| * | |||||
| * @param source the string to decode (decoded in default encoding) | |||||
| * @return the decoded data | |||||
| */ | |||||
| public static byte[] decodeWebSafe(byte[] source) | |||||
| throws Base64DecoderException { | |||||
| return decodeWebSafe(source, 0, source.length); | |||||
| } | |||||
| /** | |||||
| * Decodes Base64 content in byte array format and returns | |||||
| * the decoded byte array. | |||||
| * | |||||
| * @param source the Base64 encoded data | |||||
| * @param off the offset of where to begin decoding | |||||
| * @param len the length of characters to decode | |||||
| * @return decoded data | |||||
| * @since 1.3 | |||||
| * @throws Base64DecoderException | |||||
| */ | |||||
| public static byte[] decode(byte[] source, int off, int len) | |||||
| throws Base64DecoderException { | |||||
| return decode(source, off, len, DECODABET); | |||||
| } | |||||
| /** | |||||
| * Decodes web safe Base64 content in byte array format and returns | |||||
| * the decoded byte array. | |||||
| * Web safe encoding uses '-' instead of '+', '_' instead of '/' | |||||
| * | |||||
| * @param source the Base64 encoded data | |||||
| * @param off the offset of where to begin decoding | |||||
| * @param len the length of characters to decode | |||||
| * @return decoded data | |||||
| */ | |||||
| public static byte[] decodeWebSafe(byte[] source, int off, int len) | |||||
| throws Base64DecoderException { | |||||
| return decode(source, off, len, WEBSAFE_DECODABET); | |||||
| } | |||||
| /** | |||||
| * Decodes Base64 content using the supplied decodabet and returns | |||||
| * the decoded byte array. | |||||
| * | |||||
| * @param source the Base64 encoded data | |||||
| * @param off the offset of where to begin decoding | |||||
| * @param len the length of characters to decode | |||||
| * @param decodabet the decodabet for decoding Base64 content | |||||
| * @return decoded data | |||||
| */ | |||||
| public static byte[] decode(byte[] source, int off, int len, byte[] decodabet) | |||||
| throws Base64DecoderException { | |||||
| int len34 = len * 3 / 4; | |||||
| byte[] outBuff = new byte[2 + len34]; // Upper limit on size of output | |||||
| int outBuffPosn = 0; | |||||
| byte[] b4 = new byte[4]; | |||||
| int b4Posn = 0; | |||||
| int i = 0; | |||||
| byte sbiCrop = 0; | |||||
| byte sbiDecode = 0; | |||||
| for (i = 0; i < len; i++) { | |||||
| sbiCrop = (byte) (source[i + off] & 0x7f); // Only the low seven bits | |||||
| sbiDecode = decodabet[sbiCrop]; | |||||
| if (sbiDecode >= WHITE_SPACE_ENC) { // White space Equals sign or better | |||||
| if (sbiDecode >= EQUALS_SIGN_ENC) { | |||||
| // An equals sign (for padding) must not occur at position 0 or 1 | |||||
| // and must be the last byte[s] in the encoded value | |||||
| if (sbiCrop == EQUALS_SIGN) { | |||||
| int bytesLeft = len - i; | |||||
| byte lastByte = (byte) (source[len - 1 + off] & 0x7f); | |||||
| if (b4Posn == 0 || b4Posn == 1) { | |||||
| throw new Base64DecoderException( | |||||
| "invalid padding byte '=' at byte offset " + i); | |||||
| } else if ((b4Posn == 3 && bytesLeft > 2) | |||||
| || (b4Posn == 4 && bytesLeft > 1)) { | |||||
| throw new Base64DecoderException( | |||||
| "padding byte '=' falsely signals end of encoded value " | |||||
| + "at offset " + i); | |||||
| } else if (lastByte != EQUALS_SIGN && lastByte != NEW_LINE) { | |||||
| throw new Base64DecoderException( | |||||
| "encoded value has invalid trailing byte"); | |||||
| } | |||||
| break; | |||||
| } | |||||
| b4[b4Posn++] = sbiCrop; | |||||
| if (b4Posn == 4) { | |||||
| outBuffPosn += decode4to3(b4, 0, outBuff, outBuffPosn, decodabet); | |||||
| b4Posn = 0; | |||||
| } | |||||
| } | |||||
| } else { | |||||
| throw new Base64DecoderException("Bad Base64 input character at " + i | |||||
| + ": " + source[i + off] + "(decimal)"); | |||||
| } | |||||
| } | |||||
| // Because web safe encoding allows non padding base64 encodes, we | |||||
| // need to pad the rest of the b4 buffer with equal signs when | |||||
| // b4Posn != 0. There can be at most 2 equal signs at the end of | |||||
| // four characters, so the b4 buffer must have two or three | |||||
| // characters. This also catches the case where the input is | |||||
| // padded with EQUALS_SIGN | |||||
| if (b4Posn != 0) { | |||||
| if (b4Posn == 1) { | |||||
| throw new Base64DecoderException("single trailing character at offset " | |||||
| + (len - 1)); | |||||
| } | |||||
| b4[b4Posn++] = EQUALS_SIGN; | |||||
| outBuffPosn += decode4to3(b4, 0, outBuff, outBuffPosn, decodabet); | |||||
| } | |||||
| byte[] out = new byte[outBuffPosn]; | |||||
| System.arraycopy(outBuff, 0, out, 0, outBuffPosn); | |||||
| return out; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,32 @@ | |||||
| // Copyright 2002, Google, Inc. | |||||
| // | |||||
| // Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| // you may not use this file except in compliance with the License. | |||||
| // You may obtain a copy of the License at | |||||
| // | |||||
| // http://www.apache.org/licenses/LICENSE-2.0 | |||||
| // | |||||
| // Unless required by applicable law or agreed to in writing, software | |||||
| // distributed under the License is distributed on an "AS IS" BASIS, | |||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| // See the License for the specific language governing permissions and | |||||
| // limitations under the License. | |||||
| package ir.appeto.myketpayment.util; | |||||
| /** | |||||
| * Exception thrown when encountering an invalid Base64 input character. | |||||
| * | |||||
| * @author nelson | |||||
| */ | |||||
| public class Base64DecoderException extends Exception { | |||||
| public Base64DecoderException() { | |||||
| super(); | |||||
| } | |||||
| public Base64DecoderException(String s) { | |||||
| super(s); | |||||
| } | |||||
| private static final long serialVersionUID = 1L; | |||||
| } | |||||
| @@ -0,0 +1,43 @@ | |||||
| /* Copyright (c) 2012 Google Inc. | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| */ | |||||
| package ir.appeto.myketpayment.util; | |||||
| /** | |||||
| * Exception thrown when something went wrong with in-app billing. | |||||
| * An IabException has an associated IabResult (an error). | |||||
| * To get the IAB result that caused this exception to be thrown, | |||||
| * call {@link #getResult()}. | |||||
| */ | |||||
| public class IabException extends Exception { | |||||
| IabResult mResult; | |||||
| public IabException(IabResult r) { | |||||
| this(r, null); | |||||
| } | |||||
| public IabException(int response, String message) { | |||||
| this(new IabResult(response, message)); | |||||
| } | |||||
| public IabException(IabResult r, Exception cause) { | |||||
| super(r.getMessage(), cause); | |||||
| mResult = r; | |||||
| } | |||||
| public IabException(int response, String message, Exception cause) { | |||||
| this(new IabResult(response, message), cause); | |||||
| } | |||||
| /** Returns the IAB result (error) that this exception signals. */ | |||||
| public IabResult getResult() { return mResult; } | |||||
| } | |||||
| @@ -0,0 +1,45 @@ | |||||
| /* Copyright (c) 2012 Google Inc. | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| */ | |||||
| package ir.appeto.myketpayment.util; | |||||
| /** | |||||
| * Represents the result of an in-app billing operation. | |||||
| * A result is composed of a response code (an integer) and possibly a | |||||
| * message (String). You can get those by calling | |||||
| * {@link #getResponse} and {@link #getMessage()}, respectively. You | |||||
| * can also inquire whether a result is a success or a failure by | |||||
| * calling {@link #isSuccess()} and {@link #isFailure()}. | |||||
| */ | |||||
| public class IabResult { | |||||
| int mResponse; | |||||
| String mMessage; | |||||
| public IabResult(int response, String message) { | |||||
| mResponse = response; | |||||
| if (message == null || message.trim().length() == 0) { | |||||
| mMessage = IabHelper.getResponseDesc(response); | |||||
| } | |||||
| else { | |||||
| mMessage = message + " (response: " + IabHelper.getResponseDesc(response) + ")"; | |||||
| } | |||||
| } | |||||
| public int getResponse() { return mResponse; } | |||||
| public String getMessage() { return mMessage; } | |||||
| public boolean isSuccess() { return mResponse == IabHelper.BILLING_RESPONSE_RESULT_OK; } | |||||
| public boolean isFailure() { return !isSuccess(); } | |||||
| public String toString() { return "IabResult: " + getMessage(); } | |||||
| } | |||||
| @@ -0,0 +1,113 @@ | |||||
| /* Copyright (c) 2012 Google Inc. | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| */ | |||||
| package ir.appeto.myketpayment.util; | |||||
| import java.util.ArrayList; | |||||
| import java.util.HashMap; | |||||
| import java.util.List; | |||||
| import java.util.Map; | |||||
| /** | |||||
| * Represents a block of information about in-app items. | |||||
| * An Inventory is returned by such methods as {@link IabHelper#queryInventory}. | |||||
| */ | |||||
| public class Inventory { | |||||
| Map<String, SkuDetails> mSkuMap = new HashMap<String, SkuDetails>(); | |||||
| Map<String, Purchase> mPurchaseMap = new HashMap<String, Purchase>(); | |||||
| Inventory() { | |||||
| } | |||||
| /** | |||||
| * Returns the listing details for an in-app product. | |||||
| */ | |||||
| public SkuDetails getSkuDetails(String sku) { | |||||
| return mSkuMap.get(sku); | |||||
| } | |||||
| /** | |||||
| * Returns purchase information for a given product, or null if there is no purchase. | |||||
| */ | |||||
| public Purchase getPurchase(String sku) { | |||||
| return mPurchaseMap.get(sku); | |||||
| } | |||||
| /** | |||||
| * Returns whether or not there exists a purchase of the given product. | |||||
| */ | |||||
| public boolean hasPurchase(String sku) { | |||||
| return mPurchaseMap.containsKey(sku); | |||||
| } | |||||
| /** | |||||
| * Return whether or not details about the given product are available. | |||||
| */ | |||||
| public boolean hasDetails(String sku) { | |||||
| return mSkuMap.containsKey(sku); | |||||
| } | |||||
| /** | |||||
| * Erase a purchase (locally) from the inventory, given its product ID. This just | |||||
| * modifies the Inventory object locally and has no effect on the server! This is | |||||
| * useful when you have an existing Inventory object which you know to be up to date, | |||||
| * and you have just consumed an item successfully, which means that erasing its | |||||
| * purchase data from the Inventory you already have is quicker than querying for | |||||
| * a new Inventory. | |||||
| */ | |||||
| public void erasePurchase(String sku) { | |||||
| if (mPurchaseMap.containsKey(sku)) mPurchaseMap.remove(sku); | |||||
| } | |||||
| /** | |||||
| * Returns a list of all owned product IDs. | |||||
| */ | |||||
| List<String> getAllOwnedSkus() { | |||||
| return new ArrayList<String>(mPurchaseMap.keySet()); | |||||
| } | |||||
| /** | |||||
| * Returns a list of all owned product IDs of a given type | |||||
| */ | |||||
| List<String> getAllOwnedSkus(String itemType) { | |||||
| List<String> result = new ArrayList<String>(); | |||||
| for (Purchase p : mPurchaseMap.values()) { | |||||
| if (p.getItemType().equals(itemType)) result.add(p.getSku()); | |||||
| } | |||||
| return result; | |||||
| } | |||||
| /** | |||||
| * Returns a list of all purchases. | |||||
| */ | |||||
| public List<Purchase> getAllPurchases() { | |||||
| return new ArrayList<Purchase>(mPurchaseMap.values()); | |||||
| } | |||||
| /** | |||||
| * Returns a list of all products. | |||||
| */ | |||||
| public List<SkuDetails> getAllProducts() { | |||||
| return new ArrayList<SkuDetails>(mSkuMap.values()); | |||||
| } | |||||
| void addSkuDetails(SkuDetails d) { | |||||
| mSkuMap.put(d.getSku(), d); | |||||
| } | |||||
| public void addPurchase(Purchase p) { | |||||
| mPurchaseMap.put(p.getSku(), p); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,63 @@ | |||||
| /* Copyright (c) 2012 Google Inc. | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| */ | |||||
| package ir.appeto.myketpayment.util; | |||||
| import org.json.JSONException; | |||||
| import org.json.JSONObject; | |||||
| /** | |||||
| * Represents an in-app billing purchase. | |||||
| */ | |||||
| public class Purchase { | |||||
| String mItemType; // ITEM_TYPE_INAPP or ITEM_TYPE_SUBS | |||||
| String mOrderId; | |||||
| String mPackageName; | |||||
| String mSku; | |||||
| long mPurchaseTime; | |||||
| int mPurchaseState; | |||||
| String mDeveloperPayload; | |||||
| String mToken; | |||||
| String mOriginalJson; | |||||
| String mSignature; | |||||
| public Purchase(String itemType, String jsonPurchaseInfo, String signature) throws JSONException { | |||||
| mItemType = itemType; | |||||
| mOriginalJson = jsonPurchaseInfo; | |||||
| JSONObject o = new JSONObject(mOriginalJson); | |||||
| mOrderId = o.optString("orderId"); | |||||
| mPackageName = o.optString("packageName"); | |||||
| mSku = o.optString("productId"); | |||||
| mPurchaseTime = o.optLong("purchaseTime"); | |||||
| mPurchaseState = o.optInt("purchaseState"); | |||||
| mDeveloperPayload = o.optString("developerPayload"); | |||||
| mToken = o.optString("token", o.optString("purchaseToken")); | |||||
| mSignature = signature; | |||||
| } | |||||
| public String getItemType() { return mItemType; } | |||||
| public String getOrderId() { return mOrderId; } | |||||
| public String getPackageName() { return mPackageName; } | |||||
| public String getSku() { return mSku; } | |||||
| public long getPurchaseTime() { return mPurchaseTime; } | |||||
| public int getPurchaseState() { return mPurchaseState; } | |||||
| public String getDeveloperPayload() { return mDeveloperPayload; } | |||||
| public String getToken() { return mToken; } | |||||
| public String getOriginalJson() { return mOriginalJson; } | |||||
| public String getSignature() { return mSignature; } | |||||
| @Override | |||||
| public String toString() { return "PurchaseInfo(type:" + mItemType + "):" + mOriginalJson; } | |||||
| } | |||||
| @@ -0,0 +1,123 @@ | |||||
| /* Copyright (c) 2012 Google Inc. | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| */ | |||||
| package ir.appeto.myketpayment.util; | |||||
| import android.text.TextUtils; | |||||
| import android.util.Log; | |||||
| import org.json.JSONException; | |||||
| import org.json.JSONObject; | |||||
| import java.security.InvalidKeyException; | |||||
| import java.security.KeyFactory; | |||||
| import java.security.NoSuchAlgorithmException; | |||||
| import java.security.PublicKey; | |||||
| import java.security.Signature; | |||||
| import java.security.SignatureException; | |||||
| import java.security.spec.InvalidKeySpecException; | |||||
| import java.security.spec.X509EncodedKeySpec; | |||||
| /** | |||||
| * Security-related methods. For a secure implementation, all of this code | |||||
| * should be implemented on a server that communicates with the | |||||
| * application on the device. For the sake of simplicity and clarity of this | |||||
| * example, this code is included here and is executed on the device. If you | |||||
| * must verify the purchases on the phone, you should obfuscate this code to | |||||
| * make it harder for an attacker to replace the code with stubs that treat all | |||||
| * purchases as verified. | |||||
| */ | |||||
| public class Security { | |||||
| private static final String TAG = "IABUtil/Security"; | |||||
| private static final String KEY_FACTORY_ALGORITHM = "RSA"; | |||||
| private static final String SIGNATURE_ALGORITHM = "SHA1withRSA"; | |||||
| /** | |||||
| * Verifies that the data was signed with the given signature, and returns | |||||
| * the verified purchase. The data is in JSON format and signed | |||||
| * with a private key. The data also contains the {@link PurchaseState} | |||||
| * and product ID of the purchase. | |||||
| * @param base64PublicKey the base64-encoded public key to use for verifying. | |||||
| * @param signedData the signed JSON string (signed, not encrypted) | |||||
| * @param signature the signature for the data, signed with the private key | |||||
| */ | |||||
| public static boolean verifyPurchase(String base64PublicKey, String signedData, String signature) { | |||||
| if (TextUtils.isEmpty(signedData) || TextUtils.isEmpty(base64PublicKey) || | |||||
| TextUtils.isEmpty(signature)) { | |||||
| Log.e(TAG, "Purchase verification failed: missing data."); | |||||
| return false; | |||||
| } | |||||
| PublicKey key = Security.generatePublicKey(base64PublicKey); | |||||
| return Security.verify(key, signedData, signature); | |||||
| } | |||||
| /** | |||||
| * Generates a PublicKey instance from a string containing the | |||||
| * Base64-encoded public key. | |||||
| * | |||||
| * @param encodedPublicKey Base64-encoded public key | |||||
| * @throws IllegalArgumentException if encodedPublicKey is invalid | |||||
| */ | |||||
| public static PublicKey generatePublicKey(String encodedPublicKey) { | |||||
| try { | |||||
| byte[] decodedKey = Base64.decode(encodedPublicKey); | |||||
| KeyFactory keyFactory = KeyFactory.getInstance(KEY_FACTORY_ALGORITHM); | |||||
| return keyFactory.generatePublic(new X509EncodedKeySpec(decodedKey)); | |||||
| } catch (NoSuchAlgorithmException e) { | |||||
| throw new RuntimeException(e); | |||||
| } catch (InvalidKeySpecException e) { | |||||
| Log.e(TAG, "Invalid key specification."); | |||||
| throw new IllegalArgumentException(e); | |||||
| } catch (Base64DecoderException e) { | |||||
| Log.e(TAG, "Base64 decoding failed."); | |||||
| throw new IllegalArgumentException(e); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Verifies that the signature from the server matches the computed | |||||
| * signature on the data. Returns true if the data is correctly signed. | |||||
| * | |||||
| * @param publicKey public key associated with the developer account | |||||
| * @param signedData signed data from server | |||||
| * @param signature server signature | |||||
| * @return true if the data and signature match | |||||
| */ | |||||
| public static boolean verify(PublicKey publicKey, String signedData, String signature) { | |||||
| Signature sig; | |||||
| try { | |||||
| sig = Signature.getInstance(SIGNATURE_ALGORITHM); | |||||
| sig.initVerify(publicKey); | |||||
| sig.update(signedData.getBytes()); | |||||
| if (!sig.verify(Base64.decode(signature))) { | |||||
| Log.e(TAG, "Signature verification failed."); | |||||
| return false; | |||||
| } | |||||
| return true; | |||||
| } catch (NoSuchAlgorithmException e) { | |||||
| Log.e(TAG, "NoSuchAlgorithmException."); | |||||
| } catch (InvalidKeyException e) { | |||||
| Log.e(TAG, "Invalid key specification."); | |||||
| } catch (SignatureException e) { | |||||
| Log.e(TAG, "Signature exception."); | |||||
| } catch (Base64DecoderException e) { | |||||
| Log.e(TAG, "Base64 decoding failed."); | |||||
| } | |||||
| return false; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,77 @@ | |||||
| /* Copyright (c) 2012 Google Inc. | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| */ | |||||
| package ir.appeto.myketpayment.util; | |||||
| import org.json.JSONException; | |||||
| import org.json.JSONObject; | |||||
| /** | |||||
| * Represents an in-app product's listing details. | |||||
| */ | |||||
| public class SkuDetails { | |||||
| String mItemType; | |||||
| String mSku; | |||||
| String mType; | |||||
| String mPrice; | |||||
| String mTitle; | |||||
| String mDescription; | |||||
| String mJson; | |||||
| public SkuDetails(String jsonSkuDetails) throws JSONException { | |||||
| this(IabHelper.ITEM_TYPE_INAPP, jsonSkuDetails); | |||||
| } | |||||
| public SkuDetails(String itemType, String jsonSkuDetails) throws JSONException { | |||||
| mItemType = itemType; | |||||
| mJson = jsonSkuDetails; | |||||
| JSONObject o = new JSONObject(mJson); | |||||
| mSku = o.optString("productId"); | |||||
| mType = o.optString("type"); | |||||
| mPrice = o.optString("price"); | |||||
| mTitle = o.optString("title"); | |||||
| mDescription = o.optString("description"); | |||||
| } | |||||
| public String getSku() { | |||||
| return mSku; | |||||
| } | |||||
| public String getType() { | |||||
| return mType; | |||||
| } | |||||
| public String getPrice() { | |||||
| return mPrice; | |||||
| } | |||||
| public String getTitle() { | |||||
| return mTitle; | |||||
| } | |||||
| public String getDescription() { | |||||
| return mDescription; | |||||
| } | |||||
| @Override | |||||
| public String toString() { | |||||
| return "SkuDetails:" + mJson; | |||||
| } | |||||
| public JSONObject toJson() throws JSONException { | |||||
| JSONObject jsonObj = new JSONObject(mJson); | |||||
| return jsonObj; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,44 @@ | |||||
| # Miscellaneous | |||||
| *.class | |||||
| *.log | |||||
| *.pyc | |||||
| *.swp | |||||
| .DS_Store | |||||
| .atom/ | |||||
| .buildlog/ | |||||
| .history | |||||
| .svn/ | |||||
| # IntelliJ related | |||||
| *.iml | |||||
| *.ipr | |||||
| *.iws | |||||
| .idea/ | |||||
| # The .vscode folder contains launch configuration and tasks you configure in | |||||
| # VS Code which you may wish to be included in version control, so this line | |||||
| # is commented out by default. | |||||
| #.vscode/ | |||||
| # Flutter/Dart/Pub related | |||||
| **/doc/api/ | |||||
| **/ios/Flutter/.last_build_id | |||||
| .dart_tool/ | |||||
| .flutter-plugins | |||||
| .flutter-plugins-dependencies | |||||
| .packages | |||||
| .pub-cache/ | |||||
| .pub/ | |||||
| /build/ | |||||
| # Web related | |||||
| lib/generated_plugin_registrant.dart | |||||
| # Symbolication related | |||||
| app.*.symbols | |||||
| # Obfuscation related | |||||
| app.*.map.json | |||||
| # Exceptions to above rules. | |||||
| !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages | |||||
| @@ -0,0 +1,10 @@ | |||||
| # This file tracks properties of this Flutter project. | |||||
| # Used by Flutter tool to assess capabilities and perform upgrades etc. | |||||
| # | |||||
| # This file should be version controlled and should not be manually edited. | |||||
| version: | |||||
| revision: c969b8af7b48bd0f4e3329ed3f112f41136d8bcd | |||||
| channel: master | |||||
| project_type: app | |||||
| @@ -0,0 +1,16 @@ | |||||
| # myketpayment_example | |||||
| Demonstrates how to use the myketpayment plugin. | |||||
| ## Getting Started | |||||
| This project is a starting point for a Flutter application. | |||||
| A few resources to get you started if this is your first Flutter project: | |||||
| - [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) | |||||
| - [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) | |||||
| For help getting started with Flutter, view our | |||||
| [online documentation](https://flutter.dev/docs), which offers tutorials, | |||||
| samples, guidance on mobile development, and a full API reference. | |||||
| @@ -0,0 +1,7 @@ | |||||
| gradle-wrapper.jar | |||||
| /.gradle | |||||
| /captures/ | |||||
| /gradlew | |||||
| /gradlew.bat | |||||
| /local.properties | |||||
| GeneratedPluginRegistrant.java | |||||
| @@ -0,0 +1,54 @@ | |||||
| def localProperties = new Properties() | |||||
| def localPropertiesFile = rootProject.file('local.properties') | |||||
| if (localPropertiesFile.exists()) { | |||||
| localPropertiesFile.withReader('UTF-8') { reader -> | |||||
| localProperties.load(reader) | |||||
| } | |||||
| } | |||||
| def flutterRoot = localProperties.getProperty('flutter.sdk') | |||||
| if (flutterRoot == null) { | |||||
| throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") | |||||
| } | |||||
| def flutterVersionCode = localProperties.getProperty('flutter.versionCode') | |||||
| if (flutterVersionCode == null) { | |||||
| flutterVersionCode = '1' | |||||
| } | |||||
| def flutterVersionName = localProperties.getProperty('flutter.versionName') | |||||
| if (flutterVersionName == null) { | |||||
| flutterVersionName = '1.0' | |||||
| } | |||||
| apply plugin: 'com.android.application' | |||||
| apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" | |||||
| android { | |||||
| compileSdkVersion 28 | |||||
| lintOptions { | |||||
| disable 'InvalidPackage' | |||||
| } | |||||
| defaultConfig { | |||||
| // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). | |||||
| applicationId "ir.appeto.myketpayment_example" | |||||
| minSdkVersion 16 | |||||
| targetSdkVersion 28 | |||||
| versionCode flutterVersionCode.toInteger() | |||||
| versionName flutterVersionName | |||||
| } | |||||
| buildTypes { | |||||
| release { | |||||
| // TODO: Add your own signing config for the release build. | |||||
| // Signing with the debug keys for now, so `flutter run --release` works. | |||||
| signingConfig signingConfigs.debug | |||||
| } | |||||
| } | |||||
| } | |||||
| flutter { | |||||
| source '../..' | |||||
| } | |||||
| @@ -0,0 +1,9 @@ | |||||
| <manifest xmlns:android="http://schemas.android.com/apk/res/android" | |||||
| package="ir.appeto.myketpayment_example"> | |||||
| <!-- Flutter needs it to communicate with the running application | |||||
| to allow setting breakpoints, to provide hot reload, etc. | |||||
| --> | |||||
| <uses-permission android:name="android.permission.INTERNET"/> | |||||
| <uses-permission android:name="ir.mservices.market.BILLING" /> | |||||
| </manifest> | |||||
| @@ -0,0 +1,52 @@ | |||||
| <manifest xmlns:android="http://schemas.android.com/apk/res/android" | |||||
| package="ir.appeto.myketpayment_example"> | |||||
| <!-- io.flutter.app.FlutterApplication is an android.app.Application that | |||||
| calls FlutterMain.startInitialization(this); in its onCreate method. | |||||
| In most cases you can leave this as-is, but you if you want to provide | |||||
| additional functionality it is fine to subclass or reimplement | |||||
| FlutterApplication and put your custom class here. --> | |||||
| <uses-permission android:name="ir.mservices.market.BILLING" /> | |||||
| <application | |||||
| android:name="io.flutter.app.FlutterApplication" | |||||
| android:label="myketpayment_example" | |||||
| android:icon="@mipmap/ic_launcher"> | |||||
| <activity | |||||
| android:name=".MainActivity" | |||||
| android:launchMode="singleTop" | |||||
| android:theme="@style/LaunchTheme" | |||||
| android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" | |||||
| android:hardwareAccelerated="true" | |||||
| android:windowSoftInputMode="adjustResize"> | |||||
| <!-- Specifies an Android theme to apply to this Activity as soon as | |||||
| the Android process has started. This theme is visible to the user | |||||
| while the Flutter UI initializes. After that, this theme continues | |||||
| to determine the Window background behind the Flutter UI. --> | |||||
| <meta-data | |||||
| android:name="io.flutter.embedding.android.NormalTheme" | |||||
| android:resource="@style/NormalTheme" | |||||
| /> | |||||
| <!-- Displays an Android View that continues showing the launch screen | |||||
| Drawable until Flutter paints its first frame, then this splash | |||||
| screen fades out. A splash screen is useful to avoid any visual | |||||
| gap between the end of Android's launch screen and the painting of | |||||
| Flutter's first frame. --> | |||||
| <meta-data | |||||
| android:name="io.flutter.embedding.android.SplashScreenDrawable" | |||||
| android:resource="@drawable/launch_background" | |||||
| /> | |||||
| <intent-filter> | |||||
| <action android:name="android.intent.action.MAIN"/> | |||||
| <category android:name="android.intent.category.LAUNCHER"/> | |||||
| </intent-filter> | |||||
| </activity> | |||||
| <!-- Don't delete the meta-data below. | |||||
| This is used by the Flutter tool to generate GeneratedPluginRegistrant.java --> | |||||
| <meta-data | |||||
| android:name="flutterEmbedding" | |||||
| android:value="2" /> | |||||
| </application> | |||||
| </manifest> | |||||
| @@ -0,0 +1,6 @@ | |||||
| package ir.appeto.myketpayment_example; | |||||
| import io.flutter.embedding.android.FlutterActivity; | |||||
| public class MainActivity extends FlutterActivity { | |||||
| } | |||||
| @@ -0,0 +1,12 @@ | |||||
| <?xml version="1.0" encoding="utf-8"?> | |||||
| <!-- Modify this file to customize your launch splash screen --> | |||||
| <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> | |||||
| <item android:drawable="@android:color/white" /> | |||||
| <!-- You can insert your own image assets here --> | |||||
| <!-- <item> | |||||
| <bitmap | |||||
| android:gravity="center" | |||||
| android:src="@mipmap/launch_image" /> | |||||
| </item> --> | |||||
| </layer-list> | |||||
| @@ -0,0 +1,18 @@ | |||||
| <?xml version="1.0" encoding="utf-8"?> | |||||
| <resources> | |||||
| <!-- Theme applied to the Android Window while the process is starting --> | |||||
| <style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar"> | |||||
| <!-- Show a splash screen on the activity. Automatically removed when | |||||
| Flutter draws its first frame --> | |||||
| <item name="android:windowBackground">@drawable/launch_background</item> | |||||
| </style> | |||||
| <!-- Theme applied to the Android Window as soon as the process has started. | |||||
| This theme determines the color of the Android Window while your | |||||
| Flutter UI initializes, as well as behind your Flutter UI while its | |||||
| running. | |||||
| This Theme is only used starting with V2 of Flutter's Android embedding. --> | |||||
| <style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar"> | |||||
| <item name="android:windowBackground">@android:color/white</item> | |||||
| </style> | |||||
| </resources> | |||||
| @@ -0,0 +1,7 @@ | |||||
| <manifest xmlns:android="http://schemas.android.com/apk/res/android" | |||||
| package="ir.appeto.myketpayment_example"> | |||||
| <!-- Flutter needs it to communicate with the running application | |||||
| to allow setting breakpoints, to provide hot reload, etc. | |||||
| --> | |||||
| <uses-permission android:name="android.permission.INTERNET"/> | |||||
| </manifest> | |||||
| @@ -0,0 +1,29 @@ | |||||
| buildscript { | |||||
| repositories { | |||||
| google() | |||||
| jcenter() | |||||
| } | |||||
| dependencies { | |||||
| classpath 'com.android.tools.build:gradle:3.5.0' | |||||
| } | |||||
| } | |||||
| allprojects { | |||||
| repositories { | |||||
| google() | |||||
| jcenter() | |||||
| } | |||||
| } | |||||
| rootProject.buildDir = '../build' | |||||
| subprojects { | |||||
| project.buildDir = "${rootProject.buildDir}/${project.name}" | |||||
| } | |||||
| subprojects { | |||||
| project.evaluationDependsOn(':app') | |||||
| } | |||||
| task clean(type: Delete) { | |||||
| delete rootProject.buildDir | |||||
| } | |||||
| @@ -0,0 +1,4 @@ | |||||
| org.gradle.jvmargs=-Xmx1536M | |||||
| android.enableR8=true | |||||
| android.useAndroidX=true | |||||
| android.enableJetifier=true | |||||
| @@ -0,0 +1,6 @@ | |||||
| #Fri Jun 23 08:50:38 CEST 2017 | |||||
| distributionBase=GRADLE_USER_HOME | |||||
| distributionPath=wrapper/dists | |||||
| zipStoreBase=GRADLE_USER_HOME | |||||
| zipStorePath=wrapper/dists | |||||
| distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip | |||||
| @@ -0,0 +1,15 @@ | |||||
| // Copyright 2014 The Flutter Authors. All rights reserved. | |||||
| // Use of this source code is governed by a BSD-style license that can be | |||||
| // found in the LICENSE file. | |||||
| include ':app' | |||||
| def localPropertiesFile = new File(rootProject.projectDir, "local.properties") | |||||
| def properties = new Properties() | |||||
| assert localPropertiesFile.exists() | |||||
| localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } | |||||
| def flutterSdkPath = properties.getProperty("flutter.sdk") | |||||
| assert flutterSdkPath != null, "flutter.sdk not set in local.properties" | |||||
| apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" | |||||
| @@ -0,0 +1,32 @@ | |||||
| *.mode1v3 | |||||
| *.mode2v3 | |||||
| *.moved-aside | |||||
| *.pbxuser | |||||
| *.perspectivev3 | |||||
| **/*sync/ | |||||
| .sconsign.dblite | |||||
| .tags* | |||||
| **/.vagrant/ | |||||
| **/DerivedData/ | |||||
| Icon? | |||||
| **/Pods/ | |||||
| **/.symlinks/ | |||||
| profile | |||||
| xcuserdata | |||||
| **/.generated/ | |||||
| Flutter/App.framework | |||||
| Flutter/Flutter.framework | |||||
| Flutter/Flutter.podspec | |||||
| Flutter/Generated.xcconfig | |||||
| Flutter/app.flx | |||||
| Flutter/app.zip | |||||
| Flutter/flutter_assets/ | |||||
| Flutter/flutter_export_environment.sh | |||||
| ServiceDefinitions.json | |||||
| Runner/GeneratedPluginRegistrant.* | |||||
| # Exceptions to above rules. | |||||
| !default.mode1v3 | |||||
| !default.mode2v3 | |||||
| !default.pbxuser | |||||
| !default.perspectivev3 | |||||
| @@ -0,0 +1,26 @@ | |||||
| <?xml version="1.0" encoding="UTF-8"?> | |||||
| <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |||||
| <plist version="1.0"> | |||||
| <dict> | |||||
| <key>CFBundleDevelopmentRegion</key> | |||||
| <string>$(DEVELOPMENT_LANGUAGE)</string> | |||||
| <key>CFBundleExecutable</key> | |||||
| <string>App</string> | |||||
| <key>CFBundleIdentifier</key> | |||||
| <string>io.flutter.flutter.app</string> | |||||
| <key>CFBundleInfoDictionaryVersion</key> | |||||
| <string>6.0</string> | |||||
| <key>CFBundleName</key> | |||||
| <string>App</string> | |||||
| <key>CFBundlePackageType</key> | |||||
| <string>FMWK</string> | |||||
| <key>CFBundleShortVersionString</key> | |||||
| <string>1.0</string> | |||||
| <key>CFBundleSignature</key> | |||||
| <string>????</string> | |||||
| <key>CFBundleVersion</key> | |||||
| <string>1.0</string> | |||||
| <key>MinimumOSVersion</key> | |||||
| <string>8.0</string> | |||||
| </dict> | |||||
| </plist> | |||||
| @@ -0,0 +1 @@ | |||||
| #include "Generated.xcconfig" | |||||
| @@ -0,0 +1 @@ | |||||
| #include "Generated.xcconfig" | |||||
| @@ -0,0 +1,496 @@ | |||||
| // !$*UTF8*$! | |||||
| { | |||||
| archiveVersion = 1; | |||||
| classes = { | |||||
| }; | |||||
| objectVersion = 46; | |||||
| objects = { | |||||
| /* Begin PBXBuildFile section */ | |||||
| 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; | |||||
| 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; | |||||
| 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; }; | |||||
| 97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; }; | |||||
| 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; | |||||
| 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; | |||||
| 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; | |||||
| /* End PBXBuildFile section */ | |||||
| /* Begin PBXCopyFilesBuildPhase section */ | |||||
| 9705A1C41CF9048500538489 /* Embed Frameworks */ = { | |||||
| isa = PBXCopyFilesBuildPhase; | |||||
| buildActionMask = 2147483647; | |||||
| dstPath = ""; | |||||
| dstSubfolderSpec = 10; | |||||
| files = ( | |||||
| ); | |||||
| name = "Embed Frameworks"; | |||||
| runOnlyForDeploymentPostprocessing = 0; | |||||
| }; | |||||
| /* End PBXCopyFilesBuildPhase section */ | |||||
| /* Begin PBXFileReference section */ | |||||
| 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; }; | |||||
| 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; }; | |||||
| 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; }; | |||||
| 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; }; | |||||
| 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; }; | |||||
| 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; }; | |||||
| 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; }; | |||||
| 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; }; | |||||
| 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; | |||||
| 97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; }; | |||||
| 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; }; | |||||
| 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; }; | |||||
| 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; }; | |||||
| 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; | |||||
| /* End PBXFileReference section */ | |||||
| /* Begin PBXFrameworksBuildPhase section */ | |||||
| 97C146EB1CF9000F007C117D /* Frameworks */ = { | |||||
| isa = PBXFrameworksBuildPhase; | |||||
| buildActionMask = 2147483647; | |||||
| files = ( | |||||
| ); | |||||
| runOnlyForDeploymentPostprocessing = 0; | |||||
| }; | |||||
| /* End PBXFrameworksBuildPhase section */ | |||||
| /* Begin PBXGroup section */ | |||||
| 9740EEB11CF90186004384FC /* Flutter */ = { | |||||
| isa = PBXGroup; | |||||
| children = ( | |||||
| 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, | |||||
| 9740EEB21CF90195004384FC /* Debug.xcconfig */, | |||||
| 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, | |||||
| 9740EEB31CF90195004384FC /* Generated.xcconfig */, | |||||
| ); | |||||
| name = Flutter; | |||||
| sourceTree = "<group>"; | |||||
| }; | |||||
| 97C146E51CF9000F007C117D = { | |||||
| isa = PBXGroup; | |||||
| children = ( | |||||
| 9740EEB11CF90186004384FC /* Flutter */, | |||||
| 97C146F01CF9000F007C117D /* Runner */, | |||||
| 97C146EF1CF9000F007C117D /* Products */, | |||||
| CF3B75C9A7D2FA2A4C99F110 /* Frameworks */, | |||||
| ); | |||||
| sourceTree = "<group>"; | |||||
| }; | |||||
| 97C146EF1CF9000F007C117D /* Products */ = { | |||||
| isa = PBXGroup; | |||||
| children = ( | |||||
| 97C146EE1CF9000F007C117D /* Runner.app */, | |||||
| ); | |||||
| name = Products; | |||||
| sourceTree = "<group>"; | |||||
| }; | |||||
| 97C146F01CF9000F007C117D /* Runner */ = { | |||||
| isa = PBXGroup; | |||||
| children = ( | |||||
| 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */, | |||||
| 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */, | |||||
| 97C146FA1CF9000F007C117D /* Main.storyboard */, | |||||
| 97C146FD1CF9000F007C117D /* Assets.xcassets */, | |||||
| 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, | |||||
| 97C147021CF9000F007C117D /* Info.plist */, | |||||
| 97C146F11CF9000F007C117D /* Supporting Files */, | |||||
| 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, | |||||
| 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, | |||||
| ); | |||||
| path = Runner; | |||||
| sourceTree = "<group>"; | |||||
| }; | |||||
| 97C146F11CF9000F007C117D /* Supporting Files */ = { | |||||
| isa = PBXGroup; | |||||
| children = ( | |||||
| 97C146F21CF9000F007C117D /* main.m */, | |||||
| ); | |||||
| name = "Supporting Files"; | |||||
| sourceTree = "<group>"; | |||||
| }; | |||||
| /* End PBXGroup section */ | |||||
| /* Begin PBXNativeTarget section */ | |||||
| 97C146ED1CF9000F007C117D /* Runner */ = { | |||||
| isa = PBXNativeTarget; | |||||
| buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; | |||||
| buildPhases = ( | |||||
| 9740EEB61CF901F6004384FC /* Run Script */, | |||||
| 97C146EA1CF9000F007C117D /* Sources */, | |||||
| 97C146EB1CF9000F007C117D /* Frameworks */, | |||||
| 97C146EC1CF9000F007C117D /* Resources */, | |||||
| 9705A1C41CF9048500538489 /* Embed Frameworks */, | |||||
| 3B06AD1E1E4923F5004D2608 /* Thin Binary */, | |||||
| ); | |||||
| buildRules = ( | |||||
| ); | |||||
| dependencies = ( | |||||
| ); | |||||
| name = Runner; | |||||
| productName = Runner; | |||||
| productReference = 97C146EE1CF9000F007C117D /* Runner.app */; | |||||
| productType = "com.apple.product-type.application"; | |||||
| }; | |||||
| /* End PBXNativeTarget section */ | |||||
| /* Begin PBXProject section */ | |||||
| 97C146E61CF9000F007C117D /* Project object */ = { | |||||
| isa = PBXProject; | |||||
| attributes = { | |||||
| LastUpgradeCheck = 1020; | |||||
| ORGANIZATIONNAME = ""; | |||||
| TargetAttributes = { | |||||
| 97C146ED1CF9000F007C117D = { | |||||
| CreatedOnToolsVersion = 7.3.1; | |||||
| }; | |||||
| }; | |||||
| }; | |||||
| buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; | |||||
| compatibilityVersion = "Xcode 9.3"; | |||||
| developmentRegion = en; | |||||
| hasScannedForEncodings = 0; | |||||
| knownRegions = ( | |||||
| en, | |||||
| Base, | |||||
| ); | |||||
| mainGroup = 97C146E51CF9000F007C117D; | |||||
| productRefGroup = 97C146EF1CF9000F007C117D /* Products */; | |||||
| projectDirPath = ""; | |||||
| projectRoot = ""; | |||||
| targets = ( | |||||
| 97C146ED1CF9000F007C117D /* Runner */, | |||||
| ); | |||||
| }; | |||||
| /* End PBXProject section */ | |||||
| /* Begin PBXResourcesBuildPhase section */ | |||||
| 97C146EC1CF9000F007C117D /* Resources */ = { | |||||
| isa = PBXResourcesBuildPhase; | |||||
| buildActionMask = 2147483647; | |||||
| files = ( | |||||
| 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, | |||||
| 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, | |||||
| 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, | |||||
| 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, | |||||
| ); | |||||
| runOnlyForDeploymentPostprocessing = 0; | |||||
| }; | |||||
| /* End PBXResourcesBuildPhase section */ | |||||
| /* Begin PBXShellScriptBuildPhase section */ | |||||
| 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { | |||||
| isa = PBXShellScriptBuildPhase; | |||||
| buildActionMask = 2147483647; | |||||
| files = ( | |||||
| ); | |||||
| inputPaths = ( | |||||
| ); | |||||
| name = "Thin Binary"; | |||||
| outputPaths = ( | |||||
| ); | |||||
| runOnlyForDeploymentPostprocessing = 0; | |||||
| shellPath = /bin/sh; | |||||
| shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; | |||||
| }; | |||||
| 9740EEB61CF901F6004384FC /* Run Script */ = { | |||||
| isa = PBXShellScriptBuildPhase; | |||||
| buildActionMask = 2147483647; | |||||
| files = ( | |||||
| ); | |||||
| inputPaths = ( | |||||
| ); | |||||
| name = "Run Script"; | |||||
| outputPaths = ( | |||||
| ); | |||||
| runOnlyForDeploymentPostprocessing = 0; | |||||
| shellPath = /bin/sh; | |||||
| shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; | |||||
| }; | |||||
| /* End PBXShellScriptBuildPhase section */ | |||||
| /* Begin PBXSourcesBuildPhase section */ | |||||
| 97C146EA1CF9000F007C117D /* Sources */ = { | |||||
| isa = PBXSourcesBuildPhase; | |||||
| buildActionMask = 2147483647; | |||||
| files = ( | |||||
| 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */, | |||||
| 97C146F31CF9000F007C117D /* main.m in Sources */, | |||||
| 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, | |||||
| ); | |||||
| runOnlyForDeploymentPostprocessing = 0; | |||||
| }; | |||||
| /* End PBXSourcesBuildPhase section */ | |||||
| /* Begin PBXVariantGroup section */ | |||||
| 97C146FA1CF9000F007C117D /* Main.storyboard */ = { | |||||
| isa = PBXVariantGroup; | |||||
| children = ( | |||||
| 97C146FB1CF9000F007C117D /* Base */, | |||||
| ); | |||||
| name = Main.storyboard; | |||||
| sourceTree = "<group>"; | |||||
| }; | |||||
| 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { | |||||
| isa = PBXVariantGroup; | |||||
| children = ( | |||||
| 97C147001CF9000F007C117D /* Base */, | |||||
| ); | |||||
| name = LaunchScreen.storyboard; | |||||
| sourceTree = "<group>"; | |||||
| }; | |||||
| /* End PBXVariantGroup section */ | |||||
| /* Begin XCBuildConfiguration section */ | |||||
| 249021D3217E4FDB00AE95B9 /* Profile */ = { | |||||
| isa = XCBuildConfiguration; | |||||
| buildSettings = { | |||||
| ALWAYS_SEARCH_USER_PATHS = NO; | |||||
| CLANG_ANALYZER_NONNULL = YES; | |||||
| CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; | |||||
| CLANG_CXX_LIBRARY = "libc++"; | |||||
| CLANG_ENABLE_MODULES = YES; | |||||
| CLANG_ENABLE_OBJC_ARC = YES; | |||||
| CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; | |||||
| CLANG_WARN_BOOL_CONVERSION = YES; | |||||
| CLANG_WARN_COMMA = YES; | |||||
| CLANG_WARN_CONSTANT_CONVERSION = YES; | |||||
| CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; | |||||
| CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; | |||||
| CLANG_WARN_EMPTY_BODY = YES; | |||||
| CLANG_WARN_ENUM_CONVERSION = YES; | |||||
| CLANG_WARN_INFINITE_RECURSION = YES; | |||||
| CLANG_WARN_INT_CONVERSION = YES; | |||||
| CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; | |||||
| CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; | |||||
| CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; | |||||
| CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; | |||||
| CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; | |||||
| CLANG_WARN_STRICT_PROTOTYPES = YES; | |||||
| CLANG_WARN_SUSPICIOUS_MOVE = YES; | |||||
| CLANG_WARN_UNREACHABLE_CODE = YES; | |||||
| CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; | |||||
| "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; | |||||
| COPY_PHASE_STRIP = NO; | |||||
| DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; | |||||
| ENABLE_NS_ASSERTIONS = NO; | |||||
| ENABLE_STRICT_OBJC_MSGSEND = YES; | |||||
| GCC_C_LANGUAGE_STANDARD = gnu99; | |||||
| GCC_NO_COMMON_BLOCKS = YES; | |||||
| GCC_WARN_64_TO_32_BIT_CONVERSION = YES; | |||||
| GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; | |||||
| GCC_WARN_UNDECLARED_SELECTOR = YES; | |||||
| GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; | |||||
| GCC_WARN_UNUSED_FUNCTION = YES; | |||||
| GCC_WARN_UNUSED_VARIABLE = YES; | |||||
| IPHONEOS_DEPLOYMENT_TARGET = 8.0; | |||||
| MTL_ENABLE_DEBUG_INFO = NO; | |||||
| SDKROOT = iphoneos; | |||||
| SUPPORTED_PLATFORMS = iphoneos; | |||||
| TARGETED_DEVICE_FAMILY = "1,2"; | |||||
| VALIDATE_PRODUCT = YES; | |||||
| }; | |||||
| name = Profile; | |||||
| }; | |||||
| 249021D4217E4FDB00AE95B9 /* Profile */ = { | |||||
| isa = XCBuildConfiguration; | |||||
| baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; | |||||
| buildSettings = { | |||||
| ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; | |||||
| CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; | |||||
| ENABLE_BITCODE = NO; | |||||
| FRAMEWORK_SEARCH_PATHS = ( | |||||
| "$(inherited)", | |||||
| "$(PROJECT_DIR)/Flutter", | |||||
| ); | |||||
| INFOPLIST_FILE = Runner/Info.plist; | |||||
| LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; | |||||
| LIBRARY_SEARCH_PATHS = ( | |||||
| "$(inherited)", | |||||
| "$(PROJECT_DIR)/Flutter", | |||||
| ); | |||||
| PRODUCT_BUNDLE_IDENTIFIER = ir.appeto.myketpaymentExample; | |||||
| PRODUCT_NAME = "$(TARGET_NAME)"; | |||||
| VERSIONING_SYSTEM = "apple-generic"; | |||||
| }; | |||||
| name = Profile; | |||||
| }; | |||||
| 97C147031CF9000F007C117D /* Debug */ = { | |||||
| isa = XCBuildConfiguration; | |||||
| buildSettings = { | |||||
| ALWAYS_SEARCH_USER_PATHS = NO; | |||||
| CLANG_ANALYZER_NONNULL = YES; | |||||
| CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; | |||||
| CLANG_CXX_LIBRARY = "libc++"; | |||||
| CLANG_ENABLE_MODULES = YES; | |||||
| CLANG_ENABLE_OBJC_ARC = YES; | |||||
| CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; | |||||
| CLANG_WARN_BOOL_CONVERSION = YES; | |||||
| CLANG_WARN_COMMA = YES; | |||||
| CLANG_WARN_CONSTANT_CONVERSION = YES; | |||||
| CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; | |||||
| CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; | |||||
| CLANG_WARN_EMPTY_BODY = YES; | |||||
| CLANG_WARN_ENUM_CONVERSION = YES; | |||||
| CLANG_WARN_INFINITE_RECURSION = YES; | |||||
| CLANG_WARN_INT_CONVERSION = YES; | |||||
| CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; | |||||
| CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; | |||||
| CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; | |||||
| CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; | |||||
| CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; | |||||
| CLANG_WARN_STRICT_PROTOTYPES = YES; | |||||
| CLANG_WARN_SUSPICIOUS_MOVE = YES; | |||||
| CLANG_WARN_UNREACHABLE_CODE = YES; | |||||
| CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; | |||||
| "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; | |||||
| COPY_PHASE_STRIP = NO; | |||||
| DEBUG_INFORMATION_FORMAT = dwarf; | |||||
| ENABLE_STRICT_OBJC_MSGSEND = YES; | |||||
| ENABLE_TESTABILITY = YES; | |||||
| GCC_C_LANGUAGE_STANDARD = gnu99; | |||||
| GCC_DYNAMIC_NO_PIC = NO; | |||||
| GCC_NO_COMMON_BLOCKS = YES; | |||||
| GCC_OPTIMIZATION_LEVEL = 0; | |||||
| GCC_PREPROCESSOR_DEFINITIONS = ( | |||||
| "DEBUG=1", | |||||
| "$(inherited)", | |||||
| ); | |||||
| GCC_WARN_64_TO_32_BIT_CONVERSION = YES; | |||||
| GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; | |||||
| GCC_WARN_UNDECLARED_SELECTOR = YES; | |||||
| GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; | |||||
| GCC_WARN_UNUSED_FUNCTION = YES; | |||||
| GCC_WARN_UNUSED_VARIABLE = YES; | |||||
| IPHONEOS_DEPLOYMENT_TARGET = 8.0; | |||||
| MTL_ENABLE_DEBUG_INFO = YES; | |||||
| ONLY_ACTIVE_ARCH = YES; | |||||
| SDKROOT = iphoneos; | |||||
| TARGETED_DEVICE_FAMILY = "1,2"; | |||||
| }; | |||||
| name = Debug; | |||||
| }; | |||||
| 97C147041CF9000F007C117D /* Release */ = { | |||||
| isa = XCBuildConfiguration; | |||||
| buildSettings = { | |||||
| ALWAYS_SEARCH_USER_PATHS = NO; | |||||
| CLANG_ANALYZER_NONNULL = YES; | |||||
| CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; | |||||
| CLANG_CXX_LIBRARY = "libc++"; | |||||
| CLANG_ENABLE_MODULES = YES; | |||||
| CLANG_ENABLE_OBJC_ARC = YES; | |||||
| CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; | |||||
| CLANG_WARN_BOOL_CONVERSION = YES; | |||||
| CLANG_WARN_COMMA = YES; | |||||
| CLANG_WARN_CONSTANT_CONVERSION = YES; | |||||
| CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; | |||||
| CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; | |||||
| CLANG_WARN_EMPTY_BODY = YES; | |||||
| CLANG_WARN_ENUM_CONVERSION = YES; | |||||
| CLANG_WARN_INFINITE_RECURSION = YES; | |||||
| CLANG_WARN_INT_CONVERSION = YES; | |||||
| CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; | |||||
| CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; | |||||
| CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; | |||||
| CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; | |||||
| CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; | |||||
| CLANG_WARN_STRICT_PROTOTYPES = YES; | |||||
| CLANG_WARN_SUSPICIOUS_MOVE = YES; | |||||
| CLANG_WARN_UNREACHABLE_CODE = YES; | |||||
| CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; | |||||
| "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; | |||||
| COPY_PHASE_STRIP = NO; | |||||
| DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; | |||||
| ENABLE_NS_ASSERTIONS = NO; | |||||
| ENABLE_STRICT_OBJC_MSGSEND = YES; | |||||
| GCC_C_LANGUAGE_STANDARD = gnu99; | |||||
| GCC_NO_COMMON_BLOCKS = YES; | |||||
| GCC_WARN_64_TO_32_BIT_CONVERSION = YES; | |||||
| GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; | |||||
| GCC_WARN_UNDECLARED_SELECTOR = YES; | |||||
| GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; | |||||
| GCC_WARN_UNUSED_FUNCTION = YES; | |||||
| GCC_WARN_UNUSED_VARIABLE = YES; | |||||
| IPHONEOS_DEPLOYMENT_TARGET = 8.0; | |||||
| MTL_ENABLE_DEBUG_INFO = NO; | |||||
| SDKROOT = iphoneos; | |||||
| SUPPORTED_PLATFORMS = iphoneos; | |||||
| TARGETED_DEVICE_FAMILY = "1,2"; | |||||
| VALIDATE_PRODUCT = YES; | |||||
| }; | |||||
| name = Release; | |||||
| }; | |||||
| 97C147061CF9000F007C117D /* Debug */ = { | |||||
| isa = XCBuildConfiguration; | |||||
| baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; | |||||
| buildSettings = { | |||||
| ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; | |||||
| CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; | |||||
| ENABLE_BITCODE = NO; | |||||
| FRAMEWORK_SEARCH_PATHS = ( | |||||
| "$(inherited)", | |||||
| "$(PROJECT_DIR)/Flutter", | |||||
| ); | |||||
| INFOPLIST_FILE = Runner/Info.plist; | |||||
| LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; | |||||
| LIBRARY_SEARCH_PATHS = ( | |||||
| "$(inherited)", | |||||
| "$(PROJECT_DIR)/Flutter", | |||||
| ); | |||||
| PRODUCT_BUNDLE_IDENTIFIER = ir.appeto.myketpaymentExample; | |||||
| PRODUCT_NAME = "$(TARGET_NAME)"; | |||||
| VERSIONING_SYSTEM = "apple-generic"; | |||||
| }; | |||||
| name = Debug; | |||||
| }; | |||||
| 97C147071CF9000F007C117D /* Release */ = { | |||||
| isa = XCBuildConfiguration; | |||||
| baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; | |||||
| buildSettings = { | |||||
| ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; | |||||
| CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; | |||||
| ENABLE_BITCODE = NO; | |||||
| FRAMEWORK_SEARCH_PATHS = ( | |||||
| "$(inherited)", | |||||
| "$(PROJECT_DIR)/Flutter", | |||||
| ); | |||||
| INFOPLIST_FILE = Runner/Info.plist; | |||||
| LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; | |||||
| LIBRARY_SEARCH_PATHS = ( | |||||
| "$(inherited)", | |||||
| "$(PROJECT_DIR)/Flutter", | |||||
| ); | |||||
| PRODUCT_BUNDLE_IDENTIFIER = ir.appeto.myketpaymentExample; | |||||
| PRODUCT_NAME = "$(TARGET_NAME)"; | |||||
| VERSIONING_SYSTEM = "apple-generic"; | |||||
| }; | |||||
| name = Release; | |||||
| }; | |||||
| /* End XCBuildConfiguration section */ | |||||
| /* Begin XCConfigurationList section */ | |||||
| 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { | |||||
| isa = XCConfigurationList; | |||||
| buildConfigurations = ( | |||||
| 97C147031CF9000F007C117D /* Debug */, | |||||
| 97C147041CF9000F007C117D /* Release */, | |||||
| 249021D3217E4FDB00AE95B9 /* Profile */, | |||||
| ); | |||||
| defaultConfigurationIsVisible = 0; | |||||
| defaultConfigurationName = Release; | |||||
| }; | |||||
| 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { | |||||
| isa = XCConfigurationList; | |||||
| buildConfigurations = ( | |||||
| 97C147061CF9000F007C117D /* Debug */, | |||||
| 97C147071CF9000F007C117D /* Release */, | |||||
| 249021D4217E4FDB00AE95B9 /* Profile */, | |||||
| ); | |||||
| defaultConfigurationIsVisible = 0; | |||||
| defaultConfigurationName = Release; | |||||
| }; | |||||
| /* End XCConfigurationList section */ | |||||
| }; | |||||
| rootObject = 97C146E61CF9000F007C117D /* Project object */; | |||||
| } | |||||
| @@ -0,0 +1,7 @@ | |||||
| <?xml version="1.0" encoding="UTF-8"?> | |||||
| <Workspace | |||||
| version = "1.0"> | |||||
| <FileRef | |||||
| location = "group:Runner.xcodeproj"> | |||||
| </FileRef> | |||||
| </Workspace> | |||||
| @@ -0,0 +1,8 @@ | |||||
| <?xml version="1.0" encoding="UTF-8"?> | |||||
| <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |||||
| <plist version="1.0"> | |||||
| <dict> | |||||
| <key>IDEDidComputeMac32BitWarning</key> | |||||
| <true/> | |||||
| </dict> | |||||
| </plist> | |||||
| @@ -0,0 +1,8 @@ | |||||
| <?xml version="1.0" encoding="UTF-8"?> | |||||
| <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |||||
| <plist version="1.0"> | |||||
| <dict> | |||||
| <key>PreviewsEnabled</key> | |||||
| <false/> | |||||
| </dict> | |||||
| </plist> | |||||
| @@ -0,0 +1,91 @@ | |||||
| <?xml version="1.0" encoding="UTF-8"?> | |||||
| <Scheme | |||||
| LastUpgradeVersion = "1020" | |||||
| version = "1.3"> | |||||
| <BuildAction | |||||
| parallelizeBuildables = "YES" | |||||
| buildImplicitDependencies = "YES"> | |||||
| <BuildActionEntries> | |||||
| <BuildActionEntry | |||||
| buildForTesting = "YES" | |||||
| buildForRunning = "YES" | |||||
| buildForProfiling = "YES" | |||||
| buildForArchiving = "YES" | |||||
| buildForAnalyzing = "YES"> | |||||
| <BuildableReference | |||||
| BuildableIdentifier = "primary" | |||||
| BlueprintIdentifier = "97C146ED1CF9000F007C117D" | |||||
| BuildableName = "Runner.app" | |||||
| BlueprintName = "Runner" | |||||
| ReferencedContainer = "container:Runner.xcodeproj"> | |||||
| </BuildableReference> | |||||
| </BuildActionEntry> | |||||
| </BuildActionEntries> | |||||
| </BuildAction> | |||||
| <TestAction | |||||
| buildConfiguration = "Debug" | |||||
| selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" | |||||
| selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" | |||||
| shouldUseLaunchSchemeArgsEnv = "YES"> | |||||
| <Testables> | |||||
| </Testables> | |||||
| <MacroExpansion> | |||||
| <BuildableReference | |||||
| BuildableIdentifier = "primary" | |||||
| BlueprintIdentifier = "97C146ED1CF9000F007C117D" | |||||
| BuildableName = "Runner.app" | |||||
| BlueprintName = "Runner" | |||||
| ReferencedContainer = "container:Runner.xcodeproj"> | |||||
| </BuildableReference> | |||||
| </MacroExpansion> | |||||
| <AdditionalOptions> | |||||
| </AdditionalOptions> | |||||
| </TestAction> | |||||
| <LaunchAction | |||||
| buildConfiguration = "Debug" | |||||
| selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" | |||||
| selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" | |||||
| launchStyle = "0" | |||||
| useCustomWorkingDirectory = "NO" | |||||
| ignoresPersistentStateOnLaunch = "NO" | |||||
| debugDocumentVersioning = "YES" | |||||
| debugServiceExtension = "internal" | |||||
| allowLocationSimulation = "YES"> | |||||
| <BuildableProductRunnable | |||||
| runnableDebuggingMode = "0"> | |||||
| <BuildableReference | |||||
| BuildableIdentifier = "primary" | |||||
| BlueprintIdentifier = "97C146ED1CF9000F007C117D" | |||||
| BuildableName = "Runner.app" | |||||
| BlueprintName = "Runner" | |||||
| ReferencedContainer = "container:Runner.xcodeproj"> | |||||
| </BuildableReference> | |||||
| </BuildableProductRunnable> | |||||
| <AdditionalOptions> | |||||
| </AdditionalOptions> | |||||
| </LaunchAction> | |||||
| <ProfileAction | |||||
| buildConfiguration = "Profile" | |||||
| shouldUseLaunchSchemeArgsEnv = "YES" | |||||
| savedToolIdentifier = "" | |||||
| useCustomWorkingDirectory = "NO" | |||||
| debugDocumentVersioning = "YES"> | |||||
| <BuildableProductRunnable | |||||
| runnableDebuggingMode = "0"> | |||||
| <BuildableReference | |||||
| BuildableIdentifier = "primary" | |||||
| BlueprintIdentifier = "97C146ED1CF9000F007C117D" | |||||
| BuildableName = "Runner.app" | |||||
| BlueprintName = "Runner" | |||||
| ReferencedContainer = "container:Runner.xcodeproj"> | |||||
| </BuildableReference> | |||||
| </BuildableProductRunnable> | |||||
| </ProfileAction> | |||||
| <AnalyzeAction | |||||
| buildConfiguration = "Debug"> | |||||
| </AnalyzeAction> | |||||
| <ArchiveAction | |||||
| buildConfiguration = "Release" | |||||
| revealArchiveInOrganizer = "YES"> | |||||
| </ArchiveAction> | |||||
| </Scheme> | |||||
| @@ -0,0 +1,7 @@ | |||||
| <?xml version="1.0" encoding="UTF-8"?> | |||||
| <Workspace | |||||
| version = "1.0"> | |||||
| <FileRef | |||||
| location = "group:Runner.xcodeproj"> | |||||
| </FileRef> | |||||
| </Workspace> | |||||
| @@ -0,0 +1,8 @@ | |||||
| <?xml version="1.0" encoding="UTF-8"?> | |||||
| <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |||||
| <plist version="1.0"> | |||||
| <dict> | |||||
| <key>IDEDidComputeMac32BitWarning</key> | |||||
| <true/> | |||||
| </dict> | |||||
| </plist> | |||||
| @@ -0,0 +1,8 @@ | |||||
| <?xml version="1.0" encoding="UTF-8"?> | |||||
| <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |||||
| <plist version="1.0"> | |||||
| <dict> | |||||
| <key>PreviewsEnabled</key> | |||||
| <false/> | |||||
| </dict> | |||||
| </plist> | |||||
| @@ -0,0 +1,6 @@ | |||||
| #import <Flutter/Flutter.h> | |||||
| #import <UIKit/UIKit.h> | |||||
| @interface AppDelegate : FlutterAppDelegate | |||||
| @end | |||||
| @@ -0,0 +1,13 @@ | |||||
| #import "AppDelegate.h" | |||||
| #import "GeneratedPluginRegistrant.h" | |||||
| @implementation AppDelegate | |||||
| - (BOOL)application:(UIApplication *)application | |||||
| didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { | |||||
| [GeneratedPluginRegistrant registerWithRegistry:self]; | |||||
| // Override point for customization after application launch. | |||||
| return [super application:application didFinishLaunchingWithOptions:launchOptions]; | |||||
| } | |||||
| @end | |||||
| @@ -0,0 +1,122 @@ | |||||
| { | |||||
| "images" : [ | |||||
| { | |||||
| "size" : "20x20", | |||||
| "idiom" : "iphone", | |||||
| "filename" : "Icon-App-20x20@2x.png", | |||||
| "scale" : "2x" | |||||
| }, | |||||
| { | |||||
| "size" : "20x20", | |||||
| "idiom" : "iphone", | |||||
| "filename" : "Icon-App-20x20@3x.png", | |||||
| "scale" : "3x" | |||||
| }, | |||||
| { | |||||
| "size" : "29x29", | |||||
| "idiom" : "iphone", | |||||
| "filename" : "Icon-App-29x29@1x.png", | |||||
| "scale" : "1x" | |||||
| }, | |||||
| { | |||||
| "size" : "29x29", | |||||
| "idiom" : "iphone", | |||||
| "filename" : "Icon-App-29x29@2x.png", | |||||
| "scale" : "2x" | |||||
| }, | |||||
| { | |||||
| "size" : "29x29", | |||||
| "idiom" : "iphone", | |||||
| "filename" : "Icon-App-29x29@3x.png", | |||||
| "scale" : "3x" | |||||
| }, | |||||
| { | |||||
| "size" : "40x40", | |||||
| "idiom" : "iphone", | |||||
| "filename" : "Icon-App-40x40@2x.png", | |||||
| "scale" : "2x" | |||||
| }, | |||||
| { | |||||
| "size" : "40x40", | |||||
| "idiom" : "iphone", | |||||
| "filename" : "Icon-App-40x40@3x.png", | |||||
| "scale" : "3x" | |||||
| }, | |||||
| { | |||||
| "size" : "60x60", | |||||
| "idiom" : "iphone", | |||||
| "filename" : "Icon-App-60x60@2x.png", | |||||
| "scale" : "2x" | |||||
| }, | |||||
| { | |||||
| "size" : "60x60", | |||||
| "idiom" : "iphone", | |||||
| "filename" : "Icon-App-60x60@3x.png", | |||||
| "scale" : "3x" | |||||
| }, | |||||
| { | |||||
| "size" : "20x20", | |||||
| "idiom" : "ipad", | |||||
| "filename" : "Icon-App-20x20@1x.png", | |||||
| "scale" : "1x" | |||||
| }, | |||||
| { | |||||
| "size" : "20x20", | |||||
| "idiom" : "ipad", | |||||
| "filename" : "Icon-App-20x20@2x.png", | |||||
| "scale" : "2x" | |||||
| }, | |||||
| { | |||||
| "size" : "29x29", | |||||
| "idiom" : "ipad", | |||||
| "filename" : "Icon-App-29x29@1x.png", | |||||
| "scale" : "1x" | |||||
| }, | |||||
| { | |||||
| "size" : "29x29", | |||||
| "idiom" : "ipad", | |||||
| "filename" : "Icon-App-29x29@2x.png", | |||||
| "scale" : "2x" | |||||
| }, | |||||
| { | |||||
| "size" : "40x40", | |||||
| "idiom" : "ipad", | |||||
| "filename" : "Icon-App-40x40@1x.png", | |||||
| "scale" : "1x" | |||||
| }, | |||||
| { | |||||
| "size" : "40x40", | |||||
| "idiom" : "ipad", | |||||
| "filename" : "Icon-App-40x40@2x.png", | |||||
| "scale" : "2x" | |||||
| }, | |||||
| { | |||||
| "size" : "76x76", | |||||
| "idiom" : "ipad", | |||||
| "filename" : "Icon-App-76x76@1x.png", | |||||
| "scale" : "1x" | |||||
| }, | |||||
| { | |||||
| "size" : "76x76", | |||||
| "idiom" : "ipad", | |||||
| "filename" : "Icon-App-76x76@2x.png", | |||||
| "scale" : "2x" | |||||
| }, | |||||
| { | |||||
| "size" : "83.5x83.5", | |||||
| "idiom" : "ipad", | |||||
| "filename" : "Icon-App-83.5x83.5@2x.png", | |||||
| "scale" : "2x" | |||||
| }, | |||||
| { | |||||
| "size" : "1024x1024", | |||||
| "idiom" : "ios-marketing", | |||||
| "filename" : "Icon-App-1024x1024@1x.png", | |||||
| "scale" : "1x" | |||||
| } | |||||
| ], | |||||
| "info" : { | |||||
| "version" : 1, | |||||
| "author" : "xcode" | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,23 @@ | |||||
| { | |||||
| "images" : [ | |||||
| { | |||||
| "idiom" : "universal", | |||||
| "filename" : "LaunchImage.png", | |||||
| "scale" : "1x" | |||||
| }, | |||||
| { | |||||
| "idiom" : "universal", | |||||
| "filename" : "LaunchImage@2x.png", | |||||
| "scale" : "2x" | |||||
| }, | |||||
| { | |||||
| "idiom" : "universal", | |||||
| "filename" : "LaunchImage@3x.png", | |||||
| "scale" : "3x" | |||||
| } | |||||
| ], | |||||
| "info" : { | |||||
| "version" : 1, | |||||
| "author" : "xcode" | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,5 @@ | |||||
| # Launch Screen Assets | |||||
| You can customize the launch screen with your own desired assets by replacing the image files in this directory. | |||||
| You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. | |||||
| @@ -0,0 +1,37 @@ | |||||
| <?xml version="1.0" encoding="UTF-8" standalone="no"?> | |||||
| <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM"> | |||||
| <dependencies> | |||||
| <deployment identifier="iOS"/> | |||||
| <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/> | |||||
| </dependencies> | |||||
| <scenes> | |||||
| <!--View Controller--> | |||||
| <scene sceneID="EHf-IW-A2E"> | |||||
| <objects> | |||||
| <viewController id="01J-lp-oVM" sceneMemberID="viewController"> | |||||
| <layoutGuides> | |||||
| <viewControllerLayoutGuide type="top" id="Ydg-fD-yQy"/> | |||||
| <viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/> | |||||
| </layoutGuides> | |||||
| <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3"> | |||||
| <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> | |||||
| <subviews> | |||||
| <imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4"> | |||||
| </imageView> | |||||
| </subviews> | |||||
| <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> | |||||
| <constraints> | |||||
| <constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/> | |||||
| <constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/> | |||||
| </constraints> | |||||
| </view> | |||||
| </viewController> | |||||
| <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/> | |||||
| </objects> | |||||
| <point key="canvasLocation" x="53" y="375"/> | |||||
| </scene> | |||||
| </scenes> | |||||
| <resources> | |||||
| <image name="LaunchImage" width="168" height="185"/> | |||||
| </resources> | |||||
| </document> | |||||
| @@ -0,0 +1,26 @@ | |||||
| <?xml version="1.0" encoding="UTF-8" standalone="no"?> | |||||
| <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r"> | |||||
| <dependencies> | |||||
| <deployment identifier="iOS"/> | |||||
| <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/> | |||||
| </dependencies> | |||||
| <scenes> | |||||
| <!--Flutter View Controller--> | |||||
| <scene sceneID="tne-QT-ifu"> | |||||
| <objects> | |||||
| <viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController"> | |||||
| <layoutGuides> | |||||
| <viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/> | |||||
| <viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/> | |||||
| </layoutGuides> | |||||
| <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC"> | |||||
| <rect key="frame" x="0.0" y="0.0" width="600" height="600"/> | |||||
| <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> | |||||
| <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/> | |||||
| </view> | |||||
| </viewController> | |||||
| <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/> | |||||
| </objects> | |||||
| </scene> | |||||
| </scenes> | |||||
| </document> | |||||
| @@ -0,0 +1,45 @@ | |||||
| <?xml version="1.0" encoding="UTF-8"?> | |||||
| <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |||||
| <plist version="1.0"> | |||||
| <dict> | |||||
| <key>CFBundleDevelopmentRegion</key> | |||||
| <string>$(DEVELOPMENT_LANGUAGE)</string> | |||||
| <key>CFBundleExecutable</key> | |||||
| <string>$(EXECUTABLE_NAME)</string> | |||||
| <key>CFBundleIdentifier</key> | |||||
| <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> | |||||
| <key>CFBundleInfoDictionaryVersion</key> | |||||
| <string>6.0</string> | |||||
| <key>CFBundleName</key> | |||||
| <string>myketpayment_example</string> | |||||
| <key>CFBundlePackageType</key> | |||||
| <string>APPL</string> | |||||
| <key>CFBundleShortVersionString</key> | |||||
| <string>$(FLUTTER_BUILD_NAME)</string> | |||||
| <key>CFBundleSignature</key> | |||||
| <string>????</string> | |||||
| <key>CFBundleVersion</key> | |||||
| <string>$(FLUTTER_BUILD_NUMBER)</string> | |||||
| <key>LSRequiresIPhoneOS</key> | |||||
| <true/> | |||||
| <key>UILaunchStoryboardName</key> | |||||
| <string>LaunchScreen</string> | |||||
| <key>UIMainStoryboardFile</key> | |||||
| <string>Main</string> | |||||
| <key>UISupportedInterfaceOrientations</key> | |||||
| <array> | |||||
| <string>UIInterfaceOrientationPortrait</string> | |||||
| <string>UIInterfaceOrientationLandscapeLeft</string> | |||||
| <string>UIInterfaceOrientationLandscapeRight</string> | |||||
| </array> | |||||
| <key>UISupportedInterfaceOrientations~ipad</key> | |||||
| <array> | |||||
| <string>UIInterfaceOrientationPortrait</string> | |||||
| <string>UIInterfaceOrientationPortraitUpsideDown</string> | |||||
| <string>UIInterfaceOrientationLandscapeLeft</string> | |||||
| <string>UIInterfaceOrientationLandscapeRight</string> | |||||
| </array> | |||||
| <key>UIViewControllerBasedStatusBarAppearance</key> | |||||
| <false/> | |||||
| </dict> | |||||
| </plist> | |||||
| @@ -0,0 +1,9 @@ | |||||
| #import <Flutter/Flutter.h> | |||||
| #import <UIKit/UIKit.h> | |||||
| #import "AppDelegate.h" | |||||
| int main(int argc, char* argv[]) { | |||||
| @autoreleasepool { | |||||
| return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,87 @@ | |||||
| import 'package:flutter/material.dart'; | |||||
| import 'dart:async'; | |||||
| import 'package:flutter/services.dart'; | |||||
| import 'package:myketpayment/myketpayment.dart'; | |||||
| void main() { | |||||
| runApp(MyApp()); | |||||
| } | |||||
| class MyApp extends StatefulWidget { | |||||
| @override | |||||
| _MyAppState createState() => _MyAppState(); | |||||
| } | |||||
| class _MyAppState extends State<MyApp> { | |||||
| String _platformVersion = 'Unknown'; | |||||
| @override | |||||
| void initState() { | |||||
| super.initState(); | |||||
| } | |||||
| final String rsa = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCPBy3LGWCeF5AwPIVdS6DvkTHkS9qa45vNhpZiJTjELjG1VLa9a8nAsm4E6qqKoQ6wh5Cuq3T9NqdtkTwWtLgVYvTl6JQlkN/2XfabkWcn58f14mvrkVv8qHUFr0m/kqz9sp/fk1KvS16BjVy/M3ScuvLr0ONJ+HS5PQvHUTdDLQIDAQAB"; | |||||
| bool setup = false; | |||||
| @override | |||||
| Widget build(BuildContext context) { | |||||
| return MaterialApp( | |||||
| home: Scaffold( | |||||
| appBar: AppBar( | |||||
| title: const Text('Plugin example app'), | |||||
| ), | |||||
| body: Center( | |||||
| child: Column( | |||||
| children: [ | |||||
| Text('myket for appeto'), | |||||
| SizedBox(height: 20,), | |||||
| FlatButton( | |||||
| child: Text("buy and consume"), | |||||
| onPressed: () async { | |||||
| if(!setup) { | |||||
| setup = await Myketpayment.setup(rsa); | |||||
| } | |||||
| print("setup: $setup"); | |||||
| if(setup) { | |||||
| final result = await Myketpayment.buy(sku: 'myflutter', consume: true); | |||||
| afterPurchase(result); | |||||
| } | |||||
| else { | |||||
| print("can not connect to myket"); | |||||
| } | |||||
| }, | |||||
| ), | |||||
| SizedBox(height: 20,), | |||||
| FlatButton( | |||||
| child: Text("buy unlimit"), | |||||
| onPressed: () async { | |||||
| if(!setup) { | |||||
| setup = await Myketpayment.setup(rsa); | |||||
| } | |||||
| print("setup: $setup"); | |||||
| if(setup) { | |||||
| final result = await Myketpayment.buy(sku: 'flunlimit'); | |||||
| afterPurchase(result); | |||||
| } | |||||
| else { | |||||
| print("can not connect to myket"); | |||||
| } | |||||
| }, | |||||
| ), | |||||
| ], | |||||
| ), | |||||
| ), | |||||
| ), | |||||
| ); | |||||
| } | |||||
| void afterPurchase(Map result) { | |||||
| if(result.containsKey('purchased') && result['purchased'] == true) { | |||||
| print("purchase info: $result"); | |||||
| } | |||||
| else { | |||||
| print("no purchase: $result"); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,154 @@ | |||||
| # Generated by pub | |||||
| # See https://dart.dev/tools/pub/glossary#lockfile | |||||
| packages: | |||||
| async: | |||||
| dependency: transitive | |||||
| description: | |||||
| name: async | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "2.4.1" | |||||
| boolean_selector: | |||||
| dependency: transitive | |||||
| description: | |||||
| name: boolean_selector | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "2.0.0" | |||||
| charcode: | |||||
| dependency: transitive | |||||
| description: | |||||
| name: charcode | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "1.1.3" | |||||
| clock: | |||||
| dependency: transitive | |||||
| description: | |||||
| name: clock | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "1.0.1" | |||||
| collection: | |||||
| dependency: transitive | |||||
| description: | |||||
| name: collection | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "1.14.12" | |||||
| cupertino_icons: | |||||
| dependency: "direct main" | |||||
| description: | |||||
| name: cupertino_icons | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "0.1.3" | |||||
| fake_async: | |||||
| dependency: transitive | |||||
| description: | |||||
| name: fake_async | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "1.1.0" | |||||
| flutter: | |||||
| dependency: "direct main" | |||||
| description: flutter | |||||
| source: sdk | |||||
| version: "0.0.0" | |||||
| flutter_test: | |||||
| dependency: "direct dev" | |||||
| description: flutter | |||||
| source: sdk | |||||
| version: "0.0.0" | |||||
| matcher: | |||||
| dependency: transitive | |||||
| description: | |||||
| name: matcher | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "0.12.6" | |||||
| meta: | |||||
| dependency: transitive | |||||
| description: | |||||
| name: meta | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "1.1.8" | |||||
| myketpayment: | |||||
| dependency: "direct main" | |||||
| description: | |||||
| path: ".." | |||||
| relative: true | |||||
| source: path | |||||
| version: "0.0.1" | |||||
| path: | |||||
| dependency: transitive | |||||
| description: | |||||
| name: path | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "1.7.0" | |||||
| sky_engine: | |||||
| dependency: transitive | |||||
| description: flutter | |||||
| source: sdk | |||||
| version: "0.0.99" | |||||
| source_span: | |||||
| dependency: transitive | |||||
| description: | |||||
| name: source_span | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "1.7.0" | |||||
| stack_trace: | |||||
| dependency: transitive | |||||
| description: | |||||
| name: stack_trace | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "1.9.3" | |||||
| stream_channel: | |||||
| dependency: transitive | |||||
| description: | |||||
| name: stream_channel | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "2.0.0" | |||||
| string_scanner: | |||||
| dependency: transitive | |||||
| description: | |||||
| name: string_scanner | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "1.0.5" | |||||
| term_glyph: | |||||
| dependency: transitive | |||||
| description: | |||||
| name: term_glyph | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "1.1.0" | |||||
| test_api: | |||||
| dependency: transitive | |||||
| description: | |||||
| name: test_api | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "0.2.15" | |||||
| typed_data: | |||||
| dependency: transitive | |||||
| description: | |||||
| name: typed_data | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "1.1.6" | |||||
| vector_math: | |||||
| dependency: transitive | |||||
| description: | |||||
| name: vector_math | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "2.0.8" | |||||
| sdks: | |||||
| dart: ">=2.7.0 <3.0.0" | |||||
| flutter: ">=1.10.0" | |||||
| @@ -0,0 +1,71 @@ | |||||
| name: myketpayment_example | |||||
| description: Add myket in app purchase for appeto team. | |||||
| # The following line prevents the package from being accidentally published to | |||||
| # pub.dev using `pub publish`. This is preferred for private packages. | |||||
| publish_to: 'none' # Remove this line if you wish to publish to pub.dev | |||||
| environment: | |||||
| sdk: ">=2.7.0 <3.0.0" | |||||
| dependencies: | |||||
| flutter: | |||||
| sdk: flutter | |||||
| myketpayment: | |||||
| # When depending on this package from a real application you should use: | |||||
| # myketpayment: ^x.y.z | |||||
| # See https://dart.dev/tools/pub/dependencies#version-constraints | |||||
| # The example app is bundled with the plugin so we use a path dependency on | |||||
| # the parent directory to use the current plugin's version. | |||||
| path: ../ | |||||
| # The following adds the Cupertino Icons font to your application. | |||||
| # Use with the CupertinoIcons class for iOS style icons. | |||||
| cupertino_icons: ^0.1.3 | |||||
| dev_dependencies: | |||||
| flutter_test: | |||||
| sdk: flutter | |||||
| # For information on the generic Dart part of this file, see the | |||||
| # following page: https://dart.dev/tools/pub/pubspec | |||||
| # The following section is specific to Flutter. | |||||
| flutter: | |||||
| # The following line ensures that the Material Icons font is | |||||
| # included with your application, so that you can use the icons in | |||||
| # the material Icons class. | |||||
| uses-material-design: true | |||||
| # To add assets to your application, add an assets section, like this: | |||||
| # assets: | |||||
| # - images/a_dot_burr.jpeg | |||||
| # - images/a_dot_ham.jpeg | |||||
| # An image asset can refer to one or more resolution-specific "variants", see | |||||
| # https://flutter.dev/assets-and-images/#resolution-aware. | |||||
| # For details regarding adding assets from package dependencies, see | |||||
| # https://flutter.dev/assets-and-images/#from-packages | |||||
| # To add custom fonts to your application, add a fonts section here, | |||||
| # in this "flutter" section. Each entry in this list should have a | |||||
| # "family" key with the font family name, and a "fonts" key with a | |||||
| # list giving the asset and other descriptors for the font. For | |||||
| # example: | |||||
| # fonts: | |||||
| # - family: Schyler | |||||
| # fonts: | |||||
| # - asset: fonts/Schyler-Regular.ttf | |||||
| # - asset: fonts/Schyler-Italic.ttf | |||||
| # style: italic | |||||
| # - family: Trajan Pro | |||||
| # fonts: | |||||
| # - asset: fonts/TrajanPro.ttf | |||||
| # - asset: fonts/TrajanPro_Bold.ttf | |||||
| # weight: 700 | |||||
| # | |||||
| # For details regarding fonts from package dependencies, | |||||
| # see https://flutter.dev/custom-fonts/#from-packages | |||||
| @@ -0,0 +1,27 @@ | |||||
| // This is a basic Flutter widget test. | |||||
| // | |||||
| // To perform an interaction with a widget in your test, use the WidgetTester | |||||
| // utility that Flutter provides. For example, you can send tap and scroll | |||||
| // gestures. You can also use WidgetTester to find child widgets in the widget | |||||
| // tree, read text, and verify that the values of widget properties are correct. | |||||
| import 'package:flutter/material.dart'; | |||||
| import 'package:flutter_test/flutter_test.dart'; | |||||
| import 'package:myketpayment_example/main.dart'; | |||||
| void main() { | |||||
| testWidgets('Verify Platform version', (WidgetTester tester) async { | |||||
| // Build our app and trigger a frame. | |||||
| await tester.pumpWidget(MyApp()); | |||||
| // Verify that platform version is retrieved. | |||||
| expect( | |||||
| find.byWidgetPredicate( | |||||
| (Widget widget) => widget is Text && | |||||
| widget.data.startsWith('Running on:'), | |||||
| ), | |||||
| findsOneWidget, | |||||
| ); | |||||
| }); | |||||
| } | |||||
| @@ -0,0 +1,33 @@ | |||||
| <!DOCTYPE html> | |||||
| <html> | |||||
| <head> | |||||
| <meta charset="UTF-8"> | |||||
| <meta content="IE=Edge" http-equiv="X-UA-Compatible"> | |||||
| <meta name="description" content="Demonstrates how to use the myketpayment plugin."> | |||||
| <!-- iOS meta tags & icons --> | |||||
| <meta name="apple-mobile-web-app-capable" content="yes"> | |||||
| <meta name="apple-mobile-web-app-status-bar-style" content="black"> | |||||
| <meta name="apple-mobile-web-app-title" content="myketpayment_example"> | |||||
| <link rel="apple-touch-icon" href="icons/Icon-192.png"> | |||||
| <!-- Favicon --> | |||||
| <link rel="shortcut icon" type="image/png" href="favicon.png"/> | |||||
| <title>myketpayment_example</title> | |||||
| <link rel="manifest" href="manifest.json"> | |||||
| </head> | |||||
| <body> | |||||
| <!-- This script installs service_worker.js to provide PWA functionality to | |||||
| application. For more information, see: | |||||
| https://developers.google.com/web/fundamentals/primers/service-workers --> | |||||
| <script> | |||||
| if ('serviceWorker' in navigator) { | |||||
| window.addEventListener('load', function () { | |||||
| navigator.serviceWorker.register('flutter_service_worker.js'); | |||||
| }); | |||||
| } | |||||
| </script> | |||||
| <script src="main.dart.js" type="application/javascript"></script> | |||||
| </body> | |||||
| </html> | |||||
| @@ -0,0 +1,23 @@ | |||||
| { | |||||
| "name": "myketpayment_example", | |||||
| "short_name": "myketpayment_example", | |||||
| "start_url": ".", | |||||
| "display": "standalone", | |||||
| "background_color": "#0175C2", | |||||
| "theme_color": "#0175C2", | |||||
| "description": "Demonstrates how to use the myketpayment plugin.", | |||||
| "orientation": "portrait-primary", | |||||
| "prefer_related_applications": false, | |||||
| "icons": [ | |||||
| { | |||||
| "src": "icons/Icon-192.png", | |||||
| "sizes": "192x192", | |||||
| "type": "image/png" | |||||
| }, | |||||
| { | |||||
| "src": "icons/Icon-512.png", | |||||
| "sizes": "512x512", | |||||
| "type": "image/png" | |||||
| } | |||||
| ] | |||||
| } | |||||
| @@ -0,0 +1,37 @@ | |||||
| .idea/ | |||||
| .vagrant/ | |||||
| .sconsign.dblite | |||||
| .svn/ | |||||
| .DS_Store | |||||
| *.swp | |||||
| profile | |||||
| DerivedData/ | |||||
| build/ | |||||
| GeneratedPluginRegistrant.h | |||||
| GeneratedPluginRegistrant.m | |||||
| .generated/ | |||||
| *.pbxuser | |||||
| *.mode1v3 | |||||
| *.mode2v3 | |||||
| *.perspectivev3 | |||||
| !default.pbxuser | |||||
| !default.mode1v3 | |||||
| !default.mode2v3 | |||||
| !default.perspectivev3 | |||||
| xcuserdata | |||||
| *.moved-aside | |||||
| *.pyc | |||||
| *sync/ | |||||
| Icon? | |||||
| .tags* | |||||
| /Flutter/Generated.xcconfig | |||||
| /Flutter/flutter_export_environment.sh | |||||
| @@ -0,0 +1,4 @@ | |||||
| #import <Flutter/Flutter.h> | |||||
| @interface MyketpaymentPlugin : NSObject<FlutterPlugin> | |||||
| @end | |||||
| @@ -0,0 +1,20 @@ | |||||
| #import "MyketpaymentPlugin.h" | |||||
| @implementation MyketpaymentPlugin | |||||
| + (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar { | |||||
| FlutterMethodChannel* channel = [FlutterMethodChannel | |||||
| methodChannelWithName:@"myketpayment" | |||||
| binaryMessenger:[registrar messenger]]; | |||||
| MyketpaymentPlugin* instance = [[MyketpaymentPlugin alloc] init]; | |||||
| [registrar addMethodCallDelegate:instance channel:channel]; | |||||
| } | |||||
| - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { | |||||
| if ([@"getPlatformVersion" isEqualToString:call.method]) { | |||||
| result([@"iOS " stringByAppendingString:[[UIDevice currentDevice] systemVersion]]); | |||||
| } else { | |||||
| result(FlutterMethodNotImplemented); | |||||
| } | |||||
| } | |||||
| @end | |||||
| @@ -0,0 +1,23 @@ | |||||
| # | |||||
| # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html. | |||||
| # Run `pod lib lint myketpayment.podspec' to validate before publishing. | |||||
| # | |||||
| Pod::Spec.new do |s| | |||||
| s.name = 'myketpayment' | |||||
| s.version = '0.0.1' | |||||
| s.summary = 'Add myket in app purchase' | |||||
| s.description = <<-DESC | |||||
| Add myket in app purchase | |||||
| DESC | |||||
| s.homepage = 'http://example.com' | |||||
| s.license = { :file => '../LICENSE' } | |||||
| s.author = { 'Your Company' => 'email@example.com' } | |||||
| s.source = { :path => '.' } | |||||
| s.source_files = 'Classes/**/*' | |||||
| s.public_header_files = 'Classes/**/*.h' | |||||
| s.dependency 'Flutter' | |||||
| s.platform = :ios, '8.0' | |||||
| # Flutter.framework does not contain a i386 slice. Only x86_64 simulators are supported. | |||||
| s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'VALID_ARCHS[sdk=iphonesimulator*]' => 'x86_64' } | |||||
| end | |||||
| @@ -0,0 +1,21 @@ | |||||
| import 'dart:async'; | |||||
| import 'dart:convert'; | |||||
| import 'package:flutter/services.dart'; | |||||
| class Myketpayment { | |||||
| static const MethodChannel _channel = const MethodChannel('myketpayment'); | |||||
| static Future<bool> setup(String rsa) async { | |||||
| final bool version = await _channel.invokeMethod('setup', {"rsa": rsa}); | |||||
| return version; | |||||
| } | |||||
| static Future<Map> buy({String sku, bool consume = false, String payload = ""}) async { | |||||
| Map result = await _channel.invokeMethod('buy', {"sku": sku, "payload": payload, "consume": consume}); | |||||
| return result; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,19 @@ | |||||
| <?xml version="1.0" encoding="UTF-8"?> | |||||
| <module type="JAVA_MODULE" version="4"> | |||||
| <component name="NewModuleRootManager" inherit-compiler-output="true"> | |||||
| <exclude-output /> | |||||
| <content url="file://$MODULE_DIR$"> | |||||
| <sourceFolder url="file://$MODULE_DIR$/lib" isTestSource="false" /> | |||||
| <excludeFolder url="file://$MODULE_DIR$/.dart_tool" /> | |||||
| <excludeFolder url="file://$MODULE_DIR$/.idea" /> | |||||
| <excludeFolder url="file://$MODULE_DIR$/.pub" /> | |||||
| <excludeFolder url="file://$MODULE_DIR$/build" /> | |||||
| <excludeFolder url="file://$MODULE_DIR$/example/.dart_tool" /> | |||||
| <excludeFolder url="file://$MODULE_DIR$/example/.pub" /> | |||||
| <excludeFolder url="file://$MODULE_DIR$/example/build" /> | |||||
| </content> | |||||
| <orderEntry type="sourceFolder" forTests="false" /> | |||||
| <orderEntry type="library" name="Dart SDK" level="project" /> | |||||
| <orderEntry type="library" name="Flutter Plugins" level="project" /> | |||||
| </component> | |||||
| </module> | |||||
| @@ -0,0 +1,140 @@ | |||||
| # Generated by pub | |||||
| # See https://dart.dev/tools/pub/glossary#lockfile | |||||
| packages: | |||||
| async: | |||||
| dependency: transitive | |||||
| description: | |||||
| name: async | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "2.4.1" | |||||
| boolean_selector: | |||||
| dependency: transitive | |||||
| description: | |||||
| name: boolean_selector | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "2.0.0" | |||||
| charcode: | |||||
| dependency: transitive | |||||
| description: | |||||
| name: charcode | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "1.1.3" | |||||
| clock: | |||||
| dependency: transitive | |||||
| description: | |||||
| name: clock | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "1.0.1" | |||||
| collection: | |||||
| dependency: transitive | |||||
| description: | |||||
| name: collection | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "1.14.12" | |||||
| fake_async: | |||||
| dependency: transitive | |||||
| description: | |||||
| name: fake_async | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "1.1.0" | |||||
| flutter: | |||||
| dependency: "direct main" | |||||
| description: flutter | |||||
| source: sdk | |||||
| version: "0.0.0" | |||||
| flutter_test: | |||||
| dependency: "direct dev" | |||||
| description: flutter | |||||
| source: sdk | |||||
| version: "0.0.0" | |||||
| matcher: | |||||
| dependency: transitive | |||||
| description: | |||||
| name: matcher | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "0.12.6" | |||||
| meta: | |||||
| dependency: transitive | |||||
| description: | |||||
| name: meta | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "1.1.8" | |||||
| path: | |||||
| dependency: transitive | |||||
| description: | |||||
| name: path | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "1.7.0" | |||||
| sky_engine: | |||||
| dependency: transitive | |||||
| description: flutter | |||||
| source: sdk | |||||
| version: "0.0.99" | |||||
| source_span: | |||||
| dependency: transitive | |||||
| description: | |||||
| name: source_span | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "1.7.0" | |||||
| stack_trace: | |||||
| dependency: transitive | |||||
| description: | |||||
| name: stack_trace | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "1.9.3" | |||||
| stream_channel: | |||||
| dependency: transitive | |||||
| description: | |||||
| name: stream_channel | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "2.0.0" | |||||
| string_scanner: | |||||
| dependency: transitive | |||||
| description: | |||||
| name: string_scanner | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "1.0.5" | |||||
| term_glyph: | |||||
| dependency: transitive | |||||
| description: | |||||
| name: term_glyph | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "1.1.0" | |||||
| test_api: | |||||
| dependency: transitive | |||||
| description: | |||||
| name: test_api | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "0.2.15" | |||||
| typed_data: | |||||
| dependency: transitive | |||||
| description: | |||||
| name: typed_data | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "1.1.6" | |||||
| vector_math: | |||||
| dependency: transitive | |||||
| description: | |||||
| name: vector_math | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "2.0.8" | |||||
| sdks: | |||||
| dart: ">=2.7.0 <3.0.0" | |||||
| flutter: ">=1.10.0" | |||||
| @@ -0,0 +1,65 @@ | |||||
| name: myketpayment | |||||
| description: Add myket in app purchase | |||||
| version: 0.0.1 | |||||
| author: | |||||
| homepage: | |||||
| environment: | |||||
| sdk: ">=2.7.0 <3.0.0" | |||||
| flutter: ">=1.10.0" | |||||
| dependencies: | |||||
| flutter: | |||||
| sdk: flutter | |||||
| dev_dependencies: | |||||
| flutter_test: | |||||
| sdk: flutter | |||||
| # For information on the generic Dart part of this file, see the | |||||
| # following page: https://dart.dev/tools/pub/pubspec | |||||
| # The following section is specific to Flutter. | |||||
| flutter: | |||||
| # This section identifies this Flutter project as a plugin project. | |||||
| # The 'pluginClass' and Android 'package' identifiers should not ordinarily | |||||
| # be modified. They are used by the tooling to maintain consistency when | |||||
| # adding or updating assets for this project. | |||||
| plugin: | |||||
| platforms: | |||||
| android: | |||||
| package: ir.appeto.myketpayment | |||||
| pluginClass: MyketpaymentPlugin | |||||
| ios: | |||||
| pluginClass: MyketpaymentPlugin | |||||
| # To add assets to your plugin package, add an assets section, like this: | |||||
| # assets: | |||||
| # - images/a_dot_burr.jpeg | |||||
| # - images/a_dot_ham.jpeg | |||||
| # | |||||
| # For details regarding assets in packages, see | |||||
| # https://flutter.dev/assets-and-images/#from-packages | |||||
| # | |||||
| # An image asset can refer to one or more resolution-specific "variants", see | |||||
| # https://flutter.dev/assets-and-images/#resolution-aware. | |||||
| # To add custom fonts to your plugin package, add a fonts section here, | |||||
| # in this "flutter" section. Each entry in this list should have a | |||||
| # "family" key with the font family name, and a "fonts" key with a | |||||
| # list giving the asset and other descriptors for the font. For | |||||
| # example: | |||||
| # fonts: | |||||
| # - family: Schyler | |||||
| # fonts: | |||||
| # - asset: fonts/Schyler-Regular.ttf | |||||
| # - asset: fonts/Schyler-Italic.ttf | |||||
| # style: italic | |||||
| # - family: Trajan Pro | |||||
| # fonts: | |||||
| # - asset: fonts/TrajanPro.ttf | |||||
| # - asset: fonts/TrajanPro_Bold.ttf | |||||
| # weight: 700 | |||||
| # | |||||
| # For details regarding fonts in packages, see | |||||
| # https://flutter.dev/custom-fonts/#from-packages | |||||
| @@ -0,0 +1,23 @@ | |||||
| import 'package:flutter/services.dart'; | |||||
| import 'package:flutter_test/flutter_test.dart'; | |||||
| import 'package:myketpayment/myketpayment.dart'; | |||||
| void main() { | |||||
| const MethodChannel channel = MethodChannel('myketpayment'); | |||||
| TestWidgetsFlutterBinding.ensureInitialized(); | |||||
| setUp(() { | |||||
| channel.setMockMethodCallHandler((MethodCall methodCall) async { | |||||
| return '42'; | |||||
| }); | |||||
| }); | |||||
| tearDown(() { | |||||
| channel.setMockMethodCallHandler(null); | |||||
| }); | |||||
| test('getPlatformVersion', () async { | |||||
| expect(await Myketpayment.platformVersion, '42'); | |||||
| }); | |||||
| } | |||||