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
* 升级 Android/iOS SDK
......
# alipay_kit
[![Build Status](https://cloud.drone.io/api/badges/v7lin/alipay_kit/status.svg)](https://cloud.drone.io/v7lin/alipay_kit)
[![Codecov](https://codecov.io/gh/v7lin/alipay_kit/branch/master/graph/badge.svg)](https://codecov.io/gh/v7lin/alipay_kit)
[![GitHub Tag](https://img.shields.io/github/tag/v7lin/alipay_kit.svg)](https://github.com/v7lin/alipay_kit/releases)
[![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/rxreader/alipay_kit/branch/master/graph/badge.svg)](https://codecov.io/gh/rxreader/alipay_kit)
[![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)
[![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
## fake 系列 libraries
* [flutter版微信SDK](https://github.com/v7lin/wechat_kit)
* [flutter版腾讯(QQ)SDK](https://github.com/v7lin/tencent_kit)
* [flutter版新浪微博SDK](https://github.com/v7lin/weibo_kit)
* [flutter版支付宝SDK](https://github.com/v7lin/alipay_kit)
* [flutter版walle渠道打包工具](https://github.com/v7lin/walle_kit)
* [flutter版微信SDK](https://github.com/rxreader/wechat_kit)
* [flutter版腾讯(QQ)SDK](https://github.com/rxreader/tencent_kit)
* [flutter版新浪微博SDK](https://github.com/rxreader/weibo_kit)
* [flutter版支付宝SDK](https://github.com/rxreader/alipay_kit)
* [flutter版walle渠道打包工具](https://github.com/rxreader/walle_kit)
## dart/flutter 私服
* [simple_pub_server](https://github.com/v7lin/simple_pub_server)
* [simple_pub_server](https://github.com/rxreader/simple_pub_server)
## docs
......@@ -29,6 +29,15 @@ flutter版支付宝SDK
## 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 打包混淆
......@@ -59,13 +68,17 @@ iOS 9系统策略更新,限制了http协议的访问,此外应用需要在
## flutter
* break change
* 2.2.0: Alipay 单例
* 2.1.0: nullsafety & 不再支持 Android embedding v1
* snapshot
```
dependencies:
alipay_kit:
git:
url: https://github.com/v7lin/alipay_kit.git
url: https://github.com/rxreader/alipay_kit.git
```
* release
......
This diff is collapsed.
group 'io.github.v7lin.alipay_kit'
version '2.0.0'
version '2.2.0'
buildscript {
repositories {
google()
maven{
allowInsecureProtocol = true
url 'http://127.0.0.1:8081/repository/maven-public/'
}
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.4'
classpath 'com.android.tools.build:gradle:4.1.0'
}
}
rootProject.allprojects {
repositories {
google()
maven{
allowInsecureProtocol = true
url 'http://127.0.0.1:8081/repository/maven-public/'
}
google()
}
}
......@@ -56,6 +56,4 @@ android {
dependencies {
implementation 'androidx.annotation:annotation:1.0.0'
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
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
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;
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 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.activity.ActivityAware;
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
*/
public class AlipayKitPlugin implements FlutterPlugin, ActivityAware {
// 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.
public class AlipayKitPlugin implements FlutterPlugin, ActivityAware, MethodCallHandler {
//
// 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() {
alipayKit = new AlipayKit();
}
private static final String ARGUMENT_KEY_ORDERINFO = "orderInfo";
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
public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) {
alipayKit.setApplicationContext(binding.getApplicationContext());
alipayKit.setActivity(null);
alipayKit.startListening(binding.getBinaryMessenger());
channel = new MethodChannel(binding.getBinaryMessenger(), "v7lin.github.io/alipay_kit");
channel.setMethodCallHandler(this);
applicationContext = binding.getApplicationContext();
}
@Override
public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
alipayKit.stopListening();
alipayKit.setActivity(null);
alipayKit.setApplicationContext(null);
channel.setMethodCallHandler(null);
channel = null;
applicationContext = null;
}
// --- ActivityAware
@Override
public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) {
alipayKit.setActivity(binding.getActivity());
activity = binding.getActivity();
}
@Override
......@@ -66,6 +82,80 @@ public class AlipayKitPlugin implements FlutterPlugin, ActivityAware {
@Override
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 @@
#
Pod::Spec.new do |s|
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.description = <<-DESC
A powerful Flutter plugin allowing developers to auth/pay with natvie Android & iOS Alipay SDKs.
......
......@@ -3,15 +3,16 @@ import 'dart:convert';
import 'package:alipay_kit/src/crypto/rsa.dart';
import 'package:alipay_kit/src/model/alipay_resp.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
///
class Alipay {
///
Alipay() {
_channel.setMethodCallHandler(_handleMethod);
}
Alipay._();
static Alipay get instance => _instance;
static final Alipay _instance = Alipay._();
static const String _METHOD_ISINSTALLED = 'isInstalled';
static const String _METHOD_PAY = 'pay';
......@@ -30,8 +31,9 @@ class Alipay {
static const String AUTHTYPE_AUTHACCOUNT = 'AUTHACCOUNT';
static const String AUTHTYPE_LOGIN = 'LOGIN';
final MethodChannel _channel =
const MethodChannel('v7lin.github.io/alipay_kit');
late final MethodChannel _channel =
const MethodChannel('v7lin.github.io/alipay_kit')
..setMethodCallHandler(_handleMethod);
final StreamController<AlipayResp> _payRespStreamController =
StreamController<AlipayResp>.broadcast();
......@@ -62,19 +64,17 @@ class Alipay {
}
/// 检测支付宝是否已安装 - x.y.z-Android-Only 版本下 iOS 调用会直接抛出异常 No implementation [MissingPluginException]
Future<bool> isInstalled() {
return _channel.invokeMethod<bool>(_METHOD_ISINSTALLED);
Future<bool> isInstalled() async {
return await _channel.invokeMethod<bool?>(_METHOD_ISINSTALLED) ?? false;
}
/// 支付
Future<void> payOrderJson({
@required String orderInfo,
required String orderInfo,
String signType = SIGNTYPE_RSA2,
@required String privateKey,
required String privateKey,
bool isShowLoading = true,
}) {
assert(orderInfo?.isNotEmpty ?? false);
assert(privateKey?.isNotEmpty ?? false);
return payOrderMap(
orderInfo: json.decode(orderInfo) as Map<String, dynamic>,
signType: signType,
......@@ -85,23 +85,19 @@ class Alipay {
/// 支付
Future<void> payOrderMap({
@required Map<String, dynamic> orderInfo,
required Map<String, dynamic> orderInfo,
String signType = SIGNTYPE_RSA2,
@required String privateKey,
required String privateKey,
bool isShowLoading = true,
}) {
assert(orderInfo?.isNotEmpty ?? false);
assert(privateKey?.isNotEmpty ?? false);
String charset = orderInfo['charset'] as String;
Encoding encoding =
(charset?.isNotEmpty ?? false) ? Encoding.getByName(charset) : null;
encoding ??= utf8;
Map<String, dynamic> clone = <String, dynamic>{
final String? charset = orderInfo['charset'] as String?;
final Encoding encoding = Encoding.getByName(charset) ?? utf8;
final Map<String, dynamic> clone = <String, dynamic>{
...orderInfo,
'sign_type': signType,
};
String param = _param(clone, encoding);
String sign = _sign(clone, signType, privateKey);
final String param = _param(clone, encoding);
final String sign = _sign(clone, signType, privateKey);
return payOrderSign(
orderInfo:
'$param&sign=${Uri.encodeQueryComponent(sign, encoding: encoding)}',
......@@ -111,10 +107,9 @@ class Alipay {
/// 支付 - x.y.z-Android-Only 版本下 iOS 调用会直接抛出异常 No implementation [MissingPluginException]
Future<void> payOrderSign({
@required String orderInfo,
required String orderInfo,
bool isShowLoading = true,
}) {
assert(orderInfo?.isNotEmpty ?? false);
return _channel.invokeMethod<void>(
_METHOD_PAY,
<String, dynamic>{
......@@ -126,22 +121,18 @@ class Alipay {
/// 登录
Future<void> auth({
@required String appId, // 支付宝分配给开发者的应用ID
@required String pid, // 签约的支付宝账号对应的支付宝唯一用户号,以2088开头的16位纯数字组成
@required String targetId, // 商户标识该次用户授权请求的ID,该值在商户端应保持唯一
required String appId, // 支付宝分配给开发者的应用ID
required String pid, // 签约的支付宝账号对应的支付宝唯一用户号,以2088开头的16位纯数字组成
required String targetId, // 商户标识该次用户授权请求的ID,该值在商户端应保持唯一
String authType =
AUTHTYPE_AUTHACCOUNT, // 标识授权类型,取值范围:AUTHACCOUNT 代表授权;LOGIN 代表登录
String signType =
SIGNTYPE_RSA2, // 商户生成签名字符串所使用的签名算法类型,目前支持 RSA2 和 RSA ,推荐使用 RSA2
@required String privateKey,
required String privateKey,
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(privateKey?.isNotEmpty ?? false);
Map<String, dynamic> authInfo = <String, dynamic>{
final Map<String, dynamic> authInfo = <String, dynamic>{
'apiname': 'com.alipay.account.auth',
'method': 'alipay.open.auth.sdk.code.get',
'app_id': appId,
......@@ -154,9 +145,9 @@ class Alipay {
'auth_type': authType,
};
authInfo['sign_type'] = signType;
Encoding encoding = utf8; // utf-8
String param = _param(authInfo, encoding);
String sign = _sign(authInfo, signType, privateKey);
final Encoding encoding = utf8; // utf-8
final String param = _param(authInfo, encoding);
final String sign = _sign(authInfo, signType, privateKey);
return authSign(
info: '$param&sign=${Uri.encodeQueryComponent(sign, encoding: encoding)}',
isShowLoading: isShowLoading,
......@@ -165,10 +156,9 @@ class Alipay {
/// 登录 - x.y.z-Android-Only 版本下 iOS 调用会直接抛出异常 No implementation [MissingPluginException]
Future<void> authSign({
@required String info,
required String info,
bool isShowLoading = true,
}) {
assert(info != null && info.isNotEmpty);
return _channel.invokeMethod<void>(
_METHOD_AUTH,
<String, dynamic>{
......@@ -187,9 +177,9 @@ class Alipay {
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();
String content = keys.map((String e) => '$e=${map[e]}').join('&');
final String content = keys.map((String e) => '$e=${map[e]}').join('&');
String sign;
switch (signType) {
case SIGNTYPE_RSA:
......
import 'dart:convert';
import 'dart:typed_data';
import 'package:asn1lib/asn1lib.dart';
import 'package:pointycastle/pointycastle.dart';
import 'package:pointycastle/signers/rsa_signer.dart';
class RsaKeyParser {
RSAPublicKey parsePublic(String key) {
List<String> rows = key.split('\n');
String header = rows.first;
final List<String> rows = key.split('\n');
final String header = rows.first;
if (header == '-----BEGIN RSA PUBLIC KEY-----') {
return _parsePublic(_parseSequence(rows));
}
......@@ -19,8 +18,8 @@ class RsaKeyParser {
}
RSAPrivateKey parsePrivate(String key) {
List<String> rows = key.split('\n');
String header = rows.first;
final List<String> rows = key.split('\n');
final String header = rows.first;
if (header == '-----BEGIN RSA PRIVATE KEY-----') {
return _parsePrivate(_parseSequence(rows));
}
......@@ -31,41 +30,41 @@ class RsaKeyParser {
}
RSAPublicKey _parsePublic(ASN1Sequence sequence) {
BigInt modulus = (sequence.elements[0] as ASN1Integer).valueAsBigInteger;
BigInt exponent = (sequence.elements[1] as ASN1Integer).valueAsBigInteger;
final BigInt modulus = (sequence.elements![0] as ASN1Integer).integer!;
final BigInt exponent = (sequence.elements![1] as ASN1Integer).integer!;
return RSAPublicKey(modulus, exponent);
}
RSAPrivateKey _parsePrivate(ASN1Sequence sequence) {
BigInt modulus = (sequence.elements[1] as ASN1Integer).valueAsBigInteger;
BigInt exponent = (sequence.elements[3] as ASN1Integer).valueAsBigInteger;
BigInt p = (sequence.elements[4] as ASN1Integer).valueAsBigInteger;
BigInt q = (sequence.elements[5] as ASN1Integer).valueAsBigInteger;
final BigInt modulus = (sequence.elements![1] as ASN1Integer).integer!;
final BigInt exponent = (sequence.elements![3] as ASN1Integer).integer!;
final BigInt? p = (sequence.elements?[4] as ASN1Integer?)?.integer;
final BigInt? q = (sequence.elements?[5] as ASN1Integer?)?.integer;
return RSAPrivateKey(modulus, exponent, p, q);
}
ASN1Sequence _parseSequence(List<String> rows) {
String keyText = rows
final String keyText = rows
.skipWhile((String row) => row.startsWith('-----BEGIN'))
.takeWhile((String row) => !row.startsWith('-----END'))
.map((String row) => row.trim())
.join('');
Uint8List keyBytes = Uint8List.fromList(base64.decode(keyText));
ASN1Parser asn1Parser = ASN1Parser(keyBytes);
final Uint8List keyBytes = Uint8List.fromList(base64.decode(keyText));
final ASN1Parser asn1Parser = ASN1Parser(keyBytes);
return asn1Parser.nextObject() as ASN1Sequence;
}
ASN1Sequence _pkcs8PublicSequence(ASN1Sequence sequence) {
ASN1Object object = sequence.elements[1];
List<int> bytes = object.valueBytes().sublist(1);
ASN1Parser parser = ASN1Parser(Uint8List.fromList(bytes));
final ASN1Object object = sequence.elements![1];
final List<int> bytes = object.valueBytes!.sublist(1);
final ASN1Parser parser = ASN1Parser(Uint8List.fromList(bytes));
return parser.nextObject() as ASN1Sequence;
}
ASN1Sequence _pkcs8PrivateSequence(ASN1Sequence sequence) {
ASN1Object object = sequence.elements[2];
Uint8List bytes = object.valueBytes();
ASN1Parser parser = ASN1Parser(bytes);
final ASN1Object object = sequence.elements![2];
final Uint8List bytes = object.valueBytes!;
final ASN1Parser parser = ASN1Parser(bytes);
return parser.nextObject() as ASN1Sequence;
}
}
......@@ -82,7 +81,7 @@ class RsaSigner {
_rsaSigner
..reset()
..init(true, PrivateKeyParameter<RSAPrivateKey>(_privateKey));
RSASignature signature =
final RSASignature signature =
_rsaSigner.generateSignature(Uint8List.fromList(message));
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';
part 'alipay_auth_result.g.dart';
......@@ -9,7 +9,7 @@ part 'alipay_auth_result.g.dart';
)
class AlipayAuthResult {
AlipayAuthResult({
this.success,
required this.success,
this.resultCode,
this.authCode,
this.userId,
......@@ -18,23 +18,17 @@ class AlipayAuthResult {
factory AlipayAuthResult.fromJson(Map<String, dynamic> json) =>
_$AlipayAuthResultFromJson(json);
@JsonKey(
fromJson: boolFromString,
toJson: boolToString,
)
@NullableStringToBoolConverter()
final bool success;
/// 200 业务处理成功,会返回authCode
/// 1005 账户已冻结,如有疑问,请联系支付宝技术支持
/// 202 系统异常,请稍后再试或联系支付宝技术支持
@JsonKey(
fromJson: intFromString,
toJson: intToString,
)
final int resultCode;
@NullableStringToNullableIntConverter()
final int? resultCode;
final String authCode;
final String userId;
final String? authCode;
final String? userId;
Map<String, dynamic> toJson() => _$AlipayAuthResultToJson(this);
}
......@@ -8,17 +8,20 @@ part of 'alipay_auth_result.dart';
AlipayAuthResult _$AlipayAuthResultFromJson(Map<String, dynamic> json) {
return AlipayAuthResult(
success: boolFromString(json['success'] as String),
resultCode: intFromString(json['result_code'] as String),
authCode: json['auth_code'] as String,
userId: json['user_id'] as String,
success: const NullableStringToBoolConverter()
.fromJson(json['success'] as String?),
resultCode: const NullableStringToNullableIntConverter()
.fromJson(json['result_code'] as String?),
authCode: json['auth_code'] as String?,
userId: json['user_id'] as String?,
);
}
Map<String, dynamic> _$AlipayAuthResultToJson(AlipayAuthResult instance) =>
<String, dynamic>{
'success': boolToString(instance.success),
'result_code': intToString(instance.resultCode),
'success': const NullableStringToBoolConverter().toJson(instance.success),
'result_code': const NullableStringToNullableIntConverter()
.toJson(instance.resultCode),
'auth_code': instance.authCode,
'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:json_annotation/json_annotation.dart';
......@@ -25,21 +25,22 @@ class AlipayResp {
/// 5000——重复请求
/// 6001——用户中途取消
/// 6002——网络连接出错
@JsonKey(
fromJson: intFromString,
toJson: intToString,
)
final int resultStatus;
@NullableStringToNullableIntConverter()
final int? resultStatus;
/// 支付后结果
final String result;
final String? result;
final String memo;
final String? memo;
AlipayAuthResult parseAuthResult() {
if (resultStatus == 9000) {
if (result != null && result.isNotEmpty) {
Map<String, String> params =
bool get isSuccessful => resultStatus == 9000;
bool get isCancelled => resultStatus == 6001;
AlipayAuthResult? parseAuthResult() {
if (isSuccessful) {
if (result?.isNotEmpty ?? false) {
final Map<String, String> params =
Uri.parse('alipay://alipay?$result').queryParameters;
return AlipayAuthResult.fromJson(params);
}
......
......@@ -8,15 +8,17 @@ part of 'alipay_resp.dart';
AlipayResp _$AlipayRespFromJson(Map<String, dynamic> json) {
return AlipayResp(
resultStatus: intFromString(json['resultStatus'] as String),
result: json['result'] as String,
memo: json['memo'] as String,
resultStatus: const NullableStringToNullableIntConverter()
.fromJson(json['resultStatus'] as String?),
result: json['result'] as String?,
memo: json['memo'] as String?,
);
}
Map<String, dynamic> _$AlipayRespToJson(AlipayResp instance) =>
<String, dynamic>{
'resultStatus': intToString(instance.resultStatus),
'resultStatus': const NullableStringToNullableIntConverter()
.toJson(instance.resultStatus),
'result': instance.result,
'memo': instance.memo,
};
This diff is collapsed.
name: alipay_kit
description: A powerful Flutter plugin allowing developers to auth/pay with natvie Android & iOS Alipay SDKs.
version: 2.0.0
homepage: https://github.com/v7lin/fake_alipay
version: 2.2.0-nullsafety #-Android-Only
# author: v7lin <v7lin@qq.com>
homepage: https://github.com/rxreader/alipay_kit
environment:
sdk: ">=2.7.0 <3.0.0"
flutter: ">=1.10.0"
sdk: ">=2.12.0 <3.0.0"
flutter: ">=1.20.0"
dependencies:
asn1lib: ^0.5.8
pointycastle: ^1.0.0
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.
flutter:
# This section identifies this Flutter project as a plugin project.
# The 'pluginClass' and Android 'package' identifiers should not ordinarily
# be modified. They are used by the tooling to maintain consistency when
# adding or updating assets for this project.
plugin:
platforms:
android:
......
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