Commit de8c21d1 authored by 汪林玲's avatar 汪林玲

2.2.0-nullsafety

parent a5d75a7e
## 2.2.0-nullsafety
* 同 2.2.0-nullsafety-Android-Only
## 2.2.0-nullsafety-Android-Only
* Alipay 单例
## 2.1.0-nullsafety-Android-Only
* 同 2.1.0-nullsafety
## 2.1.0-nullsafety
* nullsafety
* 不再支持 Android embedding v1
## 2.0.0 ## 2.0.0
* 升级 Android/iOS SDK * 升级 Android/iOS SDK
......
# alipay_kit # alipay_kit
[![Build Status](https://cloud.drone.io/api/badges/v7lin/alipay_kit/status.svg)](https://cloud.drone.io/v7lin/alipay_kit) [![Build Status](https://cloud.drone.io/api/badges/rxreader/alipay_kit/status.svg)](https://cloud.drone.io/rxreader/alipay_kit)
[![Codecov](https://codecov.io/gh/v7lin/alipay_kit/branch/master/graph/badge.svg)](https://codecov.io/gh/v7lin/alipay_kit) [![Codecov](https://codecov.io/gh/rxreader/alipay_kit/branch/master/graph/badge.svg)](https://codecov.io/gh/rxreader/alipay_kit)
[![GitHub Tag](https://img.shields.io/github/tag/v7lin/alipay_kit.svg)](https://github.com/v7lin/alipay_kit/releases) [![GitHub Tag](https://img.shields.io/github/tag/rxreader/alipay_kit.svg)](https://github.com/rxreader/alipay_kit/releases)
[![Pub Package](https://img.shields.io/pub/v/alipay_kit.svg)](https://pub.dartlang.org/packages/alipay_kit) [![Pub Package](https://img.shields.io/pub/v/alipay_kit.svg)](https://pub.dartlang.org/packages/alipay_kit)
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/v7lin/alipay_kit/blob/master/LICENSE) [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/rxreader/alipay_kit/blob/master/LICENSE)
flutter版支付宝SDK flutter版支付宝SDK
## fake 系列 libraries ## fake 系列 libraries
* [flutter版微信SDK](https://github.com/v7lin/wechat_kit) * [flutter版微信SDK](https://github.com/rxreader/wechat_kit)
* [flutter版腾讯(QQ)SDK](https://github.com/v7lin/tencent_kit) * [flutter版腾讯(QQ)SDK](https://github.com/rxreader/tencent_kit)
* [flutter版新浪微博SDK](https://github.com/v7lin/weibo_kit) * [flutter版新浪微博SDK](https://github.com/rxreader/weibo_kit)
* [flutter版支付宝SDK](https://github.com/v7lin/alipay_kit) * [flutter版支付宝SDK](https://github.com/rxreader/alipay_kit)
* [flutter版walle渠道打包工具](https://github.com/v7lin/walle_kit) * [flutter版walle渠道打包工具](https://github.com/rxreader/walle_kit)
## dart/flutter 私服 ## dart/flutter 私服
* [simple_pub_server](https://github.com/v7lin/simple_pub_server) * [simple_pub_server](https://github.com/rxreader/simple_pub_server)
## docs ## docs
...@@ -29,6 +29,15 @@ flutter版支付宝SDK ...@@ -29,6 +29,15 @@ flutter版支付宝SDK
## android ## android
```groovy
buildscript {
dependencies {
// Android 11兼容,需升级Gradle到3.5.4/3.6.4/4.x.y
classpath 'com.android.tools.build:gradle:3.5.4'
}
}
```
``` ```
# 不需要做任何额外接入工作 # 不需要做任何额外接入工作
# 混淆已打入 Library,随 Library 引用,自动添加到 apk 打包混淆 # 混淆已打入 Library,随 Library 引用,自动添加到 apk 打包混淆
...@@ -59,13 +68,17 @@ iOS 9系统策略更新,限制了http协议的访问,此外应用需要在 ...@@ -59,13 +68,17 @@ iOS 9系统策略更新,限制了http协议的访问,此外应用需要在
## flutter ## flutter
* break change
* 2.2.0: Alipay 单例
* 2.1.0: nullsafety & 不再支持 Android embedding v1
* snapshot * snapshot
``` ```
dependencies: dependencies:
alipay_kit: alipay_kit:
git: git:
url: https://github.com/v7lin/alipay_kit.git url: https://github.com/rxreader/alipay_kit.git
``` ```
* release * release
......
# Specify analysis options.
#
# Until there are meta linter rules, each desired lint must be explicitly enabled.
# See: https://github.com/dart-lang/linter/issues/288
#
# For a list of lints, see: http://dart-lang.github.io/linter/lints/
# See the configuration guide for more
# https://github.com/dart-lang/sdk/tree/master/pkg/analyzer#configuring-the-analyzer
#
# There are other similar analysis options files in the flutter repos,
# which should be kept in sync with this file:
#
# - analysis_options.yaml (this file)
# - packages/flutter/lib/analysis_options_user.yaml
# - https://github.com/flutter/plugins/blob/master/analysis_options.yaml
# - https://github.com/flutter/engine/blob/master/analysis_options.yaml
#
# This file contains the analysis options used by Flutter tools, such as IntelliJ,
# Android Studio, and the `flutter analyze` command.
analyzer:
strong-mode:
implicit-casts: false
implicit-dynamic: false
errors:
# treat missing required parameters as a warning (not a hint)
missing_required_param: warning
# treat missing returns as a warning (not a hint)
missing_return: warning
# allow having TODOs in the code
todo: ignore
# allow self-reference to deprecated members (we do this because otherwise we have
# to annotate every member in every test, assert, etc, when we deprecate something)
deprecated_member_use_from_same_package: ignore
# Ignore analyzer hints for updating pubspecs when using Future or
# Stream and not importing dart:async
# Please see https://github.com/flutter/flutter/pull/24528 for details.
sdk_version_async_exported_from_core: ignore
exclude:
- "lib/*.g.dart"
linter:
rules:
# these rules are documented on and in the same order as
# the Dart Lint rules page to make maintenance easier
# https://github.com/dart-lang/linter/blob/master/example/all.yaml
- always_declare_return_types
- always_put_control_body_on_new_line
# - always_put_required_named_parameters_first # we prefer having parameters in the same order as fields https://github.com/flutter/flutter/issues/10219
- always_require_non_null_named_parameters
- always_specify_types
- always_use_package_imports # we do this commonly
- annotate_overrides
# - avoid_annotating_with_dynamic # conflicts with always_specify_types
# - avoid_as # required for implicit-casts: true
- avoid_bool_literals_in_conditional_expressions
# - avoid_catches_without_on_clauses # we do this commonly
# - avoid_catching_errors # we do this commonly
- avoid_classes_with_only_static_members
# - avoid_double_and_int_checks # only useful when targeting JS runtime
- avoid_empty_else
- avoid_equals_and_hash_code_on_mutable_classes
# - avoid_escaping_inner_quotes # not yet tested
- avoid_field_initializers_in_const_classes
- avoid_function_literals_in_foreach_calls
# - avoid_implementing_value_types # not yet tested
- avoid_init_to_null
# - avoid_js_rounded_ints # only useful when targeting JS runtime
- avoid_null_checks_in_equality_operators
# - avoid_positional_boolean_parameters # not yet tested
# - avoid_print # not yet tested
# - avoid_private_typedef_functions # we prefer having typedef (discussion in https://github.com/flutter/flutter/pull/16356)
# - avoid_redundant_argument_values # not yet tested
- avoid_relative_lib_imports
- avoid_renaming_method_parameters
- avoid_return_types_on_setters
# - avoid_returning_null # there are plenty of valid reasons to return null
# - avoid_returning_null_for_future # not yet tested
- avoid_returning_null_for_void
# - avoid_returning_this # there are plenty of valid reasons to return this
# - avoid_setters_without_getters # not yet tested
- avoid_shadowing_type_parameters
- avoid_single_cascade_in_expression_statements
- avoid_slow_async_io
# - avoid_type_to_string # we do this commonly
- avoid_types_as_parameter_names
# - avoid_types_on_closure_parameters # conflicts with always_specify_types
# - avoid_unnecessary_containers # not yet tested
- avoid_unused_constructor_parameters
- avoid_void_async
# - avoid_web_libraries_in_flutter # not yet tested
- await_only_futures
- camel_case_extensions
- camel_case_types
- cancel_subscriptions
# - cascade_invocations # not yet tested
- cast_nullable_to_non_nullable
# - close_sinks # not reliable enough
# - comment_references # blocked on https://github.com/flutter/flutter/issues/20765
# - constant_identifier_names # needs an opt-out https://github.com/dart-lang/linter/issues/204
- control_flow_in_finally
# - curly_braces_in_flow_control_structures # not required by flutter style
# - diagnostic_describe_all_properties # not yet tested
- directives_ordering
# - do_not_use_environment # we do this commonly
- empty_catches
- empty_constructor_bodies
- empty_statements
- exhaustive_cases
- file_names # not yet tested
- flutter_style_todos
- hash_and_equals
- implementation_imports
# - invariant_booleans # too many false positives: https://github.com/dart-lang/linter/issues/811
- iterable_contains_unrelated_type
# - join_return_with_assignment # not required by flutter style
- leading_newlines_in_multiline_strings
- library_names
- library_prefixes
# - lines_longer_than_80_chars # not required by flutter style
- list_remove_unrelated_type
# - literal_only_boolean_expressions # too many false positives: https://github.com/dart-lang/sdk/issues/34181
# - missing_whitespace_between_adjacent_strings # not yet tested
- no_adjacent_strings_in_list
# - no_default_cases # too many false positives
- no_duplicate_case_values
- no_logic_in_create_state
# - no_runtimeType_toString # ok in tests; we enable this only in packages/
- non_constant_identifier_names
- null_check_on_nullable_type_parameter
# - null_closures # not required by flutter style
# - omit_local_variable_types # opposite of always_specify_types
# - one_member_abstracts # too many false positives
# - only_throw_errors # https://github.com/flutter/flutter/issues/5792
- overridden_fields
- package_api_docs
# - package_names # non conforming packages in sdk
- package_prefixed_library_names
# - parameter_assignments # we do this commonly
- prefer_adjacent_string_concatenation
- prefer_asserts_in_initializer_lists
# - prefer_asserts_with_message # not required by flutter style
- prefer_collection_literals
- prefer_conditional_assignment
- prefer_const_constructors
- prefer_const_constructors_in_immutables
- prefer_const_declarations
- prefer_const_literals_to_create_immutables
# - prefer_constructors_over_static_methods # far too many false positives
- prefer_contains
# - prefer_double_quotes # opposite of prefer_single_quotes
- prefer_equal_for_default_values
# - prefer_expression_function_bodies # conflicts with https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#consider-using--for-short-functions-and-methods
- prefer_final_fields
- prefer_final_in_for_each
- prefer_final_locals
- prefer_for_elements_to_map_fromIterable
- prefer_foreach
# - prefer_function_declarations_over_variables # not yet tested
- prefer_generic_function_type_aliases
- prefer_if_elements_to_conditional_expressions
- prefer_if_null_operators
- prefer_initializing_formals
- prefer_inlined_adds
# - prefer_int_literals # not yet tested
# - prefer_interpolation_to_compose_strings # not yet tested
- prefer_is_empty
- prefer_is_not_empty
- prefer_is_not_operator
- prefer_iterable_whereType
# - prefer_mixin # https://github.com/dart-lang/language/issues/32
# - prefer_null_aware_operators # disable until NNBD, see https://github.com/flutter/flutter/pull/32711#issuecomment-492930932
# - prefer_relative_imports # not yet tested
- prefer_single_quotes
- prefer_spread_collections
- prefer_typing_uninitialized_variables
- prefer_void_to_null
# - provide_deprecation_message # not yet tested
# - public_member_api_docs # enabled on a case-by-case basis; see e.g. packages/analysis_options.yaml
- recursive_getters
# - sized_box_for_whitespace # not yet tested
- slash_for_doc_comments
# - sort_child_properties_last # not yet tested
- sort_constructors_first
# - sort_pub_dependencies # prevents separating pinned transitive dependencies
- sort_unnamed_constructors_first
- test_types_in_equals
- throw_in_finally
- tighten_type_of_initializing_formals
# - type_annotate_public_apis # subset of always_specify_types
- type_init_formals
- unawaited_futures # too many false positives
# - unnecessary_await_in_return # not yet tested
- unnecessary_brace_in_string_interps
- unnecessary_const
# - unnecessary_final # conflicts with prefer_final_locals
- unnecessary_getters_setters
# - unnecessary_lambdas # has false positives: https://github.com/dart-lang/linter/issues/498
- unnecessary_new
- unnecessary_null_aware_assignments
# - unnecessary_null_checks # not yet tested
- unnecessary_null_in_if_null_operators
- unnecessary_nullable_for_final_variable_declarations
- unnecessary_overrides
- unnecessary_parenthesis
# - unnecessary_raw_strings # not yet tested
- unnecessary_statements
- unnecessary_string_escapes
- unnecessary_string_interpolations
- unnecessary_this
- unrelated_type_equality_checks
# - unsafe_html # not yet tested
- use_full_hex_values_for_flutter_colors
# - use_function_type_syntax_for_parameters # not yet tested
- use_is_even_rather_than_modulo
# - use_key_in_widget_constructors # not yet tested
- use_late_for_private_fields_and_variables
- use_raw_strings
- use_rethrow_when_possible
# - use_setters_to_change_properties # not yet tested
# - use_string_buffers # has false positives: https://github.com/dart-lang/sdk/issues/34182
# - use_to_and_as_if_applicable # has false positives, so we prefer to catch this by code-review
- valid_regexps
- void_checks
group 'io.github.v7lin.alipay_kit' group 'io.github.v7lin.alipay_kit'
version '2.0.0' version '2.2.0'
buildscript { buildscript {
repositories { repositories {
google()
maven{ maven{
allowInsecureProtocol = true allowInsecureProtocol = true
url 'http://127.0.0.1:8081/repository/maven-public/' url 'http://127.0.0.1:8081/repository/maven-public/'
} }
google()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.5.4' classpath 'com.android.tools.build:gradle:4.1.0'
} }
} }
rootProject.allprojects { rootProject.allprojects {
repositories { repositories {
google()
maven{ maven{
allowInsecureProtocol = true allowInsecureProtocol = true
url 'http://127.0.0.1:8081/repository/maven-public/' url 'http://127.0.0.1:8081/repository/maven-public/'
} }
google()
} }
} }
...@@ -56,6 +56,4 @@ android { ...@@ -56,6 +56,4 @@ android {
dependencies { dependencies {
implementation 'androidx.annotation:annotation:1.0.0' implementation 'androidx.annotation:annotation:1.0.0'
implementation 'com.qiaomeng:noutdid.alipaysdk:1.0.0@aar' implementation 'com.qiaomeng:noutdid.alipaysdk:1.0.0@aar'
// v15.8.01
//vendorImplementation(name: 'alipaysdk-15.8.01.210112203525', ext: 'aar')
} }
...@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME ...@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip
package io.github.v7lin.alipay_kit;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.AsyncTask;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.alipay.sdk.app.AuthTask;
import com.alipay.sdk.app.PayTask;
import java.lang.ref.WeakReference;
import java.util.Map;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
public class AlipayKit implements MethodChannel.MethodCallHandler {
//
private static final String METHOD_ISINSTALLED = "isInstalled";
private static final String METHOD_PAY = "pay";
private static final String METHOD_AUTH = "auth";
private static final String METHOD_ONPAYRESP = "onPayResp";
private static final String METHOD_ONAUTHRESP = "onAuthResp";
private static final String ARGUMENT_KEY_ORDERINFO = "orderInfo";
private static final String ARGUMENT_KEY_AUTHINFO = "authInfo";
private static final String ARGUMENT_KEY_ISSHOWLOADING = "isShowLoading";
//
private Context applicationContext;
private Activity activity;
private MethodChannel channel;
public AlipayKit() {
super();
}
public AlipayKit(Context applicationContext, Activity activity) {
this.applicationContext = applicationContext;
this.activity = activity;
}
//
public void setApplicationContext(@Nullable Context applicationContext) {
this.applicationContext = applicationContext;
}
public void setActivity(@Nullable Activity activity) {
this.activity = activity;
}
public void startListening(@NonNull BinaryMessenger messenger) {
channel = new MethodChannel(messenger, "v7lin.github.io/alipay_kit");
channel.setMethodCallHandler(this);
}
public void stopListening() {
channel.setMethodCallHandler(null);
channel = null;
}
// --- MethodCallHandler
@Override
public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
if (METHOD_ISINSTALLED.equals(call.method)) {
boolean isInstalled = false;
try {
final PackageManager packageManager = applicationContext.getPackageManager();
PackageInfo info = packageManager.getPackageInfo("com.eg.android.AlipayGphone", PackageManager.GET_SIGNATURES);
isInstalled = info != null;
} catch (PackageManager.NameNotFoundException e) {
}
result.success(isInstalled);
} else if (METHOD_PAY.equals(call.method)) {
final String orderInfo = call.argument(ARGUMENT_KEY_ORDERINFO);
final boolean isShowLoading = call.argument(ARGUMENT_KEY_ISSHOWLOADING);
final WeakReference<Activity> activityRef = new WeakReference<>(activity);
final WeakReference<MethodChannel> channelRef = new WeakReference<>(channel);
new AsyncTask<String, String, Map<String, String>>() {
@Override
protected Map<String, String> doInBackground(String... params) {
Activity activity = activityRef.get();
if (activity != null && !activity.isFinishing()) {
PayTask task = new PayTask(activity);
return task.payV2(orderInfo, isShowLoading);
}
return null;
}
@Override
protected void onPostExecute(Map<String, String> result) {
if (result != null) {
Activity activity = activityRef.get();
MethodChannel channel = channelRef.get();
if (activity != null && !activity.isFinishing() && channel != null) {
channel.invokeMethod(METHOD_ONPAYRESP, result);
}
}
}
}.execute();
result.success(null);
} else if (METHOD_AUTH.equals(call.method)) {
final String authInfo = call.argument(ARGUMENT_KEY_AUTHINFO);
final boolean isShowLoading = call.argument(ARGUMENT_KEY_ISSHOWLOADING);
final WeakReference<Activity> activityRef = new WeakReference<>(activity);
final WeakReference<MethodChannel> channelRef = new WeakReference<>(channel);
new AsyncTask<String, String, Map<String, String>>(){
@Override
protected Map<String, String> doInBackground(String... strings) {
Activity activity = activityRef.get();
if (activity != null && !activity.isFinishing()) {
AuthTask task = new AuthTask(activity);
return task.authV2(authInfo, isShowLoading);
}
return null;
}
@Override
protected void onPostExecute(Map<String, String> result) {
if (result != null) {
Activity activity = activityRef.get();
MethodChannel channel = channelRef.get();
if (activity != null && !activity.isFinishing() && channel != null) {
channel.invokeMethod(METHOD_ONAUTHRESP, result);
}
}
}
}.execute();
result.success(null);
} else {
result.notImplemented();
}
}
}
package io.github.v7lin.alipay_kit; package io.github.v7lin.alipay_kit;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.AsyncTask;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import com.alipay.sdk.app.AuthTask;
import com.alipay.sdk.app.PayTask;
import java.lang.ref.WeakReference;
import java.util.Map;
import io.flutter.embedding.engine.plugins.FlutterPlugin; import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.embedding.engine.plugins.activity.ActivityAware; import io.flutter.embedding.engine.plugins.activity.ActivityAware;
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding; import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
import io.flutter.plugin.common.PluginRegistry.Registrar; import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
/** /**
* AlipayKitPlugin * AlipayKitPlugin
*/ */
public class AlipayKitPlugin implements FlutterPlugin, ActivityAware { public class AlipayKitPlugin implements FlutterPlugin, ActivityAware, MethodCallHandler {
// This static function is optional and equivalent to onAttachedToEngine. It supports the old
// pre-Flutter-1.12 Android projects. You are encouraged to continue supporting
// plugin registration via this function while apps migrate to use the new Android APIs
// post-flutter-1.12 via https://flutter.dev/go/android-project-migration.
// //
// It is encouraged to share logic between onAttachedToEngine and registerWith to keep
// them functionally equivalent. Only one of onAttachedToEngine or registerWith will be called
// depending on the user's project. onAttachedToEngine or registerWith must both be defined
// in the same class.
public static void registerWith(Registrar registrar) {
AlipayKit alipayKit = new AlipayKit(registrar.context(), registrar.activity());
alipayKit.startListening(registrar.messenger());
}
// --- FlutterPlugin private static final String METHOD_ISINSTALLED = "isInstalled";
private static final String METHOD_PAY = "pay";
private static final String METHOD_AUTH = "auth";
private final AlipayKit alipayKit; private static final String METHOD_ONPAYRESP = "onPayResp";
private static final String METHOD_ONAUTHRESP = "onAuthResp";
public AlipayKitPlugin() { private static final String ARGUMENT_KEY_ORDERINFO = "orderInfo";
alipayKit = new AlipayKit(); private static final String ARGUMENT_KEY_AUTHINFO = "authInfo";
} private static final String ARGUMENT_KEY_ISSHOWLOADING = "isShowLoading";
/// The MethodChannel that will the communication between Flutter and native Android
///
/// This local reference serves to register the plugin with the Flutter Engine and unregister it
/// when the Flutter Engine is detached from the Activity
private MethodChannel channel;
private Context applicationContext;
private Activity activity;
// --- FlutterPlugin
@Override @Override
public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) { public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) {
alipayKit.setApplicationContext(binding.getApplicationContext()); channel = new MethodChannel(binding.getBinaryMessenger(), "v7lin.github.io/alipay_kit");
alipayKit.setActivity(null); channel.setMethodCallHandler(this);
alipayKit.startListening(binding.getBinaryMessenger()); applicationContext = binding.getApplicationContext();
} }
@Override @Override
public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
alipayKit.stopListening(); channel.setMethodCallHandler(null);
alipayKit.setActivity(null); channel = null;
alipayKit.setApplicationContext(null); applicationContext = null;
} }
// --- ActivityAware // --- ActivityAware
@Override @Override
public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) { public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) {
alipayKit.setActivity(binding.getActivity()); activity = binding.getActivity();
} }
@Override @Override
...@@ -66,6 +82,80 @@ public class AlipayKitPlugin implements FlutterPlugin, ActivityAware { ...@@ -66,6 +82,80 @@ public class AlipayKitPlugin implements FlutterPlugin, ActivityAware {
@Override @Override
public void onDetachedFromActivity() { public void onDetachedFromActivity() {
alipayKit.setActivity(null); activity = null;
}
// --- MethodCallHandler
@Override
public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
if (METHOD_ISINSTALLED.equals(call.method)) {
boolean isInstalled = false;
try {
final PackageManager packageManager = applicationContext.getPackageManager();
PackageInfo info = packageManager.getPackageInfo("com.eg.android.AlipayGphone", PackageManager.GET_SIGNATURES);
isInstalled = info != null;
} catch (PackageManager.NameNotFoundException ignore) {
}
result.success(isInstalled);
} else if (METHOD_PAY.equals(call.method)) {
final String orderInfo = call.argument(ARGUMENT_KEY_ORDERINFO);
final boolean isShowLoading = call.argument(ARGUMENT_KEY_ISSHOWLOADING);
final WeakReference<Activity> activityRef = new WeakReference<>(activity);
final WeakReference<MethodChannel> channelRef = new WeakReference<>(channel);
new AsyncTask<String, String, Map<String, String>>() {
@Override
protected Map<String, String> doInBackground(String... params) {
Activity activity = activityRef.get();
if (activity != null && !activity.isFinishing()) {
PayTask task = new PayTask(activity);
return task.payV2(orderInfo, isShowLoading);
}
return null;
}
@Override
protected void onPostExecute(Map<String, String> result) {
if (result != null) {
Activity activity = activityRef.get();
MethodChannel channel = channelRef.get();
if (activity != null && !activity.isFinishing() && channel != null) {
channel.invokeMethod(METHOD_ONPAYRESP, result);
}
}
}
}.execute();
result.success(null);
} else if (METHOD_AUTH.equals(call.method)) {
final String authInfo = call.argument(ARGUMENT_KEY_AUTHINFO);
final boolean isShowLoading = call.argument(ARGUMENT_KEY_ISSHOWLOADING);
final WeakReference<Activity> activityRef = new WeakReference<>(activity);
final WeakReference<MethodChannel> channelRef = new WeakReference<>(channel);
new AsyncTask<String, String, Map<String, String>>(){
@Override
protected Map<String, String> doInBackground(String... strings) {
Activity activity = activityRef.get();
if (activity != null && !activity.isFinishing()) {
AuthTask task = new AuthTask(activity);
return task.authV2(authInfo, isShowLoading);
}
return null;
}
@Override
protected void onPostExecute(Map<String, String> result) {
if (result != null) {
Activity activity = activityRef.get();
MethodChannel channel = channelRef.get();
if (activity != null && !activity.isFinishing() && channel != null) {
channel.invokeMethod(METHOD_ONAUTHRESP, result);
}
}
}
}.execute();
result.success(null);
} else {
result.notImplemented();
}
} }
} }
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
# #
Pod::Spec.new do |s| Pod::Spec.new do |s|
s.name = 'alipay_kit' s.name = 'alipay_kit'
s.version = '2.0.0' s.version = '2.2.0'
s.summary = 'A powerful Flutter plugin allowing developers to auth/pay with natvie Android & iOS Alipay SDKs.' s.summary = 'A powerful Flutter plugin allowing developers to auth/pay with natvie Android & iOS Alipay SDKs.'
s.description = <<-DESC s.description = <<-DESC
A powerful Flutter plugin allowing developers to auth/pay with natvie Android & iOS Alipay SDKs. A powerful Flutter plugin allowing developers to auth/pay with natvie Android & iOS Alipay SDKs.
......
...@@ -3,15 +3,16 @@ import 'dart:convert'; ...@@ -3,15 +3,16 @@ import 'dart:convert';
import 'package:alipay_kit/src/crypto/rsa.dart'; import 'package:alipay_kit/src/crypto/rsa.dart';
import 'package:alipay_kit/src/model/alipay_resp.dart'; import 'package:alipay_kit/src/model/alipay_resp.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
/// ///
class Alipay { class Alipay {
/// ///
Alipay() { Alipay._();
_channel.setMethodCallHandler(_handleMethod);
} static Alipay get instance => _instance;
static final Alipay _instance = Alipay._();
static const String _METHOD_ISINSTALLED = 'isInstalled'; static const String _METHOD_ISINSTALLED = 'isInstalled';
static const String _METHOD_PAY = 'pay'; static const String _METHOD_PAY = 'pay';
...@@ -30,8 +31,9 @@ class Alipay { ...@@ -30,8 +31,9 @@ class Alipay {
static const String AUTHTYPE_AUTHACCOUNT = 'AUTHACCOUNT'; static const String AUTHTYPE_AUTHACCOUNT = 'AUTHACCOUNT';
static const String AUTHTYPE_LOGIN = 'LOGIN'; static const String AUTHTYPE_LOGIN = 'LOGIN';
final MethodChannel _channel = late final MethodChannel _channel =
const MethodChannel('v7lin.github.io/alipay_kit'); const MethodChannel('v7lin.github.io/alipay_kit')
..setMethodCallHandler(_handleMethod);
final StreamController<AlipayResp> _payRespStreamController = final StreamController<AlipayResp> _payRespStreamController =
StreamController<AlipayResp>.broadcast(); StreamController<AlipayResp>.broadcast();
...@@ -62,19 +64,17 @@ class Alipay { ...@@ -62,19 +64,17 @@ class Alipay {
} }
/// 检测支付宝是否已安装 - x.y.z-Android-Only 版本下 iOS 调用会直接抛出异常 No implementation [MissingPluginException] /// 检测支付宝是否已安装 - x.y.z-Android-Only 版本下 iOS 调用会直接抛出异常 No implementation [MissingPluginException]
Future<bool> isInstalled() { Future<bool> isInstalled() async {
return _channel.invokeMethod<bool>(_METHOD_ISINSTALLED); return await _channel.invokeMethod<bool?>(_METHOD_ISINSTALLED) ?? false;
} }
/// 支付 /// 支付
Future<void> payOrderJson({ Future<void> payOrderJson({
@required String orderInfo, required String orderInfo,
String signType = SIGNTYPE_RSA2, String signType = SIGNTYPE_RSA2,
@required String privateKey, required String privateKey,
bool isShowLoading = true, bool isShowLoading = true,
}) { }) {
assert(orderInfo?.isNotEmpty ?? false);
assert(privateKey?.isNotEmpty ?? false);
return payOrderMap( return payOrderMap(
orderInfo: json.decode(orderInfo) as Map<String, dynamic>, orderInfo: json.decode(orderInfo) as Map<String, dynamic>,
signType: signType, signType: signType,
...@@ -85,23 +85,19 @@ class Alipay { ...@@ -85,23 +85,19 @@ class Alipay {
/// 支付 /// 支付
Future<void> payOrderMap({ Future<void> payOrderMap({
@required Map<String, dynamic> orderInfo, required Map<String, dynamic> orderInfo,
String signType = SIGNTYPE_RSA2, String signType = SIGNTYPE_RSA2,
@required String privateKey, required String privateKey,
bool isShowLoading = true, bool isShowLoading = true,
}) { }) {
assert(orderInfo?.isNotEmpty ?? false); final String? charset = orderInfo['charset'] as String?;
assert(privateKey?.isNotEmpty ?? false); final Encoding encoding = Encoding.getByName(charset) ?? utf8;
String charset = orderInfo['charset'] as String; final Map<String, dynamic> clone = <String, dynamic>{
Encoding encoding =
(charset?.isNotEmpty ?? false) ? Encoding.getByName(charset) : null;
encoding ??= utf8;
Map<String, dynamic> clone = <String, dynamic>{
...orderInfo, ...orderInfo,
'sign_type': signType, 'sign_type': signType,
}; };
String param = _param(clone, encoding); final String param = _param(clone, encoding);
String sign = _sign(clone, signType, privateKey); final String sign = _sign(clone, signType, privateKey);
return payOrderSign( return payOrderSign(
orderInfo: orderInfo:
'$param&sign=${Uri.encodeQueryComponent(sign, encoding: encoding)}', '$param&sign=${Uri.encodeQueryComponent(sign, encoding: encoding)}',
...@@ -111,10 +107,9 @@ class Alipay { ...@@ -111,10 +107,9 @@ class Alipay {
/// 支付 - x.y.z-Android-Only 版本下 iOS 调用会直接抛出异常 No implementation [MissingPluginException] /// 支付 - x.y.z-Android-Only 版本下 iOS 调用会直接抛出异常 No implementation [MissingPluginException]
Future<void> payOrderSign({ Future<void> payOrderSign({
@required String orderInfo, required String orderInfo,
bool isShowLoading = true, bool isShowLoading = true,
}) { }) {
assert(orderInfo?.isNotEmpty ?? false);
return _channel.invokeMethod<void>( return _channel.invokeMethod<void>(
_METHOD_PAY, _METHOD_PAY,
<String, dynamic>{ <String, dynamic>{
...@@ -126,22 +121,18 @@ class Alipay { ...@@ -126,22 +121,18 @@ class Alipay {
/// 登录 /// 登录
Future<void> auth({ Future<void> auth({
@required String appId, // 支付宝分配给开发者的应用ID required String appId, // 支付宝分配给开发者的应用ID
@required String pid, // 签约的支付宝账号对应的支付宝唯一用户号,以2088开头的16位纯数字组成 required String pid, // 签约的支付宝账号对应的支付宝唯一用户号,以2088开头的16位纯数字组成
@required String targetId, // 商户标识该次用户授权请求的ID,该值在商户端应保持唯一 required String targetId, // 商户标识该次用户授权请求的ID,该值在商户端应保持唯一
String authType = String authType =
AUTHTYPE_AUTHACCOUNT, // 标识授权类型,取值范围:AUTHACCOUNT 代表授权;LOGIN 代表登录 AUTHTYPE_AUTHACCOUNT, // 标识授权类型,取值范围:AUTHACCOUNT 代表授权;LOGIN 代表登录
String signType = String signType =
SIGNTYPE_RSA2, // 商户生成签名字符串所使用的签名算法类型,目前支持 RSA2 和 RSA ,推荐使用 RSA2 SIGNTYPE_RSA2, // 商户生成签名字符串所使用的签名算法类型,目前支持 RSA2 和 RSA ,推荐使用 RSA2
@required String privateKey, required String privateKey,
bool isShowLoading = true, bool isShowLoading = true,
}) { }) {
assert((appId?.isNotEmpty ?? false) && appId.length <= 16);
assert((pid?.isNotEmpty ?? false) && pid.length <= 16);
assert((targetId?.isNotEmpty ?? false) && targetId.length <= 32);
assert(authType == AUTHTYPE_AUTHACCOUNT || authType == AUTHTYPE_LOGIN); assert(authType == AUTHTYPE_AUTHACCOUNT || authType == AUTHTYPE_LOGIN);
assert(privateKey?.isNotEmpty ?? false); final Map<String, dynamic> authInfo = <String, dynamic>{
Map<String, dynamic> authInfo = <String, dynamic>{
'apiname': 'com.alipay.account.auth', 'apiname': 'com.alipay.account.auth',
'method': 'alipay.open.auth.sdk.code.get', 'method': 'alipay.open.auth.sdk.code.get',
'app_id': appId, 'app_id': appId,
...@@ -154,9 +145,9 @@ class Alipay { ...@@ -154,9 +145,9 @@ class Alipay {
'auth_type': authType, 'auth_type': authType,
}; };
authInfo['sign_type'] = signType; authInfo['sign_type'] = signType;
Encoding encoding = utf8; // utf-8 final Encoding encoding = utf8; // utf-8
String param = _param(authInfo, encoding); final String param = _param(authInfo, encoding);
String sign = _sign(authInfo, signType, privateKey); final String sign = _sign(authInfo, signType, privateKey);
return authSign( return authSign(
info: '$param&sign=${Uri.encodeQueryComponent(sign, encoding: encoding)}', info: '$param&sign=${Uri.encodeQueryComponent(sign, encoding: encoding)}',
isShowLoading: isShowLoading, isShowLoading: isShowLoading,
...@@ -165,10 +156,9 @@ class Alipay { ...@@ -165,10 +156,9 @@ class Alipay {
/// 登录 - x.y.z-Android-Only 版本下 iOS 调用会直接抛出异常 No implementation [MissingPluginException] /// 登录 - x.y.z-Android-Only 版本下 iOS 调用会直接抛出异常 No implementation [MissingPluginException]
Future<void> authSign({ Future<void> authSign({
@required String info, required String info,
bool isShowLoading = true, bool isShowLoading = true,
}) { }) {
assert(info != null && info.isNotEmpty);
return _channel.invokeMethod<void>( return _channel.invokeMethod<void>(
_METHOD_AUTH, _METHOD_AUTH,
<String, dynamic>{ <String, dynamic>{
...@@ -187,9 +177,9 @@ class Alipay { ...@@ -187,9 +177,9 @@ class Alipay {
String _sign(Map<String, dynamic> map, String signType, String privateKey) { String _sign(Map<String, dynamic> map, String signType, String privateKey) {
// 参数排序 // 参数排序
List<String> keys = map.keys.toList(); final List<String> keys = map.keys.toList();
keys.sort(); keys.sort();
String content = keys.map((String e) => '$e=${map[e]}').join('&'); final String content = keys.map((String e) => '$e=${map[e]}').join('&');
String sign; String sign;
switch (signType) { switch (signType) {
case SIGNTYPE_RSA: case SIGNTYPE_RSA:
......
import 'dart:convert'; import 'dart:convert';
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:asn1lib/asn1lib.dart';
import 'package:pointycastle/pointycastle.dart'; import 'package:pointycastle/pointycastle.dart';
import 'package:pointycastle/signers/rsa_signer.dart'; import 'package:pointycastle/signers/rsa_signer.dart';
class RsaKeyParser { class RsaKeyParser {
RSAPublicKey parsePublic(String key) { RSAPublicKey parsePublic(String key) {
List<String> rows = key.split('\n'); final List<String> rows = key.split('\n');
String header = rows.first; final String header = rows.first;
if (header == '-----BEGIN RSA PUBLIC KEY-----') { if (header == '-----BEGIN RSA PUBLIC KEY-----') {
return _parsePublic(_parseSequence(rows)); return _parsePublic(_parseSequence(rows));
} }
...@@ -19,8 +18,8 @@ class RsaKeyParser { ...@@ -19,8 +18,8 @@ class RsaKeyParser {
} }
RSAPrivateKey parsePrivate(String key) { RSAPrivateKey parsePrivate(String key) {
List<String> rows = key.split('\n'); final List<String> rows = key.split('\n');
String header = rows.first; final String header = rows.first;
if (header == '-----BEGIN RSA PRIVATE KEY-----') { if (header == '-----BEGIN RSA PRIVATE KEY-----') {
return _parsePrivate(_parseSequence(rows)); return _parsePrivate(_parseSequence(rows));
} }
...@@ -31,41 +30,41 @@ class RsaKeyParser { ...@@ -31,41 +30,41 @@ class RsaKeyParser {
} }
RSAPublicKey _parsePublic(ASN1Sequence sequence) { RSAPublicKey _parsePublic(ASN1Sequence sequence) {
BigInt modulus = (sequence.elements[0] as ASN1Integer).valueAsBigInteger; final BigInt modulus = (sequence.elements![0] as ASN1Integer).integer!;
BigInt exponent = (sequence.elements[1] as ASN1Integer).valueAsBigInteger; final BigInt exponent = (sequence.elements![1] as ASN1Integer).integer!;
return RSAPublicKey(modulus, exponent); return RSAPublicKey(modulus, exponent);
} }
RSAPrivateKey _parsePrivate(ASN1Sequence sequence) { RSAPrivateKey _parsePrivate(ASN1Sequence sequence) {
BigInt modulus = (sequence.elements[1] as ASN1Integer).valueAsBigInteger; final BigInt modulus = (sequence.elements![1] as ASN1Integer).integer!;
BigInt exponent = (sequence.elements[3] as ASN1Integer).valueAsBigInteger; final BigInt exponent = (sequence.elements![3] as ASN1Integer).integer!;
BigInt p = (sequence.elements[4] as ASN1Integer).valueAsBigInteger; final BigInt? p = (sequence.elements?[4] as ASN1Integer?)?.integer;
BigInt q = (sequence.elements[5] as ASN1Integer).valueAsBigInteger; final BigInt? q = (sequence.elements?[5] as ASN1Integer?)?.integer;
return RSAPrivateKey(modulus, exponent, p, q); return RSAPrivateKey(modulus, exponent, p, q);
} }
ASN1Sequence _parseSequence(List<String> rows) { ASN1Sequence _parseSequence(List<String> rows) {
String keyText = rows final String keyText = rows
.skipWhile((String row) => row.startsWith('-----BEGIN')) .skipWhile((String row) => row.startsWith('-----BEGIN'))
.takeWhile((String row) => !row.startsWith('-----END')) .takeWhile((String row) => !row.startsWith('-----END'))
.map((String row) => row.trim()) .map((String row) => row.trim())
.join(''); .join('');
Uint8List keyBytes = Uint8List.fromList(base64.decode(keyText)); final Uint8List keyBytes = Uint8List.fromList(base64.decode(keyText));
ASN1Parser asn1Parser = ASN1Parser(keyBytes); final ASN1Parser asn1Parser = ASN1Parser(keyBytes);
return asn1Parser.nextObject() as ASN1Sequence; return asn1Parser.nextObject() as ASN1Sequence;
} }
ASN1Sequence _pkcs8PublicSequence(ASN1Sequence sequence) { ASN1Sequence _pkcs8PublicSequence(ASN1Sequence sequence) {
ASN1Object object = sequence.elements[1]; final ASN1Object object = sequence.elements![1];
List<int> bytes = object.valueBytes().sublist(1); final List<int> bytes = object.valueBytes!.sublist(1);
ASN1Parser parser = ASN1Parser(Uint8List.fromList(bytes)); final ASN1Parser parser = ASN1Parser(Uint8List.fromList(bytes));
return parser.nextObject() as ASN1Sequence; return parser.nextObject() as ASN1Sequence;
} }
ASN1Sequence _pkcs8PrivateSequence(ASN1Sequence sequence) { ASN1Sequence _pkcs8PrivateSequence(ASN1Sequence sequence) {
ASN1Object object = sequence.elements[2]; final ASN1Object object = sequence.elements![2];
Uint8List bytes = object.valueBytes(); final Uint8List bytes = object.valueBytes!;
ASN1Parser parser = ASN1Parser(bytes); final ASN1Parser parser = ASN1Parser(bytes);
return parser.nextObject() as ASN1Sequence; return parser.nextObject() as ASN1Sequence;
} }
} }
...@@ -82,7 +81,7 @@ class RsaSigner { ...@@ -82,7 +81,7 @@ class RsaSigner {
_rsaSigner _rsaSigner
..reset() ..reset()
..init(true, PrivateKeyParameter<RSAPrivateKey>(_privateKey)); ..init(true, PrivateKeyParameter<RSAPrivateKey>(_privateKey));
RSASignature signature = final RSASignature signature =
_rsaSigner.generateSignature(Uint8List.fromList(message)); _rsaSigner.generateSignature(Uint8List.fromList(message));
return signature.bytes; return signature.bytes;
} }
......
import 'package:json_annotation/json_annotation.dart';
class NullableStringToBoolConverter implements JsonConverter<bool, String?> {
const NullableStringToBoolConverter();
@override
bool fromJson(String? json) {
return json == true.toString();
}
@override
String? toJson(bool object) {
return object.toString();
}
}
class NullableStringToNullableIntConverter
implements JsonConverter<int?, String?> {
const NullableStringToNullableIntConverter();
@override
int? fromJson(String? json) {
if (json is String) {
return int.tryParse(json);
}
return null;
}
@override
String? toJson(int? object) {
return object?.toString();
}
}
int intFromString(String json) {
return (json?.isNotEmpty ?? false) ? int.parse(json) : null;
}
String intToString(int object) {
return object?.toString();
}
bool boolFromString(String json) {
return json != null ? json == true.toString() : null;
}
String boolToString(bool object) {
return object?.toString();
}
import 'package:alipay_kit/src/json/string_converter.dart'; import 'package:alipay_kit/src/json/jser_converter.dart';
import 'package:json_annotation/json_annotation.dart'; import 'package:json_annotation/json_annotation.dart';
part 'alipay_auth_result.g.dart'; part 'alipay_auth_result.g.dart';
...@@ -9,7 +9,7 @@ part 'alipay_auth_result.g.dart'; ...@@ -9,7 +9,7 @@ part 'alipay_auth_result.g.dart';
) )
class AlipayAuthResult { class AlipayAuthResult {
AlipayAuthResult({ AlipayAuthResult({
this.success, required this.success,
this.resultCode, this.resultCode,
this.authCode, this.authCode,
this.userId, this.userId,
...@@ -18,23 +18,17 @@ class AlipayAuthResult { ...@@ -18,23 +18,17 @@ class AlipayAuthResult {
factory AlipayAuthResult.fromJson(Map<String, dynamic> json) => factory AlipayAuthResult.fromJson(Map<String, dynamic> json) =>
_$AlipayAuthResultFromJson(json); _$AlipayAuthResultFromJson(json);
@JsonKey( @NullableStringToBoolConverter()
fromJson: boolFromString,
toJson: boolToString,
)
final bool success; final bool success;
/// 200 业务处理成功,会返回authCode /// 200 业务处理成功,会返回authCode
/// 1005 账户已冻结,如有疑问,请联系支付宝技术支持 /// 1005 账户已冻结,如有疑问,请联系支付宝技术支持
/// 202 系统异常,请稍后再试或联系支付宝技术支持 /// 202 系统异常,请稍后再试或联系支付宝技术支持
@JsonKey( @NullableStringToNullableIntConverter()
fromJson: intFromString, final int? resultCode;
toJson: intToString,
)
final int resultCode;
final String authCode; final String? authCode;
final String userId; final String? userId;
Map<String, dynamic> toJson() => _$AlipayAuthResultToJson(this); Map<String, dynamic> toJson() => _$AlipayAuthResultToJson(this);
} }
...@@ -8,17 +8,20 @@ part of 'alipay_auth_result.dart'; ...@@ -8,17 +8,20 @@ part of 'alipay_auth_result.dart';
AlipayAuthResult _$AlipayAuthResultFromJson(Map<String, dynamic> json) { AlipayAuthResult _$AlipayAuthResultFromJson(Map<String, dynamic> json) {
return AlipayAuthResult( return AlipayAuthResult(
success: boolFromString(json['success'] as String), success: const NullableStringToBoolConverter()
resultCode: intFromString(json['result_code'] as String), .fromJson(json['success'] as String?),
authCode: json['auth_code'] as String, resultCode: const NullableStringToNullableIntConverter()
userId: json['user_id'] as String, .fromJson(json['result_code'] as String?),
authCode: json['auth_code'] as String?,
userId: json['user_id'] as String?,
); );
} }
Map<String, dynamic> _$AlipayAuthResultToJson(AlipayAuthResult instance) => Map<String, dynamic> _$AlipayAuthResultToJson(AlipayAuthResult instance) =>
<String, dynamic>{ <String, dynamic>{
'success': boolToString(instance.success), 'success': const NullableStringToBoolConverter().toJson(instance.success),
'result_code': intToString(instance.resultCode), 'result_code': const NullableStringToNullableIntConverter()
.toJson(instance.resultCode),
'auth_code': instance.authCode, 'auth_code': instance.authCode,
'user_id': instance.userId, 'user_id': instance.userId,
}; };
import 'package:alipay_kit/src/json/string_converter.dart'; import 'package:alipay_kit/src/json/jser_converter.dart';
import 'package:alipay_kit/src/model/alipay_auth_result.dart'; import 'package:alipay_kit/src/model/alipay_auth_result.dart';
import 'package:json_annotation/json_annotation.dart'; import 'package:json_annotation/json_annotation.dart';
...@@ -25,21 +25,22 @@ class AlipayResp { ...@@ -25,21 +25,22 @@ class AlipayResp {
/// 5000——重复请求 /// 5000——重复请求
/// 6001——用户中途取消 /// 6001——用户中途取消
/// 6002——网络连接出错 /// 6002——网络连接出错
@JsonKey( @NullableStringToNullableIntConverter()
fromJson: intFromString, final int? resultStatus;
toJson: intToString,
)
final int resultStatus;
/// 支付后结果 /// 支付后结果
final String result; final String? result;
final String memo; final String? memo;
AlipayAuthResult parseAuthResult() { bool get isSuccessful => resultStatus == 9000;
if (resultStatus == 9000) {
if (result != null && result.isNotEmpty) { bool get isCancelled => resultStatus == 6001;
Map<String, String> params =
AlipayAuthResult? parseAuthResult() {
if (isSuccessful) {
if (result?.isNotEmpty ?? false) {
final Map<String, String> params =
Uri.parse('alipay://alipay?$result').queryParameters; Uri.parse('alipay://alipay?$result').queryParameters;
return AlipayAuthResult.fromJson(params); return AlipayAuthResult.fromJson(params);
} }
......
...@@ -8,15 +8,17 @@ part of 'alipay_resp.dart'; ...@@ -8,15 +8,17 @@ part of 'alipay_resp.dart';
AlipayResp _$AlipayRespFromJson(Map<String, dynamic> json) { AlipayResp _$AlipayRespFromJson(Map<String, dynamic> json) {
return AlipayResp( return AlipayResp(
resultStatus: intFromString(json['resultStatus'] as String), resultStatus: const NullableStringToNullableIntConverter()
result: json['result'] as String, .fromJson(json['resultStatus'] as String?),
memo: json['memo'] as String, result: json['result'] as String?,
memo: json['memo'] as String?,
); );
} }
Map<String, dynamic> _$AlipayRespToJson(AlipayResp instance) => Map<String, dynamic> _$AlipayRespToJson(AlipayResp instance) =>
<String, dynamic>{ <String, dynamic>{
'resultStatus': intToString(instance.resultStatus), 'resultStatus': const NullableStringToNullableIntConverter()
.toJson(instance.resultStatus),
'result': instance.result, 'result': instance.result,
'memo': instance.memo, 'memo': instance.memo,
}; };
# Generated by pub # Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile # See https://dart.dev/tools/pub/glossary#lockfile
packages: packages:
asn1lib: _fe_analyzer_shared:
dependency: "direct main" dependency: transitive
description:
name: _fe_analyzer_shared
url: "https://pub.flutter-io.cn"
source: hosted
version: "29.0.0"
analyzer:
dependency: transitive
description:
name: analyzer
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.6.0"
args:
dependency: transitive
description:
name: args
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.3.0"
async:
dependency: transitive
description:
name: async
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.8.1"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.0"
build:
dependency: transitive
description: description:
name: asn1lib name: build
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "0.5.15" version: "2.1.1"
build_config:
dependency: transitive
description:
name: build_config
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.0"
build_daemon:
dependency: transitive
description:
name: build_daemon
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.0.1"
build_resolvers:
dependency: transitive
description:
name: build_resolvers
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.0.4"
build_runner:
dependency: "direct dev"
description:
name: build_runner
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.4"
build_runner_core:
dependency: transitive
description:
name: build_runner_core
url: "https://pub.flutter-io.cn"
source: hosted
version: "7.2.2"
built_collection:
dependency: transitive
description:
name: built_collection
url: "https://pub.flutter-io.cn"
source: hosted
version: "5.1.1"
built_value:
dependency: transitive
description:
name: built_value
url: "https://pub.flutter-io.cn"
source: hosted
version: "8.1.2"
characters: characters:
dependency: transitive dependency: transitive
description: description:
...@@ -15,6 +99,41 @@ packages: ...@@ -15,6 +99,41 @@ packages:
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.1.0" version: "1.1.0"
charcode:
dependency: transitive
description:
name: charcode
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.3.1"
checked_yaml:
dependency: transitive
description:
name: checked_yaml
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.0.1"
cli_util:
dependency: transitive
description:
name: cli_util
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.3.5"
clock:
dependency: transitive
description:
name: clock
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.0"
code_builder:
dependency: transitive
description:
name: code_builder
url: "https://pub.flutter-io.cn"
source: hosted
version: "4.1.0"
collection: collection:
dependency: transitive dependency: transitive
description: description:
...@@ -22,18 +141,135 @@ packages: ...@@ -22,18 +141,135 @@ packages:
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.15.0" version: "1.15.0"
convert:
dependency: transitive
description:
name: convert
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.0.1"
crypto:
dependency: transitive
description:
name: crypto
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.0.1"
dart_style:
dependency: transitive
description:
name: dart_style
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.2.0"
fake_async:
dependency: transitive
description:
name: fake_async
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.2.0"
file:
dependency: transitive
description:
name: file
url: "https://pub.flutter-io.cn"
source: hosted
version: "6.1.2"
fixnum:
dependency: transitive
description:
name: fixnum
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.0"
flutter: flutter:
dependency: "direct main" dependency: "direct main"
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.0" version: "0.0.0"
flutter_test:
dependency: "direct dev"
description: flutter
source: sdk
version: "0.0.0"
frontend_server_client:
dependency: transitive
description:
name: frontend_server_client
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.2"
glob:
dependency: transitive
description:
name: glob
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.0.2"
graphs:
dependency: transitive
description:
name: graphs
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.0"
http_multi_server:
dependency: transitive
description:
name: http_multi_server
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.0.1"
http_parser:
dependency: transitive
description:
name: http_parser
url: "https://pub.flutter-io.cn"
source: hosted
version: "4.0.0"
io:
dependency: transitive
description:
name: io
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.3"
js:
dependency: transitive
description:
name: js
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.6.3"
json_annotation: json_annotation:
dependency: "direct main" dependency: "direct main"
description: description:
name: json_annotation name: json_annotation
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "3.1.1" version: "4.1.0"
json_serializable:
dependency: "direct dev"
description:
name: json_serializable
url: "https://pub.flutter-io.cn"
source: hosted
version: "5.0.2"
logging:
dependency: transitive
description:
name: logging
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.2"
matcher:
dependency: transitive
description:
name: matcher
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.12.10"
meta: meta:
dependency: transitive dependency: transitive
description: description:
...@@ -41,18 +277,151 @@ packages: ...@@ -41,18 +277,151 @@ packages:
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.7.0" version: "1.7.0"
mime:
dependency: transitive
description:
name: mime
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.0"
package_config:
dependency: transitive
description:
name: package_config
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.0.2"
path:
dependency: transitive
description:
name: path
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.8.0"
pedantic:
dependency: "direct dev"
description:
name: pedantic
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.11.1"
pointycastle: pointycastle:
dependency: "direct main" dependency: "direct main"
description: description:
name: pointycastle name: pointycastle
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.0.2" version: "3.3.4"
pool:
dependency: transitive
description:
name: pool
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.5.0"
pub_semver:
dependency: transitive
description:
name: pub_semver
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.0"
pubspec_parse:
dependency: transitive
description:
name: pubspec_parse
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.0"
shelf:
dependency: transitive
description:
name: shelf
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.2.0"
shelf_web_socket:
dependency: transitive
description:
name: shelf_web_socket
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.1"
sky_engine: sky_engine:
dependency: transitive dependency: transitive
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.99" version: "0.0.99"
source_gen:
dependency: transitive
description:
name: source_gen
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.1"
source_helper:
dependency: transitive
description:
name: source_helper
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.3.0"
source_span:
dependency: transitive
description:
name: source_span
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.8.1"
stack_trace:
dependency: transitive
description:
name: stack_trace
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.10.0"
stream_channel:
dependency: transitive
description:
name: stream_channel
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.0"
stream_transform:
dependency: transitive
description:
name: stream_transform
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.0.0"
string_scanner:
dependency: transitive
description:
name: string_scanner
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.0"
term_glyph:
dependency: transitive
description:
name: term_glyph
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.2.0"
test_api:
dependency: transitive
description:
name: test_api
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.4.2"
timing:
dependency: transitive
description:
name: timing
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.0"
typed_data: typed_data:
dependency: transitive dependency: transitive
description: description:
...@@ -67,6 +436,27 @@ packages: ...@@ -67,6 +436,27 @@ packages:
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "2.1.0" version: "2.1.0"
watcher:
dependency: transitive
description:
name: watcher
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.1"
web_socket_channel:
dependency: transitive
description:
name: web_socket_channel
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.0"
yaml:
dependency: transitive
description:
name: yaml
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.1.0"
sdks: sdks:
dart: ">=2.12.0 <3.0.0" dart: ">=2.14.0 <3.0.0"
flutter: ">=1.10.0" flutter: ">=1.20.0"
name: alipay_kit name: alipay_kit
description: A powerful Flutter plugin allowing developers to auth/pay with natvie Android & iOS Alipay SDKs. description: A powerful Flutter plugin allowing developers to auth/pay with natvie Android & iOS Alipay SDKs.
version: 2.0.0 version: 2.2.0-nullsafety #-Android-Only
homepage: https://github.com/v7lin/fake_alipay # author: v7lin <v7lin@qq.com>
homepage: https://github.com/rxreader/alipay_kit
environment: environment:
sdk: ">=2.7.0 <3.0.0" sdk: ">=2.12.0 <3.0.0"
flutter: ">=1.10.0" flutter: ">=1.20.0"
dependencies: dependencies:
asn1lib: ^0.5.8
pointycastle: ^1.0.0
flutter: flutter:
sdk: flutter sdk: flutter
json_annotation: '>=2.0.0 <4.0.0' pointycastle: ^3.0.0-nullsafety.2
json_annotation: ^4.0.0
dev_dependencies:
flutter_test:
sdk: flutter
pedantic:
build_runner:
json_serializable:
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
# The following section is specific to Flutter. # The following section is specific to Flutter.
flutter: flutter:
# This section identifies this Flutter project as a plugin project.
# The 'pluginClass' and Android 'package' identifiers should not ordinarily
# be modified. They are used by the tooling to maintain consistency when
# adding or updating assets for this project.
plugin: plugin:
platforms: platforms:
android: android:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment