diff --git a/.gitignore b/.gitignore index 9baf46d8..2becffa8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,12 +1,47 @@ .DS_Store .atom/ -.idea +.idea/ +.vscode/ + .packages .pub/ -build/ -ios/.generated/ -packages +.dart_tool/ pubspec.lock -example/ios/Flutter/ -example/.dart_tool -example/ios/.symlinks \ No newline at end of file +flutter_export_environment.sh + +examples/all_plugins/pubspec.yaml + +Podfile.lock +Pods/ +.symlinks/ +**/Flutter/App.framework/ +**/Flutter/ephemeral/ +**/Flutter/Flutter.framework/ +**/Flutter/Generated.xcconfig +**/Flutter/flutter_assets/ + +ServiceDefinitions.json +xcuserdata/ +**/DerivedData/ + +local.properties +keystore.properties +.gradle/ +gradlew +gradlew.bat +gradle-wrapper.jar +.flutter-plugins-dependencies +*.iml + +GeneratedPluginRegistrant.h +GeneratedPluginRegistrant.m +GeneratedPluginRegistrant.java +GeneratedPluginRegistrant.swift +build/ +.flutter-plugins + +.project +.classpath +.settings + +example/ios/Flutter/Flutter.podspec diff --git a/CHANGELOG.md b/CHANGELOG.md index aee2b892..8af9380b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,34 @@ +## [1.1.4] +- Fix #311 + +## [1.1.3] +- Fix #301, #304, #305 + +## [1.1.1] +- add information about the plugin being discontinued and its replacement + +## [1.1.0] +- support for null safety +- Xcode 12.5 is not supported - see this [discussion](https://github.com/jonasbark/flutter_stripe_payment/issues/284#issuecomment-828293850) for a fix + +## [1.0.11] +- fix #258 (by @Trede98) + +## [1.0.10] +- update sdk signature information (by @davidme-stripe) + +## [1.0.9] +- fix issues with Stripe iOS dependency + +## [1.0.8] +- fix errors with shippingMethod for Apple Play (thanks @andhieka) +- preserve card name on iOS (thanks @brauliolomeli) +- currency support for CreditCard model (thanks @cis-emp1822) + +## [1.0.7] +- update Stripe iOS dependency to support Xcode 11.4 (#131) +- bump Android gradle for latest Flutter support (thanks @ened) + ## [1.0.6] - fix #97 (thanks @sandeep-at-airlift) - support Stripe Connected accounts (thanks @nicowernli) diff --git a/README.md b/README.md index 52a6d5ac..a30595f9 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,7 @@ +> **⚠ WARNING: This plugin has been discontinued.** +> Head over to [migration.md](migration.md) for migrate to the new flutter_stripe plugin + + [![pub package](https://img.shields.io/pub/v/stripe_payment.svg)](https://pub.dev/packages/stripe_payment) # stripe_payment @@ -6,9 +10,9 @@ ## Quick Glance -- This Flutter plugin is a straight port from tipsi-stripe plugin for React Native - we tried to -keep the API as close as possible so the documentation applies this this plugin as well. -- Collect chargable tokens from users' **Card Input** and **Apple & Google Pay** +- This Flutter plugin is a straight port from the tipsi-stripe plugin for React Native - we tried to +keep the API as close as possible, so the documentation applies this plugin. +- Collect chargeable tokens from users' **Card Input** and** Apple & Google Pay**. - For **SCA** compliant apps, setup payment intents for later confirmation. ## Supported features: @@ -57,4 +61,10 @@ As this plugin is a port from tipsi-stripe for React Native you may consult thei https://github.com/tipsi/tipsi-stripe/tree/experimental-connect/website/docs-md It includes: - how to setup Google / Apple Pay -- method documentations \ No newline at end of file +- method documentations + +## Blog Posts +- [Build a marketplace in your Flutter app and accept payments using Stripe and Firebase](https://medium.com/flutter-community/build-a-marketplace-in-your-flutter-app-and-accept-payments-using-stripe-and-firebase-72f3f7228625) + +## Xcode 12.5 support +Xcode 12.5 is not supported - see this [discussion](https://github.com/jonasbark/flutter_stripe_payment/issues/284#issuecomment-828293850) for a fix diff --git a/android/build.gradle b/android/build.gradle index 213424c3..faacca8a 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -9,8 +9,8 @@ buildscript { } dependencies { - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.50" - classpath 'com.android.tools.build:gradle:3.5.0' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.70" + classpath 'com.android.tools.build:gradle:3.6.1' } } @@ -68,8 +68,9 @@ android { } dependencies { - api 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.50' - implementation 'com.android.support:support-annotations:28.0.0' - implementation 'com.stripe:stripe-android:10.4.6' + api 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.70' + implementation 'androidx.annotation:annotation:1.1.0' + implementation 'com.stripe:stripe-android:16.10.0' + implementation 'com.android.support:appcompat-v7:28.0.0' implementation 'com.google.android.gms:play-services-wallet:18.0.0' } diff --git a/android/gradle/wrapper/gradle-wrapper.jar b/android/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index f6b961fd..00000000 Binary files a/android/gradle/wrapper/gradle-wrapper.jar and /dev/null differ diff --git a/android/gradlew b/android/gradlew deleted file mode 100644 index cccdd3d5..00000000 --- a/android/gradlew +++ /dev/null @@ -1,172 +0,0 @@ -#!/usr/bin/env sh - -############################################################################## -## -## Gradle start up script for UN*X -## -############################################################################## - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn () { - echo "$*" -} - -die () { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=$((i+1)) - done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=$(save "$@") - -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" - -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi - -exec "$JAVACMD" "$@" diff --git a/android/gradlew.bat b/android/gradlew.bat deleted file mode 100644 index f9553162..00000000 --- a/android/gradlew.bat +++ /dev/null @@ -1,84 +0,0 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/android/src/main/java/com/gettipsi/stripe/GoogleApiPayFlowImpl.java b/android/src/main/java/com/gettipsi/stripe/GoogleApiPayFlowImpl.java index 0d2dbfac..c08d4a63 100644 --- a/android/src/main/java/com/gettipsi/stripe/GoogleApiPayFlowImpl.java +++ b/android/src/main/java/com/gettipsi/stripe/GoogleApiPayFlowImpl.java @@ -2,6 +2,7 @@ import android.app.Activity; import android.content.Intent; + import androidx.annotation.NonNull; import com.facebook.react.bridge.Promise; @@ -24,9 +25,12 @@ import com.google.android.gms.wallet.TransactionInfo; import com.google.android.gms.wallet.Wallet; import com.google.android.gms.wallet.WalletConstants; -import com.stripe.android.BuildConfig; +import com.stripe.android.Stripe; import com.stripe.android.model.Token; +import org.json.JSONException; +import org.json.JSONObject; + import java.util.Arrays; import java.util.Collection; @@ -35,11 +39,11 @@ import static com.gettipsi.stripe.util.Converters.getAllowedShippingCountryCodes; import static com.gettipsi.stripe.util.Converters.getBillingAddress; import static com.gettipsi.stripe.util.Converters.putExtraToTokenMap; -import static com.gettipsi.stripe.util.PayParams.CURRENCY_CODE; import static com.gettipsi.stripe.util.PayParams.BILLING_ADDRESS_REQUIRED; -import static com.gettipsi.stripe.util.PayParams.SHIPPING_ADDRESS_REQUIRED; -import static com.gettipsi.stripe.util.PayParams.PHONE_NUMBER_REQUIRED; +import static com.gettipsi.stripe.util.PayParams.CURRENCY_CODE; import static com.gettipsi.stripe.util.PayParams.EMAIL_REQUIRED; +import static com.gettipsi.stripe.util.PayParams.PHONE_NUMBER_REQUIRED; +import static com.gettipsi.stripe.util.PayParams.SHIPPING_ADDRESS_REQUIRED; import static com.gettipsi.stripe.util.PayParams.TOTAL_PRICE; /** @@ -94,7 +98,7 @@ private PaymentMethodTokenizationParameters createPaymentMethodTokenizationParam .setPaymentMethodTokenizationType(WalletConstants.PAYMENT_METHOD_TOKENIZATION_TYPE_PAYMENT_GATEWAY) .addParameter("gateway", "stripe") .addParameter("stripe:publishableKey", getPublishableKey()) - .addParameter("stripe:version", BuildConfig.VERSION_NAME) + .addParameter("stripe:version", Stripe.VERSION) .build(); } @@ -230,7 +234,13 @@ public boolean onActivityResult(Activity activity, int requestCode, int resultCo PaymentData paymentData = PaymentData.getFromIntent(data); ArgCheck.nonNull(paymentData); String tokenJson = paymentData.getPaymentMethodToken().getToken(); - Token token = Token.fromString(tokenJson); + Token token = null; + try { + JSONObject obj = new JSONObject(tokenJson); + token = Token.fromJson(obj); + } catch (JSONException e) { + e.printStackTrace(); + } if (token == null) { payPromise.reject( getErrorCode("parseResponse"), diff --git a/android/src/main/java/com/gettipsi/stripe/StripeModule.java b/android/src/main/java/com/gettipsi/stripe/StripeModule.java index 77f58bdc..07bfb0a7 100644 --- a/android/src/main/java/com/gettipsi/stripe/StripeModule.java +++ b/android/src/main/java/com/gettipsi/stripe/StripeModule.java @@ -6,29 +6,70 @@ import android.net.Uri; import android.os.AsyncTask; import android.text.TextUtils; + import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import com.facebook.react.bridge.*; + +import com.facebook.react.bridge.ActivityEventListener; +import com.facebook.react.bridge.BaseActivityEventListener; +import com.facebook.react.bridge.Promise; +import com.facebook.react.bridge.ReactContextBaseJavaModule; +import com.facebook.react.bridge.ReactMethod; +import com.facebook.react.bridge.ReadableMap; import com.gettipsi.stripe.util.ArgCheck; import com.gettipsi.stripe.util.Converters; import com.gettipsi.stripe.util.Fun0; import com.google.android.gms.wallet.WalletConstants; -import com.stripe.android.*; -import com.stripe.android.model.*; +import com.stripe.android.ApiResultCallback; +import com.stripe.android.AppInfo; +import com.stripe.android.PaymentConfiguration; +import com.stripe.android.PaymentIntentResult; +import com.stripe.android.SetupIntentResult; +import com.stripe.android.Stripe; +import com.stripe.android.model.Address; +import com.stripe.android.model.ConfirmPaymentIntentParams; +import com.stripe.android.model.ConfirmSetupIntentParams; +import com.stripe.android.model.PaymentMethod; +import com.stripe.android.model.PaymentMethodCreateParams; +import com.stripe.android.model.Source; +import com.stripe.android.model.SourceParams; +import com.stripe.android.model.StripeIntent; +import com.stripe.android.model.Token; + +import java.util.HashMap; +import java.util.Map; import de.jonasbark.stripepayment.StripeDialog; -import io.flutter.app.FlutterActivity; import io.flutter.plugin.common.PluginRegistry; import kotlin.Unit; import kotlin.jvm.functions.Function1; -import java.util.HashMap; -import java.util.Map; - -import static com.gettipsi.stripe.Errors.*; -import static com.gettipsi.stripe.util.Converters.*; -import static com.gettipsi.stripe.util.InitializationOptions.*; -import static com.stripe.android.model.StripeIntent.Status.*; +import static com.gettipsi.stripe.Errors.AUTHENTICATION_FAILED; +import static com.gettipsi.stripe.Errors.CANCELLED; +import static com.gettipsi.stripe.Errors.FAILED; +import static com.gettipsi.stripe.Errors.UNEXPECTED; +import static com.gettipsi.stripe.Errors.getDescription; +import static com.gettipsi.stripe.Errors.getErrorCode; +import static com.gettipsi.stripe.Errors.toErrorCode; +import static com.gettipsi.stripe.util.Converters.convertPaymentIntentResultToWritableMap; +import static com.gettipsi.stripe.util.Converters.convertPaymentMethodToWritableMap; +import static com.gettipsi.stripe.util.Converters.convertSetupIntentResultToWritableMap; +import static com.gettipsi.stripe.util.Converters.convertSourceToWritableMap; +import static com.gettipsi.stripe.util.Converters.convertTokenToWritableMap; +import static com.gettipsi.stripe.util.Converters.createBankAccount; +import static com.gettipsi.stripe.util.Converters.createCard; +import static com.gettipsi.stripe.util.Converters.getBooleanOrNull; +import static com.gettipsi.stripe.util.Converters.getMapOrNull; +import static com.gettipsi.stripe.util.Converters.getStringOrNull; +import static com.gettipsi.stripe.util.InitializationOptions.ANDROID_PAY_MODE_KEY; +import static com.gettipsi.stripe.util.InitializationOptions.ANDROID_PAY_MODE_PRODUCTION; +import static com.gettipsi.stripe.util.InitializationOptions.ANDROID_PAY_MODE_TEST; +import static com.gettipsi.stripe.util.InitializationOptions.PUBLISHABLE_KEY; +import static com.stripe.android.model.StripeIntent.Status.Canceled; +import static com.stripe.android.model.StripeIntent.Status.RequiresAction; +import static com.stripe.android.model.StripeIntent.Status.RequiresCapture; +import static com.stripe.android.model.StripeIntent.Status.RequiresConfirmation; +import static com.stripe.android.model.StripeIntent.Status.Succeeded; public class StripeModule extends ReactContextBaseJavaModule { @@ -40,13 +81,16 @@ public class StripeModule extends ReactContextBaseJavaModule { // Relevant Docs: // - https://stripe.dev/stripe-ios/docs/Classes/STPAppInfo.html https://stripe.dev/stripe-android/com/stripe/android/AppInfo.html // - https://stripe.com/docs/building-plugins#setappinfo - private static final String APP_INFO_NAME = "tipsi-stripe"; - private static final String APP_INFO_URL = "https://github.com/tipsi/tipsi-stripe"; - private static final String APP_INFO_VERSION = "8.x"; + private static final String APP_INFO_NAME = "flutter_stripe_payment"; + private static final String APP_INFO_URL = "https://github.com/jonasbark/flutter_stripe_payment"; + private static final String APP_INFO_VERSION = "1.x"; public static final String CLIENT_SECRET = "clientSecret"; private static StripeModule sInstance = null; + @Nullable + private String mStripeAccountId = null; + public static StripeModule getInstance() { return sInstance; } @@ -96,6 +140,7 @@ public void init(@NonNull ReadableMap options, @NonNull ReadableMap errorCodes) Stripe.setAppInfo(AppInfo.create(APP_INFO_NAME, APP_INFO_VERSION, APP_INFO_URL)); mStripe = new Stripe(getReactApplicationContext(), mPublicKey); getPayFlow().setPublishableKey(mPublicKey); + PaymentConfiguration.init(getReactApplicationContext(), mPublicKey); } if (newAndroidPayMode != null) { @@ -140,6 +185,7 @@ public void canMakeAndroidPayPayments(final Promise promise) { @ReactMethod public void setStripeAccount(final String stripeAccount) { ArgCheck.notEmptyString(mPublicKey); + mStripeAccountId = stripeAccount; if (stripeAccount == null) { mStripe = new Stripe(getReactApplicationContext(), mPublicKey); } else { @@ -153,10 +199,9 @@ public void createTokenWithCard(final ReadableMap cardData, final Promise promis ArgCheck.nonNull(mStripe); ArgCheck.notEmptyString(mPublicKey); - mStripe.createToken( + mStripe.createCardToken( createCard(cardData), - mPublicKey, - new TokenCallback() { + new ApiResultCallback() { public void onSuccess(Token token) { promise.resolve(convertTokenToWritableMap(token)); } @@ -178,9 +223,8 @@ public void createTokenWithBankAccount(final ReadableMap accountData, final Prom mStripe.createBankAccountToken( createBankAccount(accountData), - mPublicKey, null, - new TokenCallback() { + new ApiResultCallback() { public void onSuccess(Token token) { promise.resolve(convertTokenToWritableMap(token)); } @@ -201,7 +245,8 @@ public void paymentRequestWithCardForm(ReadableMap params, final Promise promise ArgCheck.nonNull(currentActivity); ArgCheck.notEmptyString(mPublicKey); final StripeDialog cardDialog = StripeDialog.newInstance( - "" + "", + mStripeAccountId ); cardDialog.setStripeInstance(mStripe); cardDialog.setTokenListener(new Function1() { @@ -395,7 +440,7 @@ public void createSourceWithParams(final ReadableMap options, final Promise prom ArgCheck.nonNull(sourceParams); - mStripe.createSource(sourceParams, new SourceCallback() { + mStripe.createSource(sourceParams, new ApiResultCallback() { @Override public void onError(Exception error) { promise.reject(toErrorCode(error)); @@ -403,7 +448,7 @@ public void onError(Exception error) { @Override public void onSuccess(Source source) { - if (Source.SourceFlow.REDIRECT.equals(source.getFlow())) { + if (Source.Flow.Redirect.equals(source.getFlow())) { Activity currentActivity = getCurrentActivity(); if (currentActivity == null) { promise.reject( @@ -701,18 +746,18 @@ protected Source doInBackground(Void... voids) { protected void onPostExecute(Source source) { if (source != null) { switch (source.getStatus()) { - case Source.SourceStatus.CHARGEABLE: - case Source.SourceStatus.CONSUMED: + case Chargeable: + case Consumed: promise.resolve(convertSourceToWritableMap(source)); break; - case Source.SourceStatus.CANCELED: + case Canceled: promise.reject( getErrorCode(mErrorCodes, "redirectCancelled"), getDescription(mErrorCodes, "redirectCancelled") ); break; - case Source.SourceStatus.PENDING: - case Source.SourceStatus.FAILED: + case Pending: + case Failed: default: promise.reject( getErrorCode(mErrorCodes, "redirectFailed"), diff --git a/android/src/main/java/com/gettipsi/stripe/util/Converters.java b/android/src/main/java/com/gettipsi/stripe/util/Converters.java index e3429be8..d678ed55 100644 --- a/android/src/main/java/com/gettipsi/stripe/util/Converters.java +++ b/android/src/main/java/com/gettipsi/stripe/util/Converters.java @@ -1,8 +1,9 @@ package com.gettipsi.stripe.util; +import android.text.TextUtils; + import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import android.text.TextUtils; import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.ReadableArray; @@ -17,15 +18,14 @@ import com.stripe.android.SetupIntentResult; import com.stripe.android.model.Address; import com.stripe.android.model.BankAccount; +import com.stripe.android.model.BankAccountTokenParams; import com.stripe.android.model.Card; +import com.stripe.android.model.CardBrand; +import com.stripe.android.model.CardFunding; import com.stripe.android.model.PaymentIntent; import com.stripe.android.model.PaymentMethod; import com.stripe.android.model.SetupIntent; import com.stripe.android.model.Source; -import com.stripe.android.model.SourceCodeVerification; -import com.stripe.android.model.SourceOwner; -import com.stripe.android.model.SourceReceiver; -import com.stripe.android.model.SourceRedirect; import com.stripe.android.model.Token; import java.util.ArrayList; @@ -88,7 +88,7 @@ private static WritableMap convertCardToWritableMap(final Card card) { result.putString("cardId", card.getId()); result.putString("number", card.getNumber()); - result.putString("cvc", card.getCVC() ); + result.putString("cvc", card.getCvc() ); result.putInt("expMonth", card.getExpMonth() ); result.putInt("expYear", card.getExpYear() ); result.putString("name", card.getName() ); @@ -99,8 +99,10 @@ private static WritableMap convertCardToWritableMap(final Card card) { result.putString("addressZip", card.getAddressZip() ); result.putString("addressCountry", card.getAddressCountry() ); result.putString("last4", card.getLast4() ); - result.putString("brand", card.getBrand() ); - result.putString("funding", card.getFunding() ); + result.putString("brand", card.getBrand().getCode() ); + if (card.getFunding() != null) { + result.putString("funding", card.getFunding().name()); + } result.putString("fingerprint", card.getFingerprint() ); result.putString("country", card.getCountry() ); result.putString("currency", card.getCurrency() ); @@ -114,11 +116,13 @@ public static WritableMap convertBankAccountToWritableMap(BankAccount account) { if (account == null) return result; result.putString("routingNumber", account.getRoutingNumber()); - result.putString("accountNumber", account.getAccountNumber()); + // TODO no longer exists result.putString("accountNumber", account.getAccountNumber()); result.putString("countryCode", account.getCountryCode()); result.putString("currency", account.getCurrency()); result.putString("accountHolderName", account.getAccountHolderName()); - result.putString("accountHolderType", account.getAccountHolderType()); + if (account.getAccountHolderType() != null) { + result.putString("accountHolderType", account.getAccountHolderType().name()); + } result.putString("fingerprint", account.getFingerprint()); result.putString("bankName", account.getBankName()); result.putString("last4", account.getLast4()); @@ -198,10 +202,10 @@ public static Card createCard(final ReadableMap cardData) { .addressState(getValue(cardData, "addressState")) .addressZip(getValue(cardData, "addressZip")) .addressCountry(getValue(cardData, "addressCountry")) - .brand(getValue(cardData, "brand")) + .brand(getValue(cardData, "brand") != null ? CardBrand.valueOf(getValue(cardData, "brand")) : null) .last4(getValue(cardData, "last4")) .fingerprint(getValue(cardData, "fingerprint")) - .funding(getValue(cardData, "funding")) + .funding(getValue(cardData, "funding") != null ? CardFunding.valueOf(getValue(cardData, "funding")) : null) .country(getValue(cardData, "country")) .currency(getValue(cardData, "currency")) .id(getValue(cardData, "id")) @@ -223,17 +227,17 @@ public static WritableMap convertSourceToWritableMap(@Nullable Source source) { newSource.putInt("created", source.getCreated().intValue()); newSource.putMap("codeVerification", convertCodeVerificationToWritableMap(source.getCodeVerification())); newSource.putString("currency", source.getCurrency()); - newSource.putString("flow", source.getFlow()); + newSource.putString("flow", source.getFlow().name()); newSource.putBoolean("livemode", source.isLiveMode()); newSource.putMap("metadata", stringMapToWritableMap(source.getMetaData())); newSource.putMap("owner", convertOwnerToWritableMap(source.getOwner())); newSource.putMap("receiver", convertReceiverToWritableMap(source.getReceiver())); newSource.putMap("redirect", convertRedirectToWritableMap(source.getRedirect())); newSource.putMap("sourceTypeData", mapToWritableMap(source.getSourceTypeData())); - newSource.putString("status", source.getStatus()); + newSource.putString("status", source.getStatus().name()); newSource.putString("type", source.getType()); newSource.putString("typeRaw", source.getTypeRaw()); - newSource.putString("usage", source.getUsage()); + newSource.putString("usage", source.getUsage().name()); return newSource; } @@ -290,7 +294,7 @@ public static WritableMap convertPaymentMethodToWritableMap(@Nullable PaymentMet wm.putString("id", paymentMethod.id); wm.putInt("created", paymentMethod.created.intValue()); wm.putBoolean("livemode", paymentMethod.liveMode); - wm.putString("type", paymentMethod.type); + wm.putString("type", paymentMethod.type.code); wm.putMap("billingDetails", convertBillingDetailsToWritableMap(paymentMethod.billingDetails)); wm.putMap("card", convertPaymentMethodCardToWritableMap(paymentMethod.card)); wm.putString("customerId", paymentMethod.customerId); @@ -309,7 +313,7 @@ public static WritableMap convertPaymentMethodCardToWritableMap(@Nullable final // Omitted (can be introduced later): card.checks, card.threeDSecureUsage, card.wallet - wm.putString("brand", card.brand); + wm.putString("brand", card.brand.getCode()); wm.putString("country", card.country); wm.putInt("expMonth", card.expiryMonth); wm.putInt("expYear", card.expiryYear); @@ -350,7 +354,7 @@ public static WritableMap stringMapToWritableMap(@Nullable Map m } @NonNull - public static WritableMap convertOwnerToWritableMap(@Nullable final SourceOwner owner) { + public static WritableMap convertOwnerToWritableMap(@Nullable final Source.Owner owner) { WritableMap map = Arguments.createMap(); if (owner == null) { @@ -388,7 +392,7 @@ public static WritableMap convertAddressToWritableMap(@Nullable final Address ad } @NonNull - public static WritableMap convertReceiverToWritableMap(@Nullable final SourceReceiver receiver) { + public static WritableMap convertReceiverToWritableMap(@Nullable final Source.Receiver receiver) { WritableMap map = Arguments.createMap(); if (receiver == null) { @@ -404,7 +408,7 @@ public static WritableMap convertReceiverToWritableMap(@Nullable final SourceRec } @NonNull - public static WritableMap convertRedirectToWritableMap(@Nullable SourceRedirect redirect) { + public static WritableMap convertRedirectToWritableMap(@Nullable Source.Redirect redirect) { WritableMap map = Arguments.createMap(); if (redirect == null) { @@ -412,14 +416,14 @@ public static WritableMap convertRedirectToWritableMap(@Nullable SourceRedirect } map.putString("returnUrl", redirect.getReturnUrl()); - map.putString("status", redirect.getStatus()); + map.putString("status", redirect.getStatus().name()); map.putString("url", redirect.getUrl()); return map; } @NonNull - public static WritableMap convertCodeVerificationToWritableMap(@Nullable SourceCodeVerification codeVerification) { + public static WritableMap convertCodeVerificationToWritableMap(@Nullable Source.CodeVerification codeVerification) { WritableMap map = Arguments.createMap(); if (codeVerification == null) { @@ -427,7 +431,7 @@ public static WritableMap convertCodeVerificationToWritableMap(@Nullable SourceC } map.putInt("attemptsRemaining", codeVerification.getAttemptsRemaining()); - map.putString("status", codeVerification.getStatus()); + map.putString("status", codeVerification.getStatus().name()); return map; } @@ -490,17 +494,19 @@ public static WritableMap convertAddressToWritableMap(final UserAddress address) return result; } - public static BankAccount createBankAccount(ReadableMap accountData) { - BankAccount account = new BankAccount( - // required fields only - accountData.getString("accountNumber"), - getValue(accountData, "accountHolderName"), - getValue(accountData, "accountHolderType"), - null, + public static BankAccountTokenParams createBankAccount(ReadableMap accountData) { + // country: kotlin.String, + // currency: kotlin.String, + // accountNumber: kotlin.String, + // accountHolderType: com.stripe.android.model.BankAccountTokenParams.Type? /* = compiled code */, + // accountHolderName: kotlin.String? /* = compiled code */, + // routingNumber: kotlin.String? /* = compiled code */ + BankAccountTokenParams account = new BankAccountTokenParams( accountData.getString("countryCode"), accountData.getString("currency"), - null, - null, + accountData.getString("accountNumber"), + BankAccountTokenParams.Type.valueOf(getValue(accountData, "accountHolderType")), + getValue(accountData, "accountHolderName"), getValue(accountData, "routingNumber", "") ); diff --git a/android/src/main/kotlin/de/jonasbark/stripepayment/StripeDialog.kt b/android/src/main/kotlin/de/jonasbark/stripepayment/StripeDialog.kt index 322f6fb5..8298af92 100644 --- a/android/src/main/kotlin/de/jonasbark/stripepayment/StripeDialog.kt +++ b/android/src/main/kotlin/de/jonasbark/stripepayment/StripeDialog.kt @@ -3,25 +3,25 @@ package de.jonasbark.stripepayment import android.app.DialogFragment import android.content.DialogInterface import android.os.Bundle -import com.google.android.material.snackbar.Snackbar import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.Toast import com.stripe.android.ApiResultCallback -import com.stripe.android.PaymentConfiguration import com.stripe.android.Stripe -import com.stripe.android.model.* +import com.stripe.android.model.PaymentMethod +import com.stripe.android.model.PaymentMethodCreateParams import com.stripe.android.view.CardMultilineWidget -import java.lang.Exception class StripeDialog : DialogFragment() { companion object { @JvmStatic - fun newInstance(title: String): StripeDialog { + fun newInstance(title: String, stripeAccountId: String?): StripeDialog { val frag = StripeDialog() val args = Bundle() + args.putString("stripeAccountId", stripeAccountId) args.putString("title", title) frag.arguments = args return frag @@ -42,6 +42,9 @@ class StripeDialog : DialogFragment() { // Fetch arguments from bundle and set title val title = arguments?.getString("title", "Add Source") dialog?.setTitle(title) + + val mCardInputWidget = view.findViewById(R.id.card_input_widget) as CardMultilineWidget + mCardInputWidget.setShouldShowPostalCode(false) view.findViewById(R.id.buttonSave)?.setOnClickListener { getToken() } @@ -82,6 +85,8 @@ class StripeDialog : DialogFragment() { stripeInstance.createPaymentMethod( paymentMethodCreateParams, + null, + arguments?.getString("stripeAccountId", null), object : ApiResultCallback { override fun onSuccess(result: PaymentMethod) { view?.findViewById(R.id.progress)?.visibility = View.GONE @@ -95,7 +100,7 @@ class StripeDialog : DialogFragment() { view?.findViewById(R.id.progress)?.visibility = View.GONE view?.findViewById(R.id.buttonSave)?.visibility = View.VISIBLE view?.let { - Snackbar.make(it, error.localizedMessage, Snackbar.LENGTH_LONG) + Toast.makeText(it.context, error.localizedMessage, Toast.LENGTH_LONG) .show() } } @@ -105,7 +110,7 @@ class StripeDialog : DialogFragment() { } } else { view?.let { - Snackbar.make(it, "The card info you entered is not correct", Snackbar.LENGTH_LONG) + Toast.makeText(it.context, "The card info you entered is not correct", Toast.LENGTH_LONG) .show() } } diff --git a/example/.flutter-plugins-dependencies b/example/.flutter-plugins-dependencies deleted file mode 100644 index b93dc064..00000000 --- a/example/.flutter-plugins-dependencies +++ /dev/null @@ -1 +0,0 @@ -{"_info":"// This is a generated file; do not edit or check into version control.","dependencyGraph":[{"name":"stripe_payment","dependencies":[]}]} \ No newline at end of file diff --git a/example/.gitignore b/example/.gitignore index eb15c3d2..9e24b697 100644 --- a/example/.gitignore +++ b/example/.gitignore @@ -8,3 +8,4 @@ ios/.generated/ packages pubspec.lock .flutter-plugins +.last_build_id diff --git a/example/.metadata b/example/.metadata new file mode 100644 index 00000000..366c3fa6 --- /dev/null +++ b/example/.metadata @@ -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: 2294d75bfa8d067ba90230c0fc2268f3636d7584 + channel: beta + +project_type: app diff --git a/example/android.iml b/example/android.iml deleted file mode 100644 index 8f9e91ab..00000000 --- a/example/android.iml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index 51bb9cc6..56787aba 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -29,8 +29,8 @@ android { defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "de.jonasbark.stripepaymentexample" - minSdkVersion 19 - targetSdkVersion 28 + minSdkVersion 21 + targetSdkVersion 29 versionCode 1 multiDexEnabled true versionName "1.0" @@ -62,8 +62,8 @@ flutter { } dependencies { - api 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.50' - implementation 'com.android.support:support-annotations:28.0.0' + api 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.70' + implementation 'androidx.annotation:annotation:1.1.0' def multidex_version = "2.0.1" implementation "androidx.multidex:multidex:$multidex_version" } diff --git a/example/android/app/src/debug/AndroidManifest.xml b/example/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 00000000..b0b4292f --- /dev/null +++ b/example/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/example/android/app/src/main/kotlin/de/jonasbark/example/MainActivity.kt b/example/android/app/src/main/kotlin/de/jonasbark/example/MainActivity.kt new file mode 100644 index 00000000..54794059 --- /dev/null +++ b/example/android/app/src/main/kotlin/de/jonasbark/example/MainActivity.kt @@ -0,0 +1,6 @@ +package de.jonasbark.example + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity: FlutterActivity() { +} diff --git a/example/android/app/src/profile/AndroidManifest.xml b/example/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 00000000..b0b4292f --- /dev/null +++ b/example/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/example/android/build.gradle b/example/android/build.gradle index 3100ad2d..09661dbb 100644 --- a/example/android/build.gradle +++ b/example/android/build.gradle @@ -1,12 +1,12 @@ buildscript { - ext.kotlin_version = '1.3.50' + ext.kotlin_version = '1.3.70' repositories { google() jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.5.0' + classpath 'com.android.tools.build:gradle:3.6.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } diff --git a/example/android/gradle/wrapper/gradle-wrapper.jar b/example/android/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 13372aef..00000000 Binary files a/example/android/gradle/wrapper/gradle-wrapper.jar and /dev/null differ diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/example/android/gradle/wrapper/gradle-wrapper.properties index d292fe45..e5535918 100644 --- a/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/example/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Sun Sep 29 11:47:07 CEST 2019 +#Wed Mar 25 13:22:17 GMT 2020 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip diff --git a/example/android/gradlew b/example/android/gradlew deleted file mode 100755 index 9d82f789..00000000 --- a/example/android/gradlew +++ /dev/null @@ -1,160 +0,0 @@ -#!/usr/bin/env bash - -############################################################################## -## -## Gradle start up script for UN*X -## -############################################################################## - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn ( ) { - echo "$*" -} - -die ( ) { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; -esac - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=$((i+1)) - done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") -} -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" - -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/example/android/gradlew.bat b/example/android/gradlew.bat deleted file mode 100644 index 8a0b282a..00000000 --- a/example/android/gradlew.bat +++ /dev/null @@ -1,90 +0,0 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windowz variants - -if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/example/ios/.gitignore b/example/ios/.gitignore index 38864eed..e96ef602 100644 --- a/example/ios/.gitignore +++ b/example/ios/.gitignore @@ -1,41 +1,32 @@ -.idea/ -.vagrant/ -.sconsign.dblite -.svn/ - -.DS_Store -*.swp -profile - -DerivedData/ -build/ -GeneratedPluginRegistrant.h -GeneratedPluginRegistrant.m - -*.pbxuser *.mode1v3 *.mode2v3 +*.moved-aside +*.pbxuser *.perspectivev3 - -!default.pbxuser +**/*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 - -xcuserdata - -*.moved-aside - -*.pyc -*sync/ -Icon? -.tags* - -/Flutter/app.flx -/Flutter/app.zip -/Flutter/App.framework -/Flutter/Flutter.framework -/Flutter/Generated.xcconfig -/ServiceDefinitions.json - -Pods/ diff --git a/example/ios/Flutter/AppFrameworkInfo.plist b/example/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 00000000..6b4c0f78 --- /dev/null +++ b/example/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 8.0 + + diff --git a/example/ios/Flutter/Debug.xcconfig b/example/ios/Flutter/Debug.xcconfig new file mode 100644 index 00000000..e8efba11 --- /dev/null +++ b/example/ios/Flutter/Debug.xcconfig @@ -0,0 +1,2 @@ +#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "Generated.xcconfig" diff --git a/example/ios/Flutter/Release.xcconfig b/example/ios/Flutter/Release.xcconfig new file mode 100644 index 00000000..399e9340 --- /dev/null +++ b/example/ios/Flutter/Release.xcconfig @@ -0,0 +1,2 @@ +#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "Generated.xcconfig" diff --git a/example/ios/Podfile b/example/ios/Podfile index 4944d5fb..9411102b 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -1,8 +1,5 @@ -# Using a CDN with CocoaPods 1.7.2 or later can save a lot of time on pod installation, but it's experimental rather than the default. -# source 'https://cdn.cocoapods.org/' - # Uncomment this line to define a global platform for your project -# platform :ios, '11.0' +platform :ios, '10.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' @@ -13,66 +10,32 @@ project 'Runner', { 'Release' => :release, } -def parse_KV_file(file, separator='=') - file_abs_path = File.expand_path(file) - if !File.exists? file_abs_path - return []; +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches end - pods_ary = [] - skip_line_start_symbols = ["#", "/"] - File.foreach(file_abs_path) { |line| - next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ } - plugin = line.split(pattern=separator) - if plugin.length == 2 - podname = plugin[0].strip() - path = plugin[1].strip() - podpath = File.expand_path("#{path}", file_abs_path) - pods_ary.push({:name => podname, :path => podpath}); - else - puts "Invalid plugin specification: #{line}" - end - } - return pods_ary + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" end -target 'Runner' do - use_frameworks! +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) - # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock - # referring to absolute paths on developers' machines. - system('rm -rf .symlinks') - system('mkdir -p .symlinks/plugins') +flutter_ios_podfile_setup - # Flutter Pods - generated_xcode_build_settings = parse_KV_file('./Flutter/Generated.xcconfig') - if generated_xcode_build_settings.empty? - puts "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter pub get is executed first." - end - generated_xcode_build_settings.map { |p| - if p[:name] == 'FLUTTER_FRAMEWORK_DIR' - symlink = File.join('.symlinks', 'flutter') - File.symlink(File.dirname(p[:path]), symlink) - pod 'Flutter', :path => File.join(symlink, File.basename(p[:path])) - end - } +target 'Runner' do + use_frameworks! + use_modular_headers! - # Plugin Pods - plugin_pods = parse_KV_file('../.flutter-plugins') - plugin_pods.map { |p| - symlink = File.join('.symlinks', 'plugins', p[:name]) - File.symlink(p[:path], symlink) - pod p[:name], :path => File.join(symlink, 'ios') - } + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) end -# Prevent Cocoapods from embedding a second Flutter framework and causing an error with the new Xcode build system. -install! 'cocoapods', :disable_input_output_paths => true - post_install do |installer| installer.pods_project.targets.each do |target| - target.build_configurations.each do |config| - config.build_settings['ENABLE_BITCODE'] = 'NO' - end + flutter_additional_ios_build_settings(target) end end - diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock deleted file mode 100644 index b5936d25..00000000 --- a/example/ios/Podfile.lock +++ /dev/null @@ -1,29 +0,0 @@ -PODS: - - Flutter (1.0.0) - - Stripe (18.0.0) - - stripe_payment (1.0.0): - - Flutter - - Stripe (>= 18.0.0) - -DEPENDENCIES: - - Flutter (from `.symlinks/flutter/ios`) - - stripe_payment (from `.symlinks/plugins/stripe_payment/ios`) - -SPEC REPOS: - https://github.com/cocoapods/specs.git: - - Stripe - -EXTERNAL SOURCES: - Flutter: - :path: ".symlinks/flutter/ios" - stripe_payment: - :path: ".symlinks/plugins/stripe_payment/ios" - -SPEC CHECKSUMS: - Flutter: 0e3d915762c693b495b44d77113d4970485de6ec - Stripe: 8c9ac6b717a38ed4f373d4db9204cfe8c4120d65 - stripe_payment: 1baf1bbf556f7a35c210dc9e2eccf2075947b6be - -PODFILE CHECKSUM: 6df7b2151b00dd359d0386e1bc413232fa807b13 - -COCOAPODS: 1.7.5 diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index d883dceb..6ccf640c 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -7,17 +7,10 @@ objects = { /* Begin PBXBuildFile section */ + 0CDE54600D831861D10687D4 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9D3CBFBF1DC6662820BD3BD4 /* Pods_Runner.framework */; }; 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; - 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; }; - 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 8CE67D42D0818641DEAC2C6C /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DDE763E2A7603EEE543EA707 /* Pods_Runner.framework */; }; - 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; }; - 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; }; - 9740EEB51CF90195004384FC /* Generated.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB31CF90195004384FC /* Generated.xcconfig */; }; - 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; }; - 97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 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 */; }; @@ -30,8 +23,6 @@ dstPath = ""; dstSubfolderSpec = 10; files = ( - 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */, - 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; @@ -39,26 +30,23 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 049E91F523503FDC00EA722F /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = ""; }; + 08AEEC3FCD4A8F04F4DE064C /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; - 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; }; + 5A6D67A8BE4347D3F0DF6F89 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; - 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; - 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; }; 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 = ""; }; 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - CE94FA263A3EFA72C8B77555 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; - DDE763E2A7603EEE543EA707 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - E18BB6B0546928544A6802C4 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 9ADCBB605DAE98D853C28070 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 9D3CBFBF1DC6662820BD3BD4 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -66,21 +54,36 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */, - 3B80C3941E831B6300D905FE /* App.framework in Frameworks */, - 8CE67D42D0818641DEAC2C6C /* Pods_Runner.framework in Frameworks */, + 0CDE54600D831861D10687D4 /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 7319EF0E133896304A55E2BE /* Frameworks */ = { + isa = PBXGroup; + children = ( + 9D3CBFBF1DC6662820BD3BD4 /* Pods_Runner.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 87361B7C9C1B336D16562608 /* Pods */ = { + isa = PBXGroup; + children = ( + 08AEEC3FCD4A8F04F4DE064C /* Pods-Runner.debug.xcconfig */, + 9ADCBB605DAE98D853C28070 /* Pods-Runner.release.xcconfig */, + 5A6D67A8BE4347D3F0DF6F89 /* Pods-Runner.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( - 3B80C3931E831B6300D905FE /* App.framework */, 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, - 9740EEBA1CF902C7004384FC /* Flutter.framework */, 9740EEB21CF90195004384FC /* Debug.xcconfig */, 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 9740EEB31CF90195004384FC /* Generated.xcconfig */, @@ -94,8 +97,8 @@ 9740EEB11CF90186004384FC /* Flutter */, 97C146F01CF9000F007C117D /* Runner */, 97C146EF1CF9000F007C117D /* Products */, - B51F2F3CF61212E43FFCFEFA /* Pods */, - F53F7ABC83911BC2B0A804BA /* Frameworks */, + 87361B7C9C1B336D16562608 /* Pods */, + 7319EF0E133896304A55E2BE /* Frameworks */, ); sourceTree = ""; }; @@ -110,9 +113,6 @@ 97C146F01CF9000F007C117D /* Runner */ = { isa = PBXGroup; children = ( - 049E91F523503FDC00EA722F /* Runner.entitlements */, - 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */, - 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */, 97C146FA1CF9000F007C117D /* Main.storyboard */, 97C146FD1CF9000F007C117D /* Assets.xcassets */, 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, @@ -120,6 +120,8 @@ 97C146F11CF9000F007C117D /* Supporting Files */, 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, ); path = Runner; sourceTree = ""; @@ -127,28 +129,10 @@ 97C146F11CF9000F007C117D /* Supporting Files */ = { isa = PBXGroup; children = ( - 97C146F21CF9000F007C117D /* main.m */, ); name = "Supporting Files"; sourceTree = ""; }; - B51F2F3CF61212E43FFCFEFA /* Pods */ = { - isa = PBXGroup; - children = ( - CE94FA263A3EFA72C8B77555 /* Pods-Runner.debug.xcconfig */, - E18BB6B0546928544A6802C4 /* Pods-Runner.release.xcconfig */, - ); - name = Pods; - sourceTree = ""; - }; - F53F7ABC83911BC2B0A804BA /* Frameworks */ = { - isa = PBXGroup; - children = ( - DDE763E2A7603EEE543EA707 /* Pods_Runner.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -156,14 +140,14 @@ isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( - ED92744E70BAEF641ACDC884 /* [CP] Check Pods Manifest.lock */, + 758DE840BDB7F87DC11884BA /* [CP] Check Pods Manifest.lock */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, - 4B4F6E0E9A5B635D319BD8AE /* [CP] Embed Pods Frameworks */, + 7EB6A04D984C431F7857F3D5 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -180,21 +164,20 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0830; - ORGANIZATIONNAME = "The Chromium Authors"; + LastUpgradeCheck = 1020; + ORGANIZATIONNAME = ""; TargetAttributes = { 97C146ED1CF9000F007C117D = { CreatedOnToolsVersion = 7.3.1; - DevelopmentTeam = VAR7436X2W; + LastSwiftMigration = 1100; }; }; }; buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( - English, en, Base, ); @@ -214,9 +197,7 @@ buildActionMask = 2147483647; files = ( 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, - 9740EEB51CF90195004384FC /* Generated.xcconfig in Resources */, 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, - 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */, 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, ); @@ -237,54 +218,65 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin"; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; }; - 4B4F6E0E9A5B635D319BD8AE /* [CP] Embed Pods Frameworks */ = { + 758DE840BDB7F87DC11884BA /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); + inputFileListPaths = ( + ); inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( ); - name = "[CP] Embed Pods Frameworks"; outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - 9740EEB61CF901F6004384FC /* Run Script */ = { + 7EB6A04D984C431F7857F3D5 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", + "${PODS_ROOT}/../Flutter/Flutter.framework", + "${BUILT_PRODUCTS_DIR}/Stripe/Stripe.framework", + "${BUILT_PRODUCTS_DIR}/stripe_payment/stripe_payment.framework", ); - name = "Run Script"; + name = "[CP] Embed Pods Frameworks"; outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Stripe.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/stripe_payment.framework", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; }; - ED92744E70BAEF641ACDC884 /* [CP] Check Pods Manifest.lock */ = { + 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", ); - name = "[CP] Check Pods Manifest.lock"; + name = "Run Script"; outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; /* End PBXShellScriptBuildPhase section */ @@ -293,8 +285,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */, - 97C146F31CF9000F007C117D /* main.m in Sources */, + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -321,9 +312,84 @@ /* 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; + CLANG_ENABLE_MODULES = YES; + 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 = de.jonasbark.example; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; 97C147031CF9000F007C117D /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; @@ -331,14 +397,22 @@ 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; @@ -371,7 +445,6 @@ }; 97C147041CF9000F007C117D /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; @@ -379,14 +452,22 @@ 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; @@ -406,6 +487,8 @@ IPHONEOS_DEPLOYMENT_TARGET = 8.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; @@ -415,24 +498,26 @@ isa = XCBuildConfiguration; baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; buildSettings = { - ARCHS = arm64; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; - DEVELOPMENT_TEAM = VAR7436X2W; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Flutter", ); INFOPLIST_FILE = Runner/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Flutter", ); - PRODUCT_BUNDLE_IDENTIFIER = com.rbitwo.stripeNativeExample; + PRODUCT_BUNDLE_IDENTIFIER = de.jonasbark.example; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; }; name = Debug; }; @@ -440,24 +525,25 @@ isa = XCBuildConfiguration; baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { - ARCHS = arm64; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; - DEVELOPMENT_TEAM = VAR7436X2W; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Flutter", ); INFOPLIST_FILE = Runner/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Flutter", ); - PRODUCT_BUNDLE_IDENTIFIER = com.rbitwo.stripeNativeExample; + PRODUCT_BUNDLE_IDENTIFIER = de.jonasbark.example; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; }; name = Release; }; @@ -469,6 +555,7 @@ buildConfigurations = ( 97C147031CF9000F007C117D /* Debug */, 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -478,6 +565,7 @@ buildConfigurations = ( 97C147061CF9000F007C117D /* Debug */, 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; diff --git a/example/ios/Runner/Runner.entitlements b/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist similarity index 62% rename from example/ios/Runner/Runner.entitlements rename to example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist index 43486da5..18d98100 100644 --- a/example/ios/Runner/Runner.entitlements +++ b/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -2,9 +2,7 @@ - com.apple.developer.in-app-payments - - merchant.rbii.stripe-example - + IDEDidComputeMac32BitWarning + diff --git a/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 00000000..f9b0d7c5 --- /dev/null +++ b/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 1c958078..a28140cf 100644 --- a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ - BuildSystemType - Original + PreviewsEnabled + diff --git a/example/ios/Runner/AppDelegate.h b/example/ios/Runner/AppDelegate.h deleted file mode 100644 index cf210d21..00000000 --- a/example/ios/Runner/AppDelegate.h +++ /dev/null @@ -1,6 +0,0 @@ -#import -#import - -@interface AppDelegate : FlutterAppDelegate - -@end diff --git a/example/ios/Runner/AppDelegate.m b/example/ios/Runner/AppDelegate.m deleted file mode 100644 index 9dc51db8..00000000 --- a/example/ios/Runner/AppDelegate.m +++ /dev/null @@ -1,14 +0,0 @@ -#include "AppDelegate.h" -#include "GeneratedPluginRegistrant.h" -@import stripe_payment; -#import - -@implementation AppDelegate - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - [GeneratedPluginRegistrant registerWithRegistry:self]; - return [super application:application didFinishLaunchingWithOptions:launchOptions]; -} - - -@end diff --git a/example/ios/Runner/AppDelegate.swift b/example/ios/Runner/AppDelegate.swift new file mode 100644 index 00000000..70693e4a --- /dev/null +++ b/example/ios/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import UIKit +import Flutter + +@UIApplicationMain +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json index d225b3c2..d36b1fab 100644 --- a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -109,8 +109,9 @@ "scale" : "2x" }, { - "idiom" : "ios-marketing", "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", "scale" : "1x" } ], @@ -118,4 +119,4 @@ "version" : 1, "author" : "xcode" } -} \ No newline at end of file +} diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 00000000..dc9ada47 Binary files /dev/null and b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ diff --git a/example/ios/Runner/Info.plist b/example/ios/Runner/Info.plist index 4e54356b..a060db61 100644 --- a/example/ios/Runner/Info.plist +++ b/example/ios/Runner/Info.plist @@ -3,7 +3,7 @@ CFBundleDevelopmentRegion - en + $(DEVELOPMENT_LANGUAGE) CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier @@ -11,25 +11,21 @@ CFBundleInfoDictionaryVersion 6.0 CFBundleName - stripe_payment_example + example CFBundlePackageType APPL CFBundleShortVersionString - 1.0 + $(FLUTTER_BUILD_NAME) CFBundleSignature ???? CFBundleVersion - 1 + $(FLUTTER_BUILD_NUMBER) LSRequiresIPhoneOS UILaunchStoryboardName LaunchScreen UIMainStoryboardFile Main - UIRequiredDeviceCapabilities - - arm64 - UISupportedInterfaceOrientations UIInterfaceOrientationPortrait diff --git a/example/ios/Runner/Runner-Bridging-Header.h b/example/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 00000000..308a2a56 --- /dev/null +++ b/example/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/example/ios/Runner/main.m b/example/ios/Runner/main.m deleted file mode 100644 index 0ccc4500..00000000 --- a/example/ios/Runner/main.m +++ /dev/null @@ -1,9 +0,0 @@ -#import -#import -#import "AppDelegate.h" - -int main(int argc, char * argv[]) { - @autoreleasepool { - return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); - } -} diff --git a/example/lib/main.dart b/example/lib/main.dart index 3a87ba0d..66f9d24f 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,8 +1,8 @@ import 'dart:convert'; +import 'dart:io'; import 'package:flutter/material.dart'; import 'package:stripe_payment/stripe_payment.dart'; -import 'dart:io'; void main() { runApp(new MyApp()); @@ -14,12 +14,16 @@ class MyApp extends StatefulWidget { } class _MyAppState extends State { - Token _paymentToken; - PaymentMethod _paymentMethod; - String _error; - final String _currentSecret = null; //set this yourself, e.g using curl - PaymentIntentResult _paymentIntent; - Source _source; + Token? _paymentToken; + PaymentMethod? _paymentMethod; + String? _error; + + //this client secret is typically created by a backend system + //check https://stripe.com/docs/payments/payment-intents#passing-to-client + final String? _paymentIntentClientSecret = null; + + PaymentIntentResult? _paymentIntent; + Source? _source; ScrollController _controller = ScrollController(); @@ -27,6 +31,13 @@ class _MyAppState extends State { number: '4000002760003184', expMonth: 12, expYear: 21, + name: 'Test User', + cvc: '133', + addressLine1: 'Address 1', + addressLine2: 'Address 2', + addressCity: 'City', + addressState: 'CA', + addressZip: '1337', ); GlobalKey _scaffoldKey = GlobalKey(); @@ -35,12 +46,15 @@ class _MyAppState extends State { initState() { super.initState(); - StripePayment.setOptions( - StripeOptions(publishableKey: "pk_test_aSaULNS8cJU6Tvo20VAXy6rp", merchantId: "Test", androidPayMode: 'test')); + StripePayment.setOptions(StripeOptions( + publishableKey: "pk_test_aSaULNS8cJU6Tvo20VAXy6rp", + merchantId: "Test", + androidPayMode: 'test')); } void setError(dynamic error) { - _scaffoldKey.currentState.showSnackBar(SnackBar(content: Text(error.toString()))); + _scaffoldKey.currentState! + .showSnackBar(SnackBar(content: Text(error.toString()))); setState(() { _error = error.toString(); }); @@ -80,7 +94,8 @@ class _MyAppState extends State { currency: 'eur', returnURL: 'example://stripe-redirect', )).then((source) { - _scaffoldKey.currentState.showSnackBar(SnackBar(content: Text('Received ${source.sourceId}'))); + _scaffoldKey.currentState!.showSnackBar( + SnackBar(content: Text('Received ${source.sourceId}'))); setState(() { _source = source; }); @@ -91,8 +106,11 @@ class _MyAppState extends State { RaisedButton( child: Text("Create Token with Card Form"), onPressed: () { - StripePayment.paymentRequestWithCardForm(CardFormPaymentRequest()).then((paymentMethod) { - _scaffoldKey.currentState.showSnackBar(SnackBar(content: Text('Received ${paymentMethod.id}'))); + StripePayment.paymentRequestWithCardForm( + CardFormPaymentRequest()) + .then((paymentMethod) { + _scaffoldKey.currentState!.showSnackBar( + SnackBar(content: Text('Received ${paymentMethod.id}'))); setState(() { _paymentMethod = paymentMethod; }); @@ -105,7 +123,8 @@ class _MyAppState extends State { StripePayment.createTokenWithCard( testCard, ).then((token) { - _scaffoldKey.currentState.showSnackBar(SnackBar(content: Text('Received ${token.tokenId}'))); + _scaffoldKey.currentState!.showSnackBar( + SnackBar(content: Text('Received ${token.tokenId}'))); setState(() { _paymentToken = token; }); @@ -121,7 +140,8 @@ class _MyAppState extends State { card: testCard, ), ).then((paymentMethod) { - _scaffoldKey.currentState.showSnackBar(SnackBar(content: Text('Received ${paymentMethod.id}'))); + _scaffoldKey.currentState!.showSnackBar( + SnackBar(content: Text('Received ${paymentMethod.id}'))); setState(() { _paymentMethod = paymentMethod; }); @@ -136,11 +156,12 @@ class _MyAppState extends State { StripePayment.createPaymentMethod( PaymentMethodRequest( card: CreditCard( - token: _paymentToken.tokenId, + token: _paymentToken!.tokenId, ), ), ).then((paymentMethod) { - _scaffoldKey.currentState.showSnackBar(SnackBar(content: Text('Received ${paymentMethod.id}'))); + _scaffoldKey.currentState!.showSnackBar(SnackBar( + content: Text('Received ${paymentMethod.id}'))); setState(() { _paymentMethod = paymentMethod; }); @@ -150,31 +171,61 @@ class _MyAppState extends State { Divider(), RaisedButton( child: Text("Confirm Payment Intent"), - onPressed: _paymentMethod == null || _currentSecret == null - ? null - : () { - StripePayment.confirmPaymentIntent( - PaymentIntent( - clientSecret: _currentSecret, - paymentMethodId: _paymentMethod.id, - ), - ).then((paymentIntent) { - _scaffoldKey.currentState - .showSnackBar(SnackBar(content: Text('Received ${paymentIntent.paymentIntentId}'))); - setState(() { - _paymentIntent = paymentIntent; - }); - }).catchError(setError); - }, + onPressed: + _paymentMethod == null || _paymentIntentClientSecret == null + ? null + : () { + StripePayment.confirmPaymentIntent( + PaymentIntent( + clientSecret: _paymentIntentClientSecret, + paymentMethodId: _paymentMethod!.id, + ), + ).then((paymentIntent) { + _scaffoldKey.currentState!.showSnackBar(SnackBar( + content: Text( + 'Received ${paymentIntent.paymentIntentId}'))); + setState(() { + _paymentIntent = paymentIntent; + }); + }).catchError(setError); + }, + ), + RaisedButton( + child: Text( + "Confirm Payment Intent with saving payment method", + textAlign: TextAlign.center, + ), + onPressed: + _paymentMethod == null || _paymentIntentClientSecret == null + ? null + : () { + StripePayment.confirmPaymentIntent( + PaymentIntent( + clientSecret: _paymentIntentClientSecret, + paymentMethodId: _paymentMethod!.id!, + isSavingPaymentMethod: true, + ), + ).then((paymentIntent) { + _scaffoldKey.currentState?.showSnackBar(SnackBar( + content: Text( + 'Received ${paymentIntent.paymentIntentId}'))); + setState(() { + _paymentIntent = paymentIntent; + }); + }).catchError(setError); + }, ), RaisedButton( child: Text("Authenticate Payment Intent"), - onPressed: _currentSecret == null + onPressed: _paymentIntentClientSecret == null ? null : () { - StripePayment.authenticatePaymentIntent(clientSecret: _currentSecret).then((paymentIntent) { - _scaffoldKey.currentState - .showSnackBar(SnackBar(content: Text('Received ${paymentIntent.paymentIntentId}'))); + StripePayment.authenticatePaymentIntent( + clientSecret: _paymentIntentClientSecret!) + .then((paymentIntent) { + _scaffoldKey.currentState!.showSnackBar(SnackBar( + content: Text( + 'Received ${paymentIntent.paymentIntentId}'))); setState(() { _paymentIntent = paymentIntent; }); @@ -205,7 +256,8 @@ class _MyAppState extends State { ), ).then((token) { setState(() { - _scaffoldKey.currentState.showSnackBar(SnackBar(content: Text('Received ${token.tokenId}'))); + _scaffoldKey.currentState!.showSnackBar( + SnackBar(content: Text('Received ${token.tokenId}'))); _paymentToken = token; }); }).catchError(setError); @@ -215,7 +267,8 @@ class _MyAppState extends State { child: Text("Complete Native Payment"), onPressed: () { StripePayment.completeNativePayRequest().then((_) { - _scaffoldKey.currentState.showSnackBar(SnackBar(content: Text('Completed successfully'))); + _scaffoldKey.currentState!.showSnackBar( + SnackBar(content: Text('Completed successfully'))); }).catchError(setError); }, ), @@ -228,19 +281,22 @@ class _MyAppState extends State { Divider(), Text('Current token:'), Text( - JsonEncoder.withIndent(' ').convert(_paymentToken?.toJson() ?? {}), + JsonEncoder.withIndent(' ') + .convert(_paymentToken?.toJson() ?? {}), style: TextStyle(fontFamily: "Monospace"), ), Divider(), Text('Current payment method:'), Text( - JsonEncoder.withIndent(' ').convert(_paymentMethod?.toJson() ?? {}), + JsonEncoder.withIndent(' ') + .convert(_paymentMethod?.toJson() ?? {}), style: TextStyle(fontFamily: "Monospace"), ), Divider(), Text('Current payment intent:'), Text( - JsonEncoder.withIndent(' ').convert(_paymentIntent?.toJson() ?? {}), + JsonEncoder.withIndent(' ') + .convert(_paymentIntent?.toJson() ?? {}), style: TextStyle(fontFamily: "Monospace"), ), Divider(), diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 9aabf19e..3c607220 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -1,6 +1,10 @@ name: stripe_payment_example description: Demonstrates how to use the stripe_payment plugin. +environment: + sdk: '>=2.12.0 <3.0.0' + flutter: ">=1.12.13+hotfix.5 <3.0.0" + dependencies: flutter: sdk: flutter diff --git a/example/stripe_payment_example.iml b/example/stripe_payment_example.iml deleted file mode 100644 index d6ba21be..00000000 --- a/example/stripe_payment_example.iml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/example/stripe_payment_example_android.iml b/example/stripe_payment_example_android.iml deleted file mode 100644 index 0ca70ed9..00000000 --- a/example/stripe_payment_example_android.iml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/example/web/favicon.png b/example/web/favicon.png new file mode 100644 index 00000000..8aaa46ac Binary files /dev/null and b/example/web/favicon.png differ diff --git a/example/web/icons/Icon-192.png b/example/web/icons/Icon-192.png new file mode 100644 index 00000000..b749bfef Binary files /dev/null and b/example/web/icons/Icon-192.png differ diff --git a/example/web/icons/Icon-512.png b/example/web/icons/Icon-512.png new file mode 100644 index 00000000..88cfd48d Binary files /dev/null and b/example/web/icons/Icon-512.png differ diff --git a/example/web/index.html b/example/web/index.html new file mode 100644 index 00000000..9b7a438f --- /dev/null +++ b/example/web/index.html @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + example + + + + + + + + diff --git a/example/web/manifest.json b/example/web/manifest.json new file mode 100644 index 00000000..c6380010 --- /dev/null +++ b/example/web/manifest.json @@ -0,0 +1,23 @@ +{ + "name": "example", + "short_name": "example", + "start_url": ".", + "display": "minimal-ui", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "A new Flutter project.", + "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" + } + ] +} diff --git a/ios/Classes/TPSStripeManager.m b/ios/Classes/TPSStripeManager.m index 3fd928a2..bc47e526 100644 --- a/ios/Classes/TPSStripeManager.m +++ b/ios/Classes/TPSStripeManager.m @@ -17,10 +17,10 @@ // Relevant Docs: // - https://stripe.dev/stripe-ios/docs/Classes/STPAppInfo.html https://stripe.dev/stripe-android/com/stripe/android/AppInfo.html // - https://stripe.com/docs/building-plugins#setappinfo -NSString * const TPSAppInfoName = @"tipsi-stripe"; -NSString * const TPSAppInfoPartnerId = @"tipsi-stripe"; -NSString * const TPSAppInfoURL = @"https://github.com/tipsi/tipsi-stripe"; -NSString * const TPSAppInfoVersion = @"8.x"; +NSString * const TPSAppInfoName = @"flutter_stripe_payment"; +NSString * const TPSAppInfoPartnerId = @"flutter_stripe_payment"; +NSString * const TPSAppInfoURL = @"https://github.com/jonasbark/flutter_stripe_payment"; +NSString * const TPSAppInfoVersion = @"1.x"; typedef NSString * TPSErrorKey NS_EXTENSIBLE_STRING_ENUM; #define TPSErrorKeyDefine(Key, string) TPSErrorKey const kErrorKey ## Key = string @@ -454,6 +454,7 @@ -(void)authenticatePaymentIntent:(NSDictionary *)untypedParams promiseResolver = resolve; promiseRejector = reject; + STPAPIClient *api = self.newAPIClient; // From example in step 3 of https://stripe.com/docs/payments/payment-intents/ios#manual-confirmation-ios [[STPPaymentHandler sharedHandler] handleNextActionForPayment:clientSecret withAuthenticationContext:self @@ -863,21 +864,15 @@ -(void)paymentRequestWithApplePay:(NSArray *)items [paymentRequest setShippingMethods:shippingMethods]; [paymentRequest setShippingType:shippingType]; - if ([self canSubmitPaymentRequest:paymentRequest rejecter:reject]) { - PKPaymentAuthorizationViewController *paymentAuthorizationVC = [[PKPaymentAuthorizationViewController alloc] initWithPaymentRequest:paymentRequest]; - paymentAuthorizationVC.delegate = self; + PKPaymentAuthorizationViewController *paymentAuthorizationVC = [[PKPaymentAuthorizationViewController alloc] initWithPaymentRequest:paymentRequest]; + paymentAuthorizationVC.delegate = self; - // move to the end of main queue - // allow the execution of hiding modal - // to be finished first - dispatch_async(dispatch_get_main_queue(), ^{ - [RCTPresentedViewController() presentViewController:paymentAuthorizationVC animated:YES completion:nil]; - }); - } else { - // There is a problem with your Apple Pay configuration. - [self resetPromiseCallbacks]; - requestIsCompleted = YES; - } + // move to the end of main queue + // allow the execution of hiding modal + // to be finished first + dispatch_async(dispatch_get_main_queue(), ^{ + [RCTPresentedViewController() presentViewController:paymentAuthorizationVC animated:YES completion:nil]; + }); } -(void)openApplePaySetup { @@ -893,20 +888,11 @@ -(void)openApplePaySetup { - (STPCardParams *)extractCardParamsFromDictionary:(NSDictionary *)params { STPCardParams *result = [[STPCardParams alloc] init]; -#define simpleUnpack(key) result.key = [RCTConvert NSString:params[TPSStripeParam(CardParams, key)]] - - simpleUnpack(number); - result.expMonth = [params[TPSStripeParam(CardParams, expMonth)] integerValue]; - result.expYear = [params[TPSStripeParam(CardParams, expYear)] integerValue]; - simpleUnpack(cvc); - - simpleUnpack(currency); - simpleUnpack(name); - -#undef simpleUnpack // Make a new address object, and fill it in with data before assigning it // Editing the fields on the assigned address won't do anything according to Stripe's docs + // Setting the address before the rest of the fields so result.name is not cleared. + // https://stripe.dev/stripe-ios/docs/Classes/STPCardParams.html#/c:objc(cs)STPCardParams(py)address STPAddress * address = [[STPAddress alloc] init]; address.line1 = params[TPSStripeParam(CardParams, addressLine1)]; address.line2 = params[TPSStripeParam(CardParams, addressLine2)]; @@ -916,6 +902,18 @@ - (STPCardParams *)extractCardParamsFromDictionary:(NSDictionary= 18.0.0' + s.dependency 'Stripe', '~> 19.4.0' s.ios.deployment_target = '10.0' end diff --git a/lib/src/android_pay_payment_request.dart b/lib/src/android_pay_payment_request.dart index a6dcd4b9..3c5a4176 100644 --- a/lib/src/android_pay_payment_request.dart +++ b/lib/src/android_pay_payment_request.dart @@ -1,20 +1,20 @@ import 'package:flutter/material.dart'; class AndroidPayPaymentRequest { - bool billingAddressRequired; - String currencyCode; - List lineItems; - bool shippingAddressRequired; - List shippingCountries; - String totalPrice; + bool? billingAddressRequired; + String? currencyCode; + List? lineItems; + bool? shippingAddressRequired; + List? shippingCountries; + String? totalPrice; AndroidPayPaymentRequest( {this.billingAddressRequired, - @required this.currencyCode, + required this.currencyCode, this.lineItems, this.shippingAddressRequired, this.shippingCountries, - @required this.totalPrice}); + required this.totalPrice}); factory AndroidPayPaymentRequest.fromJson(Map json) { return AndroidPayPaymentRequest( @@ -35,7 +35,7 @@ class AndroidPayPaymentRequest { if (this.shippingAddressRequired != null) data['shipping_address_required'] = this.shippingAddressRequired; if (this.totalPrice != null) data['total_price'] = this.totalPrice; if (this.lineItems != null) { - data['line_items'] = this.lineItems.map((v) => v.toJson()).toList(); + data['line_items'] = this.lineItems!.map((v) => v.toJson()).toList(); } if (this.shippingCountries != null) { if (this.shippingCountries != null) data['shipping_countries'] = this.shippingCountries; @@ -45,11 +45,11 @@ class AndroidPayPaymentRequest { } class LineItem { - String currencyCode; - String description; - String quantity; - String totalPrice; - String unitPrice; + String? currencyCode; + String? description; + String? quantity; + String? totalPrice; + String? unitPrice; LineItem({this.currencyCode, this.description, this.quantity, this.totalPrice, this.unitPrice}); diff --git a/lib/src/apple_pay_payment_request.dart b/lib/src/apple_pay_payment_request.dart index a35f9d9c..85a087f5 100644 --- a/lib/src/apple_pay_payment_request.dart +++ b/lib/src/apple_pay_payment_request.dart @@ -7,13 +7,13 @@ enum RequiredShippingAddressFields { all, name, email, phone, postal_address } enum ShippingType { shipping, delivery, store_pickup, service_pickup } class ApplePayPaymentOptions { - List requiredBillingAddressFields; - List requiredShippingAddressFields; - List shippingMethod; - String currencyCode; - String countryCode; - ShippingType shippingType; - List items; + List? requiredBillingAddressFields; + List? requiredShippingAddressFields; + List? shippingMethod; + String? currencyCode; + String? countryCode; + ShippingType? shippingType; + List? items; ApplePayPaymentOptions( {this.requiredBillingAddressFields, @@ -27,13 +27,13 @@ class ApplePayPaymentOptions { Map get json { final Map data = new Map(); if (this.requiredBillingAddressFields != null) { - data['requiredBillingAddressFields'] = this.requiredBillingAddressFields.map((b) => describeEnum(b)).toList(); + data['requiredBillingAddressFields'] = this.requiredBillingAddressFields!.map((b) => describeEnum(b)).toList(); } if (this.requiredShippingAddressFields != null) { - data['requiredShippingAddressFields'] = this.requiredShippingAddressFields.map((s) => describeEnum(s)).toList(); + data['requiredShippingAddressFields'] = this.requiredShippingAddressFields!.map((s) => describeEnum(s)).toList(); } if (this.shippingMethod != null) { - data['shippingMethod'] = this.shippingMethod.map((s) => s.toJson()); + data['shippingMethod'] = this.shippingMethod!.map((s) => s.toJson()).toList(); } data['currencyCode'] = currencyCode; if (this.shippingType != null) { @@ -45,10 +45,10 @@ class ApplePayPaymentOptions { } class ShippingMethod { - String amount; - String detail; - String id; - String label; + String? amount; + String? detail; + String? id; + String? label; ShippingMethod({this.amount, this.detail, this.id, this.label}); @@ -72,9 +72,9 @@ class ShippingMethod { } class ApplePayItem { - String label; - String amount; - String type; + String? label; + String? amount; + String? type; ApplePayItem({this.label, this.amount, this.type}); Map get json { diff --git a/lib/src/card_form_payment_request.dart b/lib/src/card_form_payment_request.dart index 508708a2..e49b31a9 100644 --- a/lib/src/card_form_payment_request.dart +++ b/lib/src/card_form_payment_request.dart @@ -1,6 +1,6 @@ class CardFormPaymentRequest { - PrefilledInformation prefilledInformation; - String requiredBillingAddressFields; + PrefilledInformation? prefilledInformation; + String? requiredBillingAddressFields; CardFormPaymentRequest({this.prefilledInformation, this.requiredBillingAddressFields}); @@ -17,14 +17,14 @@ class CardFormPaymentRequest { if (this.requiredBillingAddressFields != null) if (this.requiredBillingAddressFields != null) data['requiredBillingAddressFields'] = this.requiredBillingAddressFields; if (this.prefilledInformation != null) { - data['prefilledInformation'] = this.prefilledInformation.toJson(); + data['prefilledInformation'] = this.prefilledInformation!.toJson(); } return data; } } class PrefilledInformation { - BillingAddress billingAddress; + BillingAddress? billingAddress; PrefilledInformation({this.billingAddress}); @@ -37,20 +37,20 @@ class PrefilledInformation { Map toJson() { final Map data = new Map(); if (this.billingAddress != null) { - data['billingAddress'] = this.billingAddress.toJson(); + data['billingAddress'] = this.billingAddress!.toJson(); } return data; } } class BillingAddress { - String city; - String country; - String line1; - String line2; - String name; - String postalCode; - String state; + String? city; + String? country; + String? line1; + String? line2; + String? name; + String? postalCode; + String? state; BillingAddress({this.city, this.country, this.line1, this.line2, this.name, this.postalCode, this.state}); diff --git a/lib/src/error_codes.dart b/lib/src/error_codes.dart index 209cf0c3..ed81ac6b 100644 --- a/lib/src/error_codes.dart +++ b/lib/src/error_codes.dart @@ -4,7 +4,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; class Errors { - static Map> mapping = { + static Map> mapping = { "busy": ErrorCode( errorCode: 'busy', description: 'Previous request is not completed', @@ -123,9 +123,9 @@ class Errors { class ErrorCode { final String errorCode; - final String description; + final String? description; - ErrorCode({@required this.errorCode, this.description}); + ErrorCode({required this.errorCode, this.description}); - Map toJson() => {"errorCode": errorCode, "description": description}; + Map toJson() => {"errorCode": errorCode, "description": description}; } diff --git a/lib/src/payment_intent.dart b/lib/src/payment_intent.dart index 16c1882d..ab6f9952 100644 --- a/lib/src/payment_intent.dart +++ b/lib/src/payment_intent.dart @@ -2,34 +2,37 @@ import 'package:flutter/material.dart'; import 'package:stripe_payment/src/payment_method.dart'; class PaymentIntent { - PaymentMethodRequest paymentMethod; - String paymentMethodId; - String returnURL; - String clientSecret; + PaymentMethodRequest? paymentMethod; + String? paymentMethodId; + String? returnURL; + String? clientSecret; + bool? isSavingPaymentMethod; PaymentIntent({ this.paymentMethod, this.paymentMethodId, this.returnURL, @required this.clientSecret, + this.isSavingPaymentMethod, }); Map toJson() { final Map data = new Map(); if (this.paymentMethod != null) { - data['paymentMethod'] = this.paymentMethod.toJson(); + data['paymentMethod'] = this.paymentMethod!.toJson(); } if (this.paymentMethodId != null) data['paymentMethodId'] = this.paymentMethodId; if (this.returnURL != null) data['returnURL'] = this.returnURL; if (this.clientSecret != null) data['clientSecret'] = this.clientSecret; + if (this.isSavingPaymentMethod != null) data['savePaymentMethod'] = this.isSavingPaymentMethod; return data; } } class PaymentIntentResult { - String status; - String paymentIntentId; - String paymentMethodId; + String? status; + String? paymentIntentId; + String? paymentMethodId; PaymentIntentResult({this.status, this.paymentIntentId, this.paymentMethodId}); @@ -51,9 +54,9 @@ class PaymentIntentResult { } class SetupIntentResult { - String status; - String paymentIntentId; - String setupIntentId; + String? status; + String? paymentIntentId; + String? setupIntentId; SetupIntentResult({ this.status, diff --git a/lib/src/payment_method.dart b/lib/src/payment_method.dart index 5ccccaaf..9df3de8b 100644 --- a/lib/src/payment_method.dart +++ b/lib/src/payment_method.dart @@ -3,25 +3,25 @@ import 'package:stripe_payment/src/token.dart'; import 'card_form_payment_request.dart'; class PaymentMethodRequest { - final BillingAddress billingAddress; - final CreditCard card; - final Token token; - final Map metadata; + final BillingAddress? billingAddress; + final CreditCard? card; + final Token? token; + final Map? metadata; PaymentMethodRequest({this.billingAddress, this.card, this.token, this.metadata}) { assert(card != null || token != null); } - Map toJson() { + Map toJson() { final Map data = new Map(); if (this.card != null) { - data['card'] = card.toJson(); + data['card'] = card!.toJson(); } if (this.token != null) { - data['token'] = token.toJson(); + data['token'] = token!.toJson(); } if (this.billingAddress != null) { - data['billingAddress'] = this.billingAddress.toJson(); + data['billingAddress'] = this.billingAddress!.toJson(); } if (this.metadata != null) { if (this.metadata != null) data['metadata'] = this.metadata; @@ -31,13 +31,13 @@ class PaymentMethodRequest { } class PaymentMethod { - BillingDetails billingDetails; - CreditCard card; - num created; - String customerId; - String id; - bool livemode; - String type; + BillingDetails? billingDetails; + CreditCard? card; + num? created; + String? customerId; + String? id; + bool? livemode; + String? type; PaymentMethod({this.billingDetails, this.card, this.created, this.customerId, this.id, this.livemode, this.type}); @@ -61,20 +61,20 @@ class PaymentMethod { if (this.livemode != null) data['livemode'] = this.livemode; if (this.type != null) data['type'] = this.type; if (this.billingDetails != null) { - data['billingDetails'] = this.billingDetails.toJson(); + data['billingDetails'] = this.billingDetails!.toJson(); } if (this.card != null) { - data['card'] = this.card.toJson(); + data['card'] = this.card!.toJson(); } return data; } } class BillingDetails { - BillingAddress address; - String email; - String name; - String phone; + BillingAddress? address; + String? email; + String? name; + String? phone; BillingDetails({this.address, this.email, this.name, this.phone}); @@ -93,7 +93,7 @@ class BillingDetails { if (this.name != null) data['name'] = this.name; if (this.phone != null) data['phone'] = this.phone; if (this.address != null) { - data['address'] = this.address.toJson(); + data['address'] = this.address!.toJson(); } return data; } diff --git a/lib/src/source.dart b/lib/src/source.dart index 628eb160..5b7ac9f9 100644 --- a/lib/src/source.dart +++ b/lib/src/source.dart @@ -1,22 +1,22 @@ import 'package:stripe_payment/src/card_form_payment_request.dart'; class Source { - String object; - Receiver receiver; - AchCreditTransfer achCreditTransfer; - num amount; - String clientSecret; - num created; - String currency; - String flow; - String sourceId; - bool livemode; - Map metadata; - Owner owner; - String statementDescriptor; - String status; - String type; - String usage; + String? object; + Receiver? receiver; + AchCreditTransfer? achCreditTransfer; + num? amount; + String? clientSecret; + num? created; + String? currency; + String? flow; + String? sourceId; + bool? livemode; + Map? metadata; + Owner? owner; + String? statementDescriptor; + String? status; + String? type; + String? usage; Source( {this.object, @@ -72,29 +72,29 @@ class Source { if (this.type != null) data['type'] = this.type; if (this.usage != null) data['usage'] = this.usage; if (this.receiver != null) { - data['receiver'] = this.receiver.toJson(); + data['receiver'] = this.receiver!.toJson(); } if (this.achCreditTransfer != null) { - data['ach_credit_transfer'] = this.achCreditTransfer.toJson(); + data['ach_credit_transfer'] = this.achCreditTransfer!.toJson(); } if (this.amount != null) data['amount'] = this.amount; if (this.metadata != null) { if (this.metadata != null) data['metadata'] = this.metadata; } if (this.owner != null) { - data['owner'] = this.owner.toJson(); + data['owner'] = this.owner!.toJson(); } return data; } } class Receiver { - String address; - int amountCharged; - int amountReceived; - int amountReturned; - String refundAttributesMethod; - String refundAttributesStatus; + String? address; + int? amountCharged; + int? amountReceived; + int? amountReturned; + String? refundAttributesMethod; + String? refundAttributesStatus; Receiver( {this.address, @@ -128,14 +128,14 @@ class Receiver { } class Owner { - BillingAddress address; - String email; - String name; - String phone; - BillingAddress verifiedAddress; - String verifiedEmail; - String verifiedName; - String verifiedPhone; + BillingAddress? address; + String? email; + String? name; + String? phone; + BillingAddress? verifiedAddress; + String? verifiedEmail; + String? verifiedName; + String? verifiedPhone; Owner( {this.address, @@ -175,11 +175,11 @@ class Owner { } class AchCreditTransfer { - String accountNumber; - String bankName; - String fingerprint; - String routingNumber; - String swiftCode; + String? accountNumber; + String? bankName; + String? fingerprint; + String? routingNumber; + String? swiftCode; AchCreditTransfer({this.accountNumber, this.bankName, this.fingerprint, this.routingNumber, this.swiftCode}); @@ -194,7 +194,7 @@ class AchCreditTransfer { } Map toJson() { - final Map data = new Map(); + final Map data = new Map() as Map; if (this.accountNumber != null) data['account_number'] = this.accountNumber; if (this.bankName != null) data['bank_name'] = this.bankName; if (this.fingerprint != null) data['fingerprint'] = this.fingerprint; diff --git a/lib/src/source_params.dart b/lib/src/source_params.dart index 1451db4b..1dcc2130 100644 --- a/lib/src/source_params.dart +++ b/lib/src/source_params.dart @@ -2,21 +2,21 @@ import 'package:flutter/material.dart'; import 'package:stripe_payment/src/token.dart'; class SourceParams { - int amount; - String currency; - String returnURL; - String type; - String name; - String statementDescriptor; - String country; - String email; - CreditCard card; + int? amount; + String? currency; + String? returnURL; + String? type; + String? name; + String? statementDescriptor; + String? country; + String? email; + CreditCard? card; SourceParams( {this.amount, this.currency, - @required this.returnURL, - @required this.type, + required this.returnURL, + required this.type, this.name, this.statementDescriptor, this.country, @@ -46,7 +46,7 @@ class SourceParams { if (this.statementDescriptor != null) data['statement_descriptor'] = this.statementDescriptor; if (this.country != null) data['country'] = this.country; if (this.email != null) data['email'] = this.email; - if (this.card != null) data['card'] = this.card.toJson(); + if (this.card != null) data['card'] = this.card!.toJson(); return data; } } diff --git a/lib/src/stripe_payment.dart b/lib/src/stripe_payment.dart index a37205a9..155bf495 100644 --- a/lib/src/stripe_payment.dart +++ b/lib/src/stripe_payment.dart @@ -33,7 +33,7 @@ class StripePayment { } /// https://tipsi.github.io/tipsi-stripe/docs/usage.html - static Future deviceSupportsNativePay() async { + static Future deviceSupportsNativePay() async { if (kIsWeb) { return false; } else { @@ -48,7 +48,7 @@ class StripePayment { } /// https://tipsi.github.io/tipsi-stripe/docs/canMakeNativePayPayments.html - static Future canMakeNativePayPayments(List networks) async { + static Future canMakeNativePayPayments(List networks) async { if (kIsWeb) { throw UnimplementedError(); } else { @@ -62,13 +62,13 @@ class StripePayment { } } - static Future _deviceSupportsAndroidPay() => _channel.invokeMethod("deviceSupportsAndroidPay"); + static Future _deviceSupportsAndroidPay() => _channel.invokeMethod("deviceSupportsAndroidPay"); - static Future _deviceSupportsApplePay() => _channel.invokeMethod("deviceSupportsApplePay"); + static Future _deviceSupportsApplePay() => _channel.invokeMethod("deviceSupportsApplePay"); /// https://tipsi.github.io/tipsi-stripe/docs/paymentRequestWithNativePay.html static Future paymentRequestWithNativePay( - {@required AndroidPayPaymentRequest androidPayOptions, @required ApplePayPaymentOptions applePayOptions}) { + {required AndroidPayPaymentRequest androidPayOptions, required ApplePayPaymentOptions applePayOptions}) { if (kIsWeb) { throw UnimplementedError(); } else { @@ -88,7 +88,7 @@ class StripePayment { static Future _paymentRequestWithApplePay(ApplePayPaymentOptions options) async { final token = await _channel.invokeMethod("paymentRequestWithApplePay", - {"options": options.json, "items": options.items.map((item) => item.json).toList()}); + {"options": options.json, "items": options.items!.map((item) => item.json).toList()}); return Token.fromJson(token); } @@ -151,7 +151,7 @@ class StripePayment { } /// https://tipsi.github.io/tipsi-stripe/docs/authenticatePaymentIntent.html - static Future authenticatePaymentIntent({@required String clientSecret}) async { + static Future authenticatePaymentIntent({required String clientSecret}) async { assert(clientSecret != null); final result = await _channel.invokeMethod('authenticatePaymentIntent', {"clientSecret": clientSecret}); return PaymentIntentResult.fromJson(result); @@ -166,7 +166,7 @@ class StripePayment { } /// https://tipsi.github.io/tipsi-stripe/docs/authenticateSetupIntent.html - static Future authenticateSetupIntent({@required String clientSecret}) async { + static Future authenticateSetupIntent({required String clientSecret}) async { assert(clientSecret != null); final result = await _channel.invokeMethod('authenticateSetupIntent', {"clientSecret": clientSecret}); return SetupIntentResult.fromJson(result); @@ -186,11 +186,11 @@ class StripePayment { } class StripeOptions { - final String publishableKey; - final String merchantId; - final String androidPayMode; + final String? publishableKey; + final String? merchantId; + final String? androidPayMode; - StripeOptions({@required this.publishableKey, this.merchantId, this.androidPayMode}); + StripeOptions({required this.publishableKey, this.merchantId, this.androidPayMode}); factory StripeOptions.fromJson(Map json) { return StripeOptions( diff --git a/lib/src/token.dart b/lib/src/token.dart index 1c7cf03b..2ab0a304 100644 --- a/lib/src/token.dart +++ b/lib/src/token.dart @@ -1,12 +1,11 @@ class Token { - BankAccount bankAccount; - CreditCard card; - double created; - bool livemode; - String tokenId; - Extra extra; + BankAccount? bankAccount; + CreditCard? card; + double? created; + bool? livemode; + String? tokenId; - Token({this.bankAccount, this.card, this.created, this.livemode, this.tokenId, this.extra}); + Token({this.bankAccount, this.card, this.created, this.livemode, this.tokenId}); factory Token.fromJson(Map json) { return Token( @@ -15,7 +14,6 @@ class Token { created: json['created'] is int ? (json['created'] as int).toDouble() : json['created'], livemode: json['livemode'], tokenId: json['tokenId'], - extra: json['extra'] != null ? Extra.fromJson(json['extra']) : null, ); } @@ -25,28 +23,25 @@ class Token { if (this.livemode != null) data['livemode'] = this.livemode; if (this.tokenId != null) data['tokenId'] = this.tokenId; if (this.bankAccount != null) { - data['bankAccount'] = this.bankAccount.toJson(); + data['bankAccount'] = this.bankAccount!.toJson(); } if (this.card != null) { - data['card'] = this.card.toJson(); - } - if (this.extra != null) { - data['extra'] = this.extra.toJson(); + data['card'] = this.card!.toJson(); } return data; } } class BankAccount { - String accountHolderName; - String accountHolderType; - String accountNumber; - String bankName; - String countryCode; - String currency; - String fingerprint; - String last4; - String routingNumber; + String? accountHolderName; + String? accountHolderType; + String? accountNumber; + String? bankName; + String? countryCode; + String? currency; + String? fingerprint; + String? last4; + String? routingNumber; BankAccount( {this.accountHolderName, @@ -89,23 +84,24 @@ class BankAccount { } class CreditCard { - String addressCity; - String addressCountry; - String addressLine1; - String addressLine2; - String addressState; - String addressZip; - String brand; - String cardId; - String country; - int expMonth; - int expYear; - String funding; - String last4; - String name; - String number; - String cvc; - String token; + String? addressCity; + String? addressCountry; + String? addressLine1; + String? addressLine2; + String? addressState; + String? addressZip; + String? brand; + String? cardId; + String? country; + String? currency; + int? expMonth; + int? expYear; + String? funding; + String? last4; + String? name; + String? number; + String? cvc; + String? token; CreditCard( {this.addressCity, @@ -116,6 +112,7 @@ class CreditCard { this.addressZip, this.brand, this.cardId, + this.currency, this.country, this.expMonth, this.expYear, @@ -136,6 +133,7 @@ class CreditCard { addressZip: json['addressZip'], brand: json['brand'], cardId: json['cardId'], + currency: json['currency'], country: json['country'], expMonth: json['expMonth'], expYear: json['expYear'], @@ -161,6 +159,7 @@ class CreditCard { if (this.expMonth != null) data['expMonth'] = this.expMonth; if (this.expYear != null) data['expYear'] = this.expYear; if (this.funding != null) data['funding'] = this.funding; + if (this.currency != null) data['currency'] = this.currency; data['last4'] = this.last4; if (this.name != null) data['name'] = this.name; if (this.number != null) data['number'] = this.number; @@ -169,91 +168,3 @@ class CreditCard { return data; } } - -class Extra { - Contact shippingContact; - Contact billingContact; - - Extra( - {this.shippingContact, - this.billingContact}); - - factory Extra.fromJson(Map json) { - return Extra( - shippingContact: Contact.fromJson(json['shippingContact']), - billingContact: Contact.fromJson(json['billingContact']), - ); - } - - Map toJson() { - final Map data = new Map(); - if (this.shippingContact != null) data['shippingContact'] = this.shippingContact.toJson(); - if (this.billingContact != null) data['billingContact'] = this.billingContact.toJson(); - return data; - } -} - -class Contact { - String name; - String emailAddress; - String phoneNumber; - String country; - String postalCode; - String state; - String city; - String street; - String isoCountryCode; - String subAdministrativeArea; - String subLocality; - String supplementarySubLocality; - - Contact ( - {this.name, - this.emailAddress, - this.phoneNumber, - this.country, - this.postalCode, - this.state, - this.city, - this.street, - this.isoCountryCode, - this.subAdministrativeArea, - this.subLocality, - this.supplementarySubLocality - }); - - factory Contact.fromJson(Map json) { - print(json); - return Contact( - name: json['name'] ?? "", - emailAddress: json['emailAddress'] ?? "", - phoneNumber: json['phoneNumber'] ?? "", - country: json['country'] ?? "", - postalCode: json['postalCode'] ?? "", - state: json['state'] ?? json['administrativeArea'] ?? "", - city: json['city'] ?? json['locality'] ?? "", - street: json['street'] ?? json['address1'] != null ? json['address1'] + json['address2'] : "", - isoCountryCode: json['ISOCountryCode'] ?? json['countryCode'] ?? "", - subAdministrativeArea: json['subAdministrativeArea'] ?? "", - subLocality: json['subLocality'] ?? json['locality'] ?? "", - supplementarySubLocality: json['supplementarySubLocality'] ?? "", - ); - } - - Map toJson() { - final Map data = new Map(); - if (this.name != null) data['name'] = this.name; - if (this.emailAddress != null) data['emailAddress'] = this.emailAddress; - if (this.phoneNumber != null) data['phoneNumber'] = this.phoneNumber; - if (this.country != null) data['country'] = this.country; - if (this.postalCode != null) data['postalCode'] = this.postalCode; - if (this.state != null) data['state'] = this.state; - if (this.city != null) data['city'] = this.city; - if (this.street != null) data['street'] = this.street; - if (this.isoCountryCode != null) data['ISOCountryCode'] = this.isoCountryCode; - if (this.subAdministrativeArea != null) data['subAdministrativeArea'] = this.subAdministrativeArea; - if (this.subLocality != null) data['subLocality'] = this.subLocality; - if (this.supplementarySubLocality != null) data['supplementarySubLocality'] = this.supplementarySubLocality; - return data; - } -} \ No newline at end of file diff --git a/migration.md b/migration.md new file mode 100644 index 00000000..bc67925d --- /dev/null +++ b/migration.md @@ -0,0 +1,31 @@ +**flutter_stripe_payment** has been discontinued - a new plugin called [flutter_stripe](https://pub.dev/packages/flutter_stripe) should be used instead: + +# Main changes +- the credit card information form is no longer a dialog but can be used as and styled as a native view +- support for [Payment Sheet](https://stripe.com/docs/payments/accept-a-payment?platform=android) +- support for many more [payment providers](https://github.com/flutter-stripe/flutter_stripe/blob/main/stripe_platform_interface/lib/src/models/payment_methods.dart#L36) +- [PCI compliant](https://stripe.com/en-de/guides/pci-compliance), SCA-Ready with [3D Secure authentication](https://stripe.com/docs/payments/3d-secure) +- integration with the [Pay](https://pub.dev/packages/pay) plugin +- documentation, support and regular updates + +# Migration +| Old method name | New method name | Comment | +|-------------------------------|------------------------|-----------------------------------------------------------| +| `setOptions` | `initialize` | | +| `setStripeAccount` | `initialize` | `stripeAccountId` parameter | +| `deviceSupportsNativePay` | - | Apple + Google Pay is supported by using the `pay` plugin or payment sheet | +| `canMakeNativePayPayments` | - | see above | +| `paymentRequestWithNativePay` | - | see above | +| `completeNativePayRequest` | - | see above | +| `cancelNativePayRequest` | - | see above | +| `paymentRequestWithCardForm` | - | use the `CardField` view or payment sheet | +| `createTokenWithCard` | `createToken` | | +| `createTokenWithBankAccount` | - | | +| `createSourceWithParams` | `createPaymentMethod` | | +| `createPaymentMethod` | `createPaymentMethod` | | +| `authenticatePaymentIntent` | `handleCardAction` | | +| `confirmPaymentIntent` | `confirmPaymentMethod` | | +| `authenticateSetupIntent` | - | | +| `confirmSetupIntent` | `confirmSetupIntent` | | + +Check the example app for details on how to use the new plugin. diff --git a/pubspec.yaml b/pubspec.yaml index 435633be..8233a2ae 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,23 +1,21 @@ name: stripe_payment description: A Flutter plugin to integrate the stripe libraries for iOS and Android. Supports Apple / Google Pay, SCA, PSD2 and much more. -version: 1.0.6 -authors: -- Jonas Bark -- John Blanchard +version: 1.1.4 homepage: https://github.com/jonasbark/flutter_stripe_payment environment: - sdk: ">=2.1.0 <3.0.0" + sdk: '>=2.12.0 <3.0.0' + flutter: ">=1.12.0" dependencies: flutter: sdk: flutter -# For information on the generic Dart part of this file, see the -# following page: https://www.dartlang.org/tools/pub/pubspec - -# The following section is specific to Flutter. flutter: plugin: - androidPackage: de.jonasbark.stripepayment - pluginClass: StripePaymentPlugin \ No newline at end of file + platforms: + android: + package: de.jonasbark.stripepayment + pluginClass: StripePaymentPlugin + ios: + pluginClass: StripePaymentPlugin diff --git a/stripe_payment.iml b/stripe_payment.iml deleted file mode 100644 index 50e493bd..00000000 --- a/stripe_payment.iml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/stripe_payment_android.iml b/stripe_payment_android.iml deleted file mode 100644 index 9150d49b..00000000 --- a/stripe_payment_android.iml +++ /dev/null @@ -1,130 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file