提交 82f72e78 authored 作者: JarvanMo's avatar JarvanMo

introduce v4

上级 00231ca2
......@@ -16,14 +16,14 @@ RUN sudo apt-get update && sudo apt-get install -y google-cloud-sdk && \
gcloud config set component_manager/disable_update_check true
RUN yes | sdkmanager \
"platforms;android-29" \
"build-tools;29.0.2" \
"platforms;android-33" \
"build-tools;33.0.2" \
"extras;google;m2repository" \
"extras;android;m2repository"
RUN yes | sdkmanager \
"platforms;android-30" \
"build-tools;28.0.3" \
"platforms;android-32" \
"build-tools;33.0.2" \
"extras;google;m2repository" \
"extras;android;m2repository"
......
include: package:flutter_lints/flutter.yaml
# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options
......@@ -6,3 +6,4 @@
.DS_Store
/build
/captures
.cxx
......@@ -9,12 +9,12 @@ buildscript {
}
dependencies {
classpath 'com.android.tools.build:gradle:7.1.2'
classpath 'com.android.tools.build:gradle:7.3.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
rootProject.allprojects {
allprojects {
repositories {
google()
mavenCentral()
......@@ -25,26 +25,38 @@ apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
android {
namespace "com.jarvan.fluwx"
compileSdkVersion 31
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
test.java.srcDirs += 'src/test/kotlin'
}
defaultConfig {
minSdkVersion 16
consumerProguardFiles 'consumer-proguard-rules.txt'
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
lintOptions {
disable 'InvalidPackage'
}
}
dependencies {
dependencies {
api 'com.tencent.mm.opensdk:wechat-sdk-android:6.8.24'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4'
implementation 'id.zelory:compressor:3.0.1'
implementation 'com.squareup.okhttp3:okhttp:4.9.1'
testImplementation 'junit:junit:4.13.2'
implementation 'com.squareup.okhttp3:okhttp:4.10.0'
testImplementation 'org.jetbrains.kotlin:kotlin-test'
testImplementation 'org.mockito:mockito-core:5.0.0'
}
testOptions {
unitTests.all {
useJUnitPlatform()
testLogging {
events "passed", "skipped", "failed", "standardOut", "standardError"
outputs.upToDateWhen {false}
showStandardStreams = true
}
}
}
}
org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true
android.enableJetifier=true
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.jarvan.fluwx">
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
......@@ -14,8 +13,8 @@
<application>
<activity
android:name=".wxapi.FluwxWXEntryActivity"
android:launchMode="singleTask"
android:exported="false"
android:launchMode="singleTask"
android:taskAffinity="${applicationId}"
android:theme="@style/DisablePreviewTheme" />
......@@ -25,13 +24,13 @@
android:launchMode="singleTop"
android:targetActivity="com.jarvan.fluwx.wxapi.FluwxWXEntryActivity"
android:taskAffinity="${applicationId}"
android:theme="@style/DisablePreviewTheme"/>
android:theme="@style/DisablePreviewTheme" />
<activity-alias
android:name="${applicationId}.wxapi.WXPayEntryActivity"
android:exported="true"
android:launchMode="singleInstance"
android:targetActivity="com.jarvan.fluwx.wxapi.FluwxWXEntryActivity"
android:theme="@style/DisablePreviewTheme"/>
android:theme="@style/DisablePreviewTheme" />
<provider
android:name="com.jarvan.fluwx.FluwxFileProvider"
......
package com.jarvan.fluwx
class FluwxTest {
fun test(){}
}
\ No newline at end of file
package com.jarvan.fluwx
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import kotlin.test.Test
import org.mockito.Mockito
/*
* This demonstrates a simple unit test of the Kotlin portion of this plugin's implementation.
*
* Once you have built the plugin's example app, you can run these tests from the command
* line by running `./gradlew testDebugUnitTest` in the `example/android/` directory, or
* you can run them directly from IDEs that support JUnit such as Android Studio.
*/
internal class FluwxPluginTest {
@Test
fun onMethodCall_getPlatformVersion_returnsExpectedValue() {
val plugin = FluwxPlugin()
val call = MethodCall("getPlatformVersion", null)
val mockResult: MethodChannel.Result = Mockito.mock(MethodChannel.Result::class.java)
plugin.onMethodCall(call, mockResult)
Mockito.verify(mockResult).success("Android " + android.os.Build.VERSION.RELEASE)
}
}
......@@ -8,7 +8,7 @@
.buildlog/
.history
.svn/
**/Podfile.lock
migrate_working_dir/
# IntelliJ related
*.iml
......@@ -24,7 +24,6 @@
# Flutter/Dart/Pub related
**/doc/api/
**/ios/Flutter/.last_build_id
**/ios/Flutter/flutter_export_environment.sh
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
......@@ -33,11 +32,13 @@
.pub/
/build/
# Web related
lib/generated_plugin_registrant.dart
# Symbolication related
app.*.symbols
# Obfuscation related
app.*.map.json
# Android Studio will place build artifacts here
/android/app/debug
/android/app/profile
/android/app/release
# 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: 0b8abb4724aa590dd0f429683339b1e045a1594d
channel: stable
project_type: app
......@@ -8,9 +8,9 @@ This project is a starting point for a Flutter application.
A few resources to get you started if this is your first Flutter project:
- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab)
- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook)
- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
For help getting started with Flutter, view our
[online documentation](https://flutter.dev/docs), which offers tutorials,
For help getting started with Flutter development, view the
[online documentation](https://docs.flutter.dev/), which offers tutorials,
samples, guidance on mobile development, and a full API reference.
# This file configures the analyzer, which statically analyzes Dart code to
# check for errors, warnings, and lints.
#
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
# invoked from the command line by running `flutter analyze`.
# The following line activates a set of recommended lints for Flutter apps,
# packages, and plugins designed to encourage good coding practices.
include: package:flutter_lints/flutter.yaml
linter:
# The lint rules applied to this project can be customized in the
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
# included above or to enable additional rules. A list of all available lints
# and their documentation is published at
# https://dart-lang.github.io/linter/lints/index.html.
#
# Instead of disabling a lint rule for the entire project in the
# section below, it can also be suppressed for a single line of code
# or a specific dart file by using the `// ignore: name_of_lint` and
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
# producing the lint.
rules:
# avoid_print: false # Uncomment to disable the `avoid_print` rule
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options
gradle-wrapper.jar
**.classpath
**.project
**.settings
/.gradle
/captures/
/gradlew
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java
# Remember to never publicly share your keystore.
# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
key.properties
**/*.keystore
**/*.jks
plugins {
id "com.android.application"
id "kotlin-android"
id "dev.flutter.flutter-gradle-plugin"
}
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
......@@ -6,12 +12,6 @@ if (localPropertiesFile.exists()) {
}
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
......@@ -22,32 +22,27 @@ if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
compileSdkVersion 31
namespace "com.jarvan.fluwx_example"
compileSdkVersion flutter.compileSdkVersion
ndkVersion flutter.ndkVersion
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
lintOptions {
disable 'InvalidPackage'
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "net.sourceforge.simcpux"
// You can update the following values to match your application needs.
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
minSdkVersion 16
targetSdkVersion 31
targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
flavorDimensions "branch"
buildTypes {
release {
// TODO: Add your own signing config for the release build.
......@@ -73,7 +68,4 @@ flutter {
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test:runner:1.4.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.jarvan.fluwx_example">
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
calls FlutterMain.startInitialization(this); in its onCreate method.
In most cases you can leave this as-is, but you if you want to provide
......@@ -28,9 +27,9 @@
<activity
android:name=".MainActivity"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:exported="true"
android:hardwareAccelerated="true"
android:launchMode="singleTop"
android:exported="true"
android:theme="@style/LaunchTheme"
android:windowSoftInputMode="adjustResize">
<intent-filter>
......
......@@ -5,7 +5,6 @@ import android.os.Bundle
import com.jarvan.fluwx.handlers.FluwxRequestHandler
import io.flutter.embedding.android.FlutterActivity
class MainActivity: FlutterActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
......
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
Flutter draws its first frame -->
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>
......@@ -6,7 +6,7 @@ buildscript {
}
dependencies {
classpath 'com.android.tools.build:gradle:7.1.2'
classpath 'com.android.tools.build:gradle:7.3.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
......@@ -26,6 +26,6 @@ subprojects {
project.evaluationDependsOn(':app')
}
task clean(type: Delete) {
tasks.register("clean", Delete) {
delete rootProject.buildDir
}
......@@ -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-7.4-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip
include ':app'
pluginManagement {
def flutterSdkPath = {
def properties = new Properties()
file("local.properties").withInputStream { properties.load(it) }
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
return flutterSdkPath
}
settings.ext.flutterSdkPath = flutterSdkPath()
def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
includeBuild("${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle")
def plugins = new Properties()
def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
if (pluginsFile.exists()) {
pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
plugins {
id "dev.flutter.flutter-gradle-plugin" version "1.0.0" apply false
}
}
plugins.each { name, path ->
def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
include ":$name"
project(":$name").projectDir = pluginDirectory
}
include ":app"
apply from: "${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle/app_plugin_loader.gradle"
// This is a basic Flutter integration test.
//
// Since integration tests run in a full Flutter application, they can interact
// with the host side of a plugin implementation, unlike Dart unit tests.
//
// For more information about Flutter integration tests, please see
// https://docs.flutter.dev/cookbook/testing/integration/introduction
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
import 'package:fluwx/fluwx.dart';
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
testWidgets('getPlatformVersion test', (WidgetTester tester) async {
});
}
**/dgph
*.mode1v3
*.mode2v3
*.moved-aside
......@@ -11,7 +12,6 @@
Icon?
**/Pods/
**/.symlinks/
Podfile.lock
profile
xcuserdata
**/.generated/
......@@ -19,6 +19,7 @@ Flutter/App.framework
Flutter/Flutter.framework
Flutter/Flutter.podspec
Flutter/Generated.xcconfig
Flutter/ephemeral/
Flutter/app.flx
Flutter/app.zip
Flutter/flutter_assets/
......
......@@ -3,7 +3,7 @@
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<string>en</string>
<key>CFBundleExecutable</key>
<string>App</string>
<key>CFBundleIdentifier</key>
......
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "Generated.xcconfig"
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig"
......@@ -29,6 +29,9 @@ flutter_ios_podfile_setup
target 'Runner' do
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
target 'RunnerTests' do
inherit! :search_paths
end
end
post_install do |installer|
......
......@@ -37,6 +37,17 @@
</BuildableReference>
</MacroExpansion>
<Testables>
<TestableReference
skipped = "NO"
parallelizable = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "331C80F0294D02FB00263BE5"
BuildableName = "RunnerTests.xctest"
BlueprintName = "RunnerTests"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
......
......@@ -4,6 +4,8 @@
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
<string>Fluwx</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
......@@ -18,22 +20,8 @@
<string>$(FLUTTER_BUILD_NAME)</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>wxd930ea5d5a258f4f</string>
</dict>
</array>
<key>CFBundleVersion</key>
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSApplicationQueriesSchemes</key>
<array>
<string>weixin</string>
<string>weixinULAPI</string>
</array>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
......
......@@ -26,6 +26,8 @@ class MyApp extends StatefulWidget {
}
class _MyAppState extends State<MyApp> {
Fluwx fluwx = Fluwx();
@override
void initState() {
super.initState();
......@@ -33,14 +35,14 @@ class _MyAppState extends State<MyApp> {
}
_initFluwx() async {
await registerWxApi(
await fluwx.registerWxApi(
appId: 'wxd930ea5d5a258f4f',
doOnAndroid: true,
doOnIOS: true,
universalLink: 'https://your.univerallink.com/link/',
);
var result = await isWeChatInstalled;
print('is installed $result');
var result = await fluwx.isWeChatInstalled;
debugPrint('is installed $result');
}
// Platform messages are asynchronous, so we initialize in an async method.
......@@ -51,20 +53,20 @@ class _MyAppState extends State<MyApp> {
return MaterialApp(
routes: <String, WidgetBuilder>{
'shareText': (context) => ShareTextPage(),
'shareImage': (context) => ShareImagePage(),
'shareWebPage': (context) => ShareWebPagePage(),
'shareMusic': (context) => ShareMusicPage(),
'shareVideo': (context) => ShareVideoPage(),
'sendAuth': (context) => SendAuthPage(),
'shareImage': (context) => const ShareImagePage(),
'shareWebPage': (context) => const ShareWebPagePage(),
'shareMusic': (context) => const ShareMusicPage(),
'shareVideo': (context) => const ShareVideoPage(),
'sendAuth': (context) => const SendAuthPage(),
'shareMiniProgram': (context) => ShareMiniProgramPage(),
'pay': (context) => PayPage(),
'launchMiniProgram': (context) => LaunchMiniProgramPage(),
'subscribeMessage': (ctx) => SubscribeMessagePage(),
'AuthByQRCode': (ctx) => AuthByQRCodePage(),
'AutoDeduct': (ctx) => SignAutoDeductPage(),
'pay': (context) => const PayPage(),
'launchMiniProgram': (context) => const LaunchMiniProgramPage(),
'subscribeMessage': (ctx) => const SubscribeMessagePage(),
'AuthByQRCode': (ctx) => const AuthByQRCodePage(),
'AutoDeduct': (ctx) => const SignAutoDeductPage(),
},
home: Scaffold(
appBar: AppBar(title: const Text('Plugin example app')),
appBar: AppBar(title: const Text('Fluwx sample')),
body: ShareSelectorPage(),
),
);
......@@ -72,6 +74,10 @@ class _MyAppState extends State<MyApp> {
}
class ShareSelectorPage extends StatelessWidget {
final Fluwx fluwx = Fluwx();
ShareSelectorPage({super.key});
@override
Widget build(BuildContext context) {
return Center(
......@@ -81,8 +87,8 @@ class ShareSelectorPage extends StatelessWidget {
padding: const EdgeInsets.all(8.0),
child: OutlinedButton(
onPressed: () async {
String? extMsg = await getExtMsg();
print('extMsg:$extMsg\n');
String? extMsg = await fluwx.getExtMsg();
debugPrint('extMsg:$extMsg\n');
},
child: const Text('Get ExtMessage'),
),
......@@ -91,8 +97,9 @@ class ShareSelectorPage extends StatelessWidget {
padding: const EdgeInsets.all(8.0),
child: OutlinedButton(
onPressed: () async {
bool? success = await startLog(logLevel: WXLogLevel.NORMAL);
print('startLog:$success\n');
bool? success =
await fluwx.startLog(logLevel: WXLogLevel.normal);
debugPrint('startLog:$success\n');
},
child: const Text('start log'),
),
......@@ -101,8 +108,8 @@ class ShareSelectorPage extends StatelessWidget {
padding: const EdgeInsets.all(8.0),
child: OutlinedButton(
onPressed: () async {
dynamic success = await stopLog();
print('stopLog:$success\n');
dynamic success = await fluwx.stopLog();
debugPrint('stopLog:$success\n');
},
child: const Text('stop log'),
),
......@@ -219,7 +226,7 @@ class ShareSelectorPage extends StatelessWidget {
padding: const EdgeInsets.all(8.0),
child: OutlinedButton(
onPressed: () {
openWeChatApp();
fluwx.openWeChatApp();
},
child: const Text('Open WeChat App'),
),
......
......@@ -6,11 +6,11 @@ class AuthByQRCodePage extends StatefulWidget {
const AuthByQRCodePage({Key? key}) : super(key: key);
@override
_AuthByQRCodePageState createState() => _AuthByQRCodePageState();
State<AuthByQRCodePage> createState() => _AuthByQRCodePageState();
}
class _AuthByQRCodePageState extends State<AuthByQRCodePage> {
String _status = 'status';
final String _status = 'status';
Uint8List? _image;
@override
......
......@@ -5,30 +5,35 @@ class LaunchMiniProgramPage extends StatefulWidget {
const LaunchMiniProgramPage({Key? key}) : super(key: key);
@override
_LaunchMiniProgramPageState createState() => _LaunchMiniProgramPageState();
State<LaunchMiniProgramPage> createState() => _LaunchMiniProgramPageState();
}
class _LaunchMiniProgramPageState extends State<LaunchMiniProgramPage> {
String? _result = '无';
final Fluwx fluwx = Fluwx();
late Function(WeChatResponse) responseListener;
@override
void dispose() {
super.dispose();
_result = null;
fluwx.unsubscribeResponse(responseListener);
}
@override
void initState() {
super.initState();
weChatResponseEventHandler.listen((res) {
if (res is WeChatLaunchMiniProgramResponse) {
responseListener = (response) {
if (response is WeChatLaunchMiniProgramResponse) {
if (mounted) {
setState(() {
_result = 'isSuccessful:${res.isSuccessful}';
_result = 'isSuccessful:${response.isSuccessful}';
});
}
}
});
}
};
@override
void dispose() {
super.dispose();
_result = null;
fluwx.subscribeResponse(responseListener);
}
@override
......@@ -41,7 +46,7 @@ class _LaunchMiniProgramPageState extends State<LaunchMiniProgramPage> {
children: <Widget>[
OutlinedButton(
onPressed: () {
launchWeChatMiniProgram(username: 'gh_d43f693ca31f');
fluwx.launchMiniProgram(username: 'gh_d43f693ca31f');
},
child: const Text('Launch MiniProgrom'),
),
......
......@@ -2,34 +2,38 @@ import 'dart:convert';
import 'dart:io' as H;
import 'package:flutter/material.dart';
import 'package:fluwx/fluwx.dart' as fluwx;
import 'package:fluwx/fluwx.dart';
class PayPage extends StatefulWidget {
const PayPage({Key? key}) : super(key: key);
@override
_PayPageState createState() => _PayPageState();
State<PayPage> createState() => _PayPageState();
}
class _PayPageState extends State<PayPage> {
String _url = 'https://wxpay.wxutil.com/pub_v2/app/app_pay.php';
final Fluwx fluwx = Fluwx();
final String _url = 'https://wxpay.wxutil.com/pub_v2/app/app_pay.php';
String _result = '无';
late Function(WeChatResponse) responseListener;
@override
void dispose() {
super.dispose();
fluwx.unsubscribeResponse(responseListener);
}
@override
void initState() {
super.initState();
fluwx.weChatResponseEventHandler.listen((res) {
if (res is fluwx.WeChatPaymentResponse) {
responseListener = (response) {
if (response is WeChatPaymentResponse) {
setState(() {
_result = 'pay :${res.isSuccessful}';
_result = 'pay :${response.isSuccessful}';
});
}
});
// fluwx.responseFromPayment.listen((data) {
// setState(() {
// _result = '${data.errCode}';
// });
// });
};
fluwx.subscribeResponse(responseListener);
}
@override
......@@ -46,18 +50,18 @@ class _PayPageState extends State<PayPage> {
};
var request = await h.getUrl(Uri.parse(_url));
var response = await request.close();
var data = await Utf8Decoder().bind(response).join();
var data = await const Utf8Decoder().bind(response).join();
Map<String, dynamic> result = json.decode(data);
print(result['appid']);
print(result['timestamp']);
debugPrint(result['appid']);
debugPrint(result['timestamp']);
fluwx
.payWithWeChat(
.pay(
appId: result['appid'].toString(),
partnerId: result['partnerid'].toString(),
prepayId: result['prepayid'].toString(),
packageValue: result['package'].toString(),
nonceStr: result['noncestr'].toString(),
timeStamp: result['timestamp'],
timestamp: result['timestamp'],
sign: result['sign'].toString(),
)
.then((data) {
......
import 'package:flutter/material.dart';
import 'package:fluwx/fluwx.dart' as fluwx;
import 'package:fluwx/fluwx.dart';
class SendAuthPage extends StatefulWidget {
const SendAuthPage({Key? key}) : super(key: key);
@override
_SendAuthPageState createState() => _SendAuthPageState();
State<SendAuthPage> createState() => _SendAuthPageState();
}
class _SendAuthPageState extends State<SendAuthPage> {
String? _result = '无';
Fluwx fluwx = Fluwx();
@override
void initState() {
super.initState();
fluwx.weChatResponseEventHandler.distinct((a, b) => a == b).listen((res) {
if (res is fluwx.WeChatAuthResponse) {
fluwx.subscribeResponse((response) {
if (response is WeChatAuthResponse) {
setState(() {
_result = 'state :${res.state} \n code:${res.code}';
_result = 'state :${response.state} \n code:${response.code}';
});
}
});
......@@ -38,7 +39,7 @@ class _SendAuthPageState extends State<SendAuthPage> {
OutlinedButton(
onPressed: () {
fluwx
.sendWeChatAuth(
.sendAuth(
scope: 'snsapi_userinfo',
state: 'wechat_sdk_demo_test',
)
......
......@@ -5,20 +5,21 @@ class ShareImagePage extends StatefulWidget {
const ShareImagePage({Key? key}) : super(key: key);
@override
_ShareImagePageState createState() => _ShareImagePageState();
State<ShareImagePage> createState() => _ShareImagePageState();
}
class _ShareImagePageState extends State<ShareImagePage> {
WeChatScene scene = WeChatScene.SESSION;
WeChatScene scene = WeChatScene.session;
String _response = '';
WeChatImage? source;
WeChatImage? thumbnail;
Fluwx fluwx = Fluwx();
@override
void initState() {
super.initState();
weChatResponseEventHandler.listen((res) {
fluwx.subscribeResponse((res) {
if (res is WeChatShareResponse) {
setState(() {
_response = 'state :${res.isSuccessful}';
......@@ -34,7 +35,7 @@ class _ShareImagePageState extends State<ShareImagePage> {
title: const Text('shareImage'),
actions: <Widget>[
IconButton(
icon: Icon(Icons.share, color: Colors.white),
icon: const Icon(Icons.share, color: Colors.white),
onPressed: _shareImage,
),
],
......@@ -44,7 +45,7 @@ class _ShareImagePageState extends State<ShareImagePage> {
child: Column(
children: <Widget>[
TextField(
decoration: InputDecoration(labelText: '图片地址(仅限网络)'),
decoration: const InputDecoration(labelText: '图片地址(仅限网络)'),
controller: TextEditingController(
text: 'https://timgsa.baidu.com/timg'
'?image'
......@@ -73,7 +74,7 @@ class _ShareImagePageState extends State<ShareImagePage> {
Row(
children: <Widget>[
Radio<WeChatScene>(
value: WeChatScene.SESSION,
value: WeChatScene.session,
groupValue: scene,
onChanged: (v) {
if (v != null) handleRadioValueChanged(v);
......@@ -85,7 +86,7 @@ class _ShareImagePageState extends State<ShareImagePage> {
Row(
children: <Widget>[
Radio<WeChatScene>(
value: WeChatScene.TIMELINE,
value: WeChatScene.timeline,
groupValue: scene,
onChanged: (v) {
if (v != null) handleRadioValueChanged(v);
......@@ -97,7 +98,7 @@ class _ShareImagePageState extends State<ShareImagePage> {
Row(
children: <Widget>[
Radio<WeChatScene>(
value: WeChatScene.FAVORITE,
value: WeChatScene.favorite,
groupValue: scene,
onChanged: (v) {
if (v != null) handleRadioValueChanged(v);
......@@ -116,7 +117,7 @@ class _ShareImagePageState extends State<ShareImagePage> {
}
void _shareImage() {
shareToWeChat(WeChatShareImageModel(source!, thumbnail: thumbnail));
fluwx.share(WeChatShareImageModel(source!, thumbnail: thumbnail));
}
void handleRadioValueChanged(WeChatScene scene) {
......
......@@ -2,12 +2,14 @@ import 'package:flutter/material.dart';
import 'package:fluwx/fluwx.dart';
class ShareMiniProgramPage extends StatefulWidget {
const ShareMiniProgramPage({Key? key}) : super(key: key);
@override
_ShareMiniProgramPageState createState() => _ShareMiniProgramPageState();
State<ShareMiniProgramPage> createState() => _ShareMiniProgramPageState();
}
class _ShareMiniProgramPageState extends State<ShareMiniProgramPage> {
WeChatScene scene = WeChatScene.SESSION;
WeChatScene scene = WeChatScene.session;
String _webPageUrl = 'http://www.qq.com';
String _thumbnail = 'https://timgsa.baidu.com/timg'
'?image'
......@@ -22,6 +24,8 @@ class _ShareMiniProgramPageState extends State<ShareMiniProgramPage> {
String _path = '/pages/media';
String _description = 'Fluwx';
Fluwx fluwx = Fluwx();
@override
Widget build(BuildContext context) {
return Scaffold(
......@@ -29,7 +33,7 @@ class _ShareMiniProgramPageState extends State<ShareMiniProgramPage> {
title: const Text('ShareMiniProgram'),
actions: <Widget>[
IconButton(
icon: Icon(Icons.share, color: Colors.white),
icon: const Icon(Icons.share, color: Colors.white),
onPressed: _share,
),
],
......@@ -95,6 +99,6 @@ class _ShareMiniProgramPageState extends State<ShareMiniProgramPage> {
description: _description,
thumbnail: WeChatImage.network(_thumbnail),
);
shareToWeChat(model);
fluwx.share(model);
}
}
......@@ -5,7 +5,7 @@ class ShareMusicPage extends StatefulWidget {
const ShareMusicPage({Key? key}) : super(key: key);
@override
_ShareMusicPageState createState() => _ShareMusicPageState();
State<ShareMusicPage> createState() => _ShareMusicPageState();
}
class _ShareMusicPageState extends State<ShareMusicPage> {
......@@ -15,7 +15,8 @@ class _ShareMusicPageState extends State<ShareMusicPage> {
String _title = 'Beyond';
String _description = 'A Popular Rock Band From China';
String _thumnail = 'images/logo.png';
WeChatScene scene = WeChatScene.SESSION;
WeChatScene scene = WeChatScene.session;
Fluwx _fluwx = Fluwx();
@override
Widget build(BuildContext context) {
......@@ -24,7 +25,7 @@ class _ShareMusicPageState extends State<ShareMusicPage> {
title: const Text('ShareMusicPage'),
actions: <Widget>[
IconButton(
icon: Icon(Icons.share, color: Colors.white),
icon: const Icon(Icons.share, color: Colors.white),
onPressed: _share,
),
],
......@@ -41,21 +42,22 @@ class _ShareMusicPageState extends State<ShareMusicPage> {
onChanged: (str) {
_musicUrl = str;
},
decoration: InputDecoration(labelText: 'music url'),
decoration: const InputDecoration(labelText: 'music url'),
),
TextField(
controller: TextEditingController(text: 'http://www.qq.com'),
onChanged: (str) {
_musicLowBandUrl = str;
},
decoration: InputDecoration(labelText: 'music low band url'),
decoration:
const InputDecoration(labelText: 'music low band url'),
),
TextField(
controller: TextEditingController(text: 'Beyond'),
onChanged: (str) {
_title = str;
},
decoration: InputDecoration(labelText: 'title'),
decoration: const InputDecoration(labelText: 'title'),
),
TextField(
controller: TextEditingController(
......@@ -64,14 +66,14 @@ class _ShareMusicPageState extends State<ShareMusicPage> {
onChanged: (str) {
_description = str;
},
decoration: InputDecoration(labelText: 'description'),
decoration: const InputDecoration(labelText: 'description'),
),
TextField(
controller: TextEditingController(text: 'images/logo.png'),
onChanged: (str) {
_thumnail = str;
},
decoration: InputDecoration(labelText: 'thumbnail'),
decoration: const InputDecoration(labelText: 'thumbnail'),
),
Row(
children: <Widget>[
......@@ -79,7 +81,7 @@ class _ShareMusicPageState extends State<ShareMusicPage> {
Row(
children: <Widget>[
Radio<WeChatScene>(
value: WeChatScene.SESSION,
value: WeChatScene.session,
groupValue: scene,
onChanged: (v) {
if (v != null) handleRadioValueChanged(v);
......@@ -91,7 +93,7 @@ class _ShareMusicPageState extends State<ShareMusicPage> {
Row(
children: <Widget>[
Radio<WeChatScene>(
value: WeChatScene.TIMELINE,
value: WeChatScene.timeline,
groupValue: scene,
onChanged: (v) {
if (v != null) handleRadioValueChanged(v);
......@@ -103,7 +105,7 @@ class _ShareMusicPageState extends State<ShareMusicPage> {
Row(
children: <Widget>[
Radio<WeChatScene>(
value: WeChatScene.FAVORITE,
value: WeChatScene.favorite,
groupValue: scene,
onChanged: (v) {
if (v != null) handleRadioValueChanged(v);
......@@ -130,7 +132,7 @@ class _ShareMusicPageState extends State<ShareMusicPage> {
thumbnail: WeChatImage.network(_thumnail),
);
shareToWeChat(model);
_fluwx.share(model);
}
void handleRadioValueChanged(WeChatScene scene) {
......
......@@ -2,13 +2,16 @@ import 'package:flutter/material.dart';
import 'package:fluwx/fluwx.dart';
class ShareTextPage extends StatefulWidget {
const ShareTextPage({Key? key}) : super(key: key);
@override
_ShareTextPageState createState() => _ShareTextPageState();
State<ShareTextPage> createState() => _ShareTextPageState();
}
class _ShareTextPageState extends State<ShareTextPage> {
String _text = 'share text from fluwx';
WeChatScene scene = WeChatScene.SESSION;
WeChatScene scene = WeChatScene.session;
Fluwx fluwx = Fluwx();
@override
Widget build(BuildContext context) {
......@@ -31,7 +34,7 @@ class _ShareTextPageState extends State<ShareTextPage> {
onChanged: (str) {
_text = str;
},
decoration: InputDecoration(labelText: 'TextToShare'),
decoration: const InputDecoration(labelText: 'TextToShare'),
),
Row(
children: <Widget>[
......@@ -39,7 +42,7 @@ class _ShareTextPageState extends State<ShareTextPage> {
Row(
children: <Widget>[
Radio<WeChatScene>(
value: WeChatScene.SESSION,
value: WeChatScene.session,
groupValue: scene,
onChanged: (v) {
if (v != null) handleRadioValueChanged(v);
......@@ -51,7 +54,7 @@ class _ShareTextPageState extends State<ShareTextPage> {
Row(
children: <Widget>[
Radio<WeChatScene>(
value: WeChatScene.TIMELINE,
value: WeChatScene.timeline,
groupValue: scene,
onChanged: (v) {
if (v != null) handleRadioValueChanged(v);
......@@ -63,7 +66,7 @@ class _ShareTextPageState extends State<ShareTextPage> {
Row(
children: <Widget>[
Radio<WeChatScene>(
value: WeChatScene.FAVORITE,
value: WeChatScene.favorite,
groupValue: scene,
onChanged: (v) {
if (v != null) handleRadioValueChanged(v);
......@@ -81,9 +84,7 @@ class _ShareTextPageState extends State<ShareTextPage> {
}
void _shareText() {
shareToWeChat(WeChatShareTextModel(_text, scene: scene)).then((data) {
print('-->$data');
});
fluwx.share(WeChatShareTextModel(_text, scene: scene));
}
void handleRadioValueChanged(WeChatScene scene) {
......
......@@ -5,16 +5,18 @@ class ShareVideoPage extends StatefulWidget {
const ShareVideoPage({Key? key}) : super(key: key);
@override
_ShareMusicPageState createState() => _ShareMusicPageState();
State<ShareVideoPage> createState() => _ShareVideoPageState();
}
class _ShareMusicPageState extends State<ShareVideoPage> {
class _ShareVideoPageState extends State<ShareVideoPage> {
String _videoUrl = 'http://www.qq.com';
String _videoLowBandUrl = 'http://www.qq.com';
String _title = 'Beyond';
String _description = 'A Popular Rock Band From China';
String _thumnail = 'images/logo.png';
WeChatScene scene = WeChatScene.SESSION;
WeChatScene scene = WeChatScene.session;
Fluwx fluwx = Fluwx();
@override
Widget build(BuildContext context) {
......@@ -23,7 +25,7 @@ class _ShareMusicPageState extends State<ShareVideoPage> {
title: const Text('ShareVideoPage'),
actions: <Widget>[
IconButton(
icon: Icon(Icons.share, color: Colors.white),
icon: const Icon(Icons.share, color: Colors.white),
onPressed: _share,
),
],
......@@ -40,21 +42,22 @@ class _ShareMusicPageState extends State<ShareVideoPage> {
onChanged: (str) {
_videoUrl = str;
},
decoration: InputDecoration(labelText: 'video url'),
decoration: const InputDecoration(labelText: 'video url'),
),
TextField(
controller: TextEditingController(text: 'http://www.qq.com'),
onChanged: (str) {
_videoLowBandUrl = str;
},
decoration: InputDecoration(labelText: 'video low band url'),
decoration:
const InputDecoration(labelText: 'video low band url'),
),
TextField(
controller: TextEditingController(text: 'Beyond'),
onChanged: (str) {
_title = str;
},
decoration: InputDecoration(labelText: 'title'),
decoration: const InputDecoration(labelText: 'title'),
),
TextField(
controller:
......@@ -62,14 +65,14 @@ class _ShareMusicPageState extends State<ShareVideoPage> {
onChanged: (str) {
_description = str;
},
decoration: InputDecoration(labelText: 'description'),
decoration: const InputDecoration(labelText: 'description'),
),
TextField(
controller: TextEditingController(text: 'images/logo.png'),
onChanged: (str) {
_thumnail = str;
},
decoration: InputDecoration(labelText: 'thumbnail'),
decoration: const InputDecoration(labelText: 'thumbnail'),
),
Row(
children: <Widget>[
......@@ -77,7 +80,7 @@ class _ShareMusicPageState extends State<ShareVideoPage> {
Row(
children: <Widget>[
Radio<WeChatScene>(
value: WeChatScene.SESSION,
value: WeChatScene.session,
groupValue: scene,
onChanged: (v) {
if (v != null) handleRadioValueChanged(v);
......@@ -89,7 +92,7 @@ class _ShareMusicPageState extends State<ShareVideoPage> {
Row(
children: <Widget>[
Radio<WeChatScene>(
value: WeChatScene.TIMELINE,
value: WeChatScene.timeline,
groupValue: scene,
onChanged: (v) {
if (v != null) handleRadioValueChanged(v);
......@@ -101,7 +104,7 @@ class _ShareMusicPageState extends State<ShareVideoPage> {
Row(
children: <Widget>[
Radio<WeChatScene>(
value: WeChatScene.FAVORITE,
value: WeChatScene.favorite,
groupValue: scene,
onChanged: (v) {
if (v != null) handleRadioValueChanged(v);
......@@ -124,10 +127,10 @@ class _ShareMusicPageState extends State<ShareVideoPage> {
videoLowBandUrl: _videoLowBandUrl,
thumbnail: WeChatImage.network(_thumnail),
description: _description,
scene: this.scene,
scene: scene,
title: _title,
);
shareToWeChat(model);
fluwx.share(model);
}
void handleRadioValueChanged(WeChatScene scene) {
......
......@@ -12,7 +12,9 @@ class ShareWebPagePageState extends State<ShareWebPagePage> {
String _url = 'share text from fluwx';
String _title = 'Fluwx';
String _thumnail = 'images/logo.png';
WeChatScene scene = WeChatScene.SESSION;
WeChatScene scene = WeChatScene.session;
Fluwx fluwx = Fluwx();
@override
Widget build(BuildContext context) {
......@@ -21,7 +23,7 @@ class ShareWebPagePageState extends State<ShareWebPagePage> {
title: const Text('ShareWebPage'),
actions: <Widget>[
IconButton(
icon: Icon(Icons.share, color: Colors.white),
icon: const Icon(Icons.share, color: Colors.white),
onPressed: _share,
),
],
......@@ -37,21 +39,21 @@ class ShareWebPagePageState extends State<ShareWebPagePage> {
onChanged: (str) {
_url = str;
},
decoration: InputDecoration(labelText: 'web page'),
decoration: const InputDecoration(labelText: 'web page'),
),
TextField(
controller: TextEditingController(text: 'Fluwx'),
onChanged: (str) {
_title = str;
},
decoration: InputDecoration(labelText: 'thumbnail'),
decoration: const InputDecoration(labelText: 'thumbnail'),
),
TextField(
controller: TextEditingController(text: 'images/logo.png'),
onChanged: (str) {
_thumnail = str;
},
decoration: InputDecoration(labelText: 'thumbnail'),
decoration: const InputDecoration(labelText: 'thumbnail'),
),
Row(
children: <Widget>[
......@@ -59,7 +61,7 @@ class ShareWebPagePageState extends State<ShareWebPagePage> {
Row(
children: <Widget>[
Radio<WeChatScene>(
value: WeChatScene.SESSION,
value: WeChatScene.session,
groupValue: scene,
onChanged: (v) {
if (v != null) handleRadioValueChanged(v);
......@@ -71,7 +73,7 @@ class ShareWebPagePageState extends State<ShareWebPagePage> {
Row(
children: <Widget>[
Radio<WeChatScene>(
value: WeChatScene.TIMELINE,
value: WeChatScene.timeline,
groupValue: scene,
onChanged: (v) {
if (v != null) handleRadioValueChanged(v);
......@@ -83,7 +85,7 @@ class ShareWebPagePageState extends State<ShareWebPagePage> {
Row(
children: <Widget>[
Radio<WeChatScene>(
value: WeChatScene.FAVORITE,
value: WeChatScene.favorite,
groupValue: scene,
onChanged: (v) {
if (v != null) handleRadioValueChanged(v);
......@@ -107,7 +109,7 @@ class ShareWebPagePageState extends State<ShareWebPagePage> {
thumbnail: WeChatImage.network(_thumnail),
scene: scene,
);
shareToWeChat(model);
fluwx.share(model);
}
void handleRadioValueChanged(WeChatScene scene) {
......
......@@ -6,10 +6,9 @@ class SignAutoDeductPage extends StatefulWidget {
const SignAutoDeductPage({Key? key}) : super(key: key);
@override
_SignAutoDeductPageState createState() => _SignAutoDeductPageState();
State<SignAutoDeductPage> createState() => _SignAutoDeductPageState();
}
/// see wechat [document](https://pay.weixin.qq.com/wiki/doc/api/pap.php?chapter=18_5&index=2)
class _SignAutoDeductPageState extends State<SignAutoDeductPage> {
TextEditingController appId =
TextEditingController(text: 'wx316f9c82e99ac105');
......@@ -25,10 +24,12 @@ class _SignAutoDeductPageState extends State<SignAutoDeductPage> {
TextEditingController timestamp = TextEditingController(text: '');
TextEditingController returnApp = TextEditingController(text: '3');
Fluwx fluwx = Fluwx();
@override
void initState() {
super.initState();
weChatResponseEventHandler.listen((resp) {
fluwx.subscribeResponse((resp) {
print('resp = ${resp.isSuccessful}');
});
}
......@@ -54,10 +55,9 @@ class _SignAutoDeductPageState extends State<SignAutoDeductPage> {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('SubscribeMessagePage'),
title: const Text('SubscribeMessagePage'),
),
body: Container(
child: ListView(
body: ListView(
children: <Widget>[
_buildTextField(
title: 'appId',
......@@ -109,7 +109,6 @@ class _SignAutoDeductPageState extends State<SignAutoDeductPage> {
),
],
),
),
);
}
......@@ -124,7 +123,7 @@ class _SignAutoDeductPageState extends State<SignAutoDeductPage> {
}
void _signAutoDeduct() {
autoDeDuctWeChat(
fluwx.autoDeDuct(
appId: appId.text,
mchId: mchId.text,
planId: planId.text,
......
......@@ -5,7 +5,7 @@ class SubscribeMessagePage extends StatefulWidget {
const SubscribeMessagePage({Key? key}) : super(key: key);
@override
_SubscribeMessagePageState createState() => _SubscribeMessagePageState();
State<SubscribeMessagePage> createState() => _SubscribeMessagePageState();
}
/// see wechat [document](https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1500434436_aWfqW&token=&lang=zh_CN)
......@@ -16,12 +16,13 @@ class _SubscribeMessagePageState extends State<SubscribeMessagePage> {
TextEditingController templateId = TextEditingController(
text: 'cm_vM2k3IjHcYbkGUeAfL6Fja_7Pgv4Hx_q4tA253Ss');
TextEditingController reserved = TextEditingController(text: '123');
Fluwx fluwx = Fluwx();
@override
void initState() {
super.initState();
weChatResponseEventHandler.listen((resp) {
print('resp = $resp');
fluwx.subscribeResponse((resp) {
debugPrint('resp = $resp');
});
}
......@@ -80,7 +81,7 @@ class _SubscribeMessagePageState extends State<SubscribeMessagePage> {
}
void _requestSubMsg() {
subscribeWeChatMsg(
fluwx.subscribeMsg(
appId: appId.text,
scene: int.tryParse(scene.text) ?? 1,
templateId: templateId.text,
......
name: fluwx_example
description: Demonstrates how to use the fluwx plugin.
publish_to: 'none'
# The following line prevents the package from being accidentally published to
# pub.dev using `flutter pub publish`. This is preferred for private packages.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
environment:
sdk: ">=2.12.4 <3.0.0"
sdk: '>=3.1.0-26.0.dev <4.0.0'
# Dependencies specify other packages that your package needs in order to work.
# To automatically upgrade your package dependencies to the latest versions
# consider running `flutter pub upgrade --major-versions`. Alternatively,
# dependencies can be manually updated by changing the version numbers below to
# the latest version available on pub.dev. To see which dependencies have newer
# versions available, run `flutter pub outdated`.
dependencies:
flutter:
sdk: flutter
characters: ^1.2.0
fluwx:
# When depending on this package from a real application you should use:
# fluwx: ^x.y.z
# See https://dart.dev/tools/pub/dependencies#version-constraints
# The example app is bundled with the plugin so we use a path dependency on
# the parent directory to use the current plugin's version.
path: ../
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.1+1
cupertino_icons: ^1.0.2
dev_dependencies:
integration_test:
sdk: flutter
flutter_test:
sdk: flutter
fluwx:
path: ../
# The "flutter_lints" package below contains a set of recommended lints to
# encourage good coding practices. The lint set provided by the package is
# activated in the `analysis_options.yaml` file located at the root of your
# package. See that file for information about deactivating specific lint
# rules and activating additional ones.
flutter_lints: ^2.0.0
# 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 packages.
flutter:
# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in
# the material Icons class.
uses-material-design: true
# To add assets to your application, add an assets section, like this:
assets:
- images/logo.png
# To add assets to your application, add an assets section, like this:
# assets:
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/assets-and-images/#resolution-aware.
# https://flutter.dev/assets-and-images/#resolution-aware
# For details regarding adding assets from package dependencies, see
# https://flutter.dev/assets-and-images/#from-packages
......
// This is a basic Flutter widget test.
//
// To perform an interaction with a widget in your test, use the WidgetTester
// utility that Flutter provides. For example, you can send tap and scroll
// utility in the flutter_test package. For example, you can send tap and scroll
// gestures. You can also use WidgetTester to find child widgets in the widget
// tree, read text, and verify that the values of widget properties are correct.
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:fluwx_example/main.dart';
......@@ -12,15 +13,15 @@ import 'package:fluwx_example/main.dart';
void main() {
testWidgets('Verify Platform version', (WidgetTester tester) async {
// Build our app and trigger a frame.
await tester.pumpWidget(MyApp());
await tester.pumpWidget(const MyApp());
// Verify that platform version is retrieved.
// expect(
// find.byWidgetPredicate(
// (Widget widget) => widget is Text &&
// widget.data.startsWith('Running on:'),
// ),
// findsOneWidget,
// );
expect(
find.byWidgetPredicate(
(Widget widget) => widget is Text &&
widget.data!.startsWith('Running on:'),
),
findsOneWidget,
);
});
}
......@@ -34,6 +34,5 @@ Icon?
.tags*
/Flutter/Generated.xcconfig
/Flutter/ephemeral/
/Flutter/flutter_export_environment.sh
\ No newline at end of file
.gradle
\ No newline at end of file
#
# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html.
# Run `pod lib lint fluwx.podspec' to validate before publishing.
# Run `pod lib lint fluwx.podspec` to validate before publishing.
#
Pod::Spec.new do |s|
s.name = 'fluwx'
s.version = '0.0.1'
s.summary = 'A new Flutter plugin for Wechat SDK.'
s.summary = 'The capability of implementing WeChat SDKs in Flutter. With Fluwx, developers can use WeChatSDK easily, such as sharing, payment, lanuch mini program and etc.'
s.description = <<-DESC
A new Flutter plugin for Wechat SDK.
The capability of implementing WeChat SDKs in Flutter. With Fluwx, developers can use WeChatSDK easily, such as sharing, payment, lanuch mini program and etc.
DESC
s.homepage = 'https://github.com/OpenFlutter/fluwx'
s.homepage = 'http://example.com'
s.license = { :file => '../LICENSE' }
s.author = { 'JarvanMo' => 'jarvan.mo@gmail.com' }
s.author = { 'Your Company' => 'email@example.com' }
s.source = { :path => '.' }
s.source_files = 'Classes/**/*'
s.public_header_files = 'Classes/public/*.h'
s.static_framework = true
s.public_header_files = 'Classes/**/*.h'
s.dependency 'Flutter'
# s.dependency 'WechatOpenSDK', '1.8.7.1'
# s.dependency 'OpenWeChatSDK','~> 1.9.9'
s.platform = :ios, '12.0'
s.dependency 'WechatOpenSDK-XCFramework','~> 2.0.2'
# s.xcconfig = { 'HEADER_SEARCH_PATHS' => "${PODS_ROOT}/Headers/Public/#{s.name}" }
s.frameworks = ["SystemConfiguration", "CoreTelephony","WebKit"]
s.libraries = ["z", "sqlite3.0", "c++"]
s.preserve_paths = 'Lib/*.a'
s.vendored_libraries = "**/*.a"
s.ios.deployment_target = '12.0'
# Flutter.framework does not contain a i386 slice. Only x86_64 simulators are supported.
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'VALID_ARCHS[sdk=iphonesimulator*]' => 'x86_64' }
# Flutter.framework does not contain a i386 slice.
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' }
end
/*
* Copyright (c) 2023. OpenFlutter Project
*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor
* license agreements. See the NOTICE file distributed with this work for
* additional information regarding copyright ownership. The ASF licenses this
* file to you under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
/// Fluwx is a powerful plugin for WeChatSDK.
/// easy to use.
///
/// A open sou;rce project authorized by [OpenFlutter](https://github.com/OpenFlutter).
library fluwx;
export 'src/fluwx_iml.dart';
export 'src/fluwx.dart';
export 'src/response/wechat_response.dart';
export 'src/share/share_models.dart';
export 'src/wechat_enums.dart';
......
/*
* Copyright (c) 2023. OpenFlutter Project
*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor
* license agreements. See the NOTICE file distributed with this work for
* additional information regarding copyright ownership. The ASF licenses this
* file to you under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
import 'dart:async';
import 'method_channel/fluwx_platform_interface.dart';
import 'response/wechat_response.dart';
import 'share/share_models.dart';
import 'wechat_enums.dart';
class Fluwx {
final List<Function(WeChatResponse response)> _responseListeners = [];
Fluwx() {
FluwxPlatform.instance.responseEventHandler.listen((event) {
for (var listener in _responseListeners) {
listener(event);
}
});
}
Future<bool> get isWeChatInstalled =>
FluwxPlatform.instance.isWeChatInstalled;
Future<bool> openWeChatApp() async {
return FluwxPlatform.instance.openWeChatApp();
}
Future<bool> registerWxApi({
required String appId,
bool doOnIOS = true,
bool doOnAndroid = true,
String? universalLink,
}) async {
return FluwxPlatform.instance.registerWxApi(
appId: appId,
doOnAndroid: doOnAndroid,
doOnIOS: doOnIOS,
universalLink: universalLink);
}
Future<bool?> startLog({WXLogLevel logLevel = WXLogLevel.unspecific}) {
return FluwxPlatform.instance.startLog(logLevel: logLevel);
}
Future<bool?> stopLog() {
return FluwxPlatform.instance.stopLog();
}
Future<bool> share(WeChatShareModel what) async {
return FluwxPlatform.instance.share(what);
}
Future<bool> sendAuth(
{required String scope,
String state = 'state',
bool nonAutomatic = false}) async {
return FluwxPlatform.instance
.sendAuth(scope: scope, nonAutomatic: nonAutomatic);
}
Future<bool> subscribeMsg({
required String appId,
required int scene,
required String templateId,
String? reserved,
}) async {
return FluwxPlatform.instance.subscribeMsg(
appId: appId, scene: scene, templateId: templateId, reserved: reserved);
}
Future<bool> autoDeDuct({
required String appId,
required String mchId,
required String planId,
required String contractCode,
required String requestSerial,
required String contractDisplayAccount,
required String notifyUrl,
required String version,
required String sign,
required String timestamp,
String returnApp = '3',
int businessType = 12,
}) async {
return FluwxPlatform.instance.autoDeDuct(
appId: appId,
mchId: mchId,
planId: planId,
contractCode: contractCode,
requestSerial: requestSerial,
contractDisplayAccount: contractDisplayAccount,
notifyUrl: notifyUrl,
version: version,
sign: sign,
timestamp: timestamp,
returnApp: returnApp,
businessType: businessType);
}
Future<bool> autoDeductV2(
Map<String, String> queryInfo, {
int businessType = 12,
}) async {
return FluwxPlatform.instance.autoDeductV2(queryInfo, businessType: 12);
}
Future<bool> authByQRCode({
required String appId,
required String scope,
required String nonceStr,
required String timestamp,
required String signature,
String? schemeData,
}) async {
return FluwxPlatform.instance.authByQRCode(
appId: appId,
scope: scope,
nonceStr: nonceStr,
timestamp: timestamp,
signature: signature,
schemeData: schemeData);
}
/// IOS only
Future<bool> authByPhoneLogin({
required String scope,
String state = 'state',
}) async {
return FluwxPlatform.instance.authByPhoneLogin(scope: scope, state: state);
}
Future<bool> openCustomerServiceChat(
{required String url, required String corpId}) async {
return await FluwxPlatform.instance
.openCustomerServiceChat(url: url, corpId: corpId);
}
/// see * https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter6_2_1.shtml
Future<bool> openBusinessView(
{required String businessType, required String query}) async {
return await FluwxPlatform.instance
.openBusinessView(businessType: businessType, query: query);
}
Future<bool> checkSupportOpenBusinessView() async {
return await FluwxPlatform.instance.checkSupportOpenBusinessView();
}
Future<bool> openInvoice(
{required String appId,
required String cardType,
String locationId = "",
String cardId = "",
String canMultiSelect = "1"}) async {
return FluwxPlatform.instance.openInvoice(
appId: appId,
cardType: cardType,
locationId: locationId,
cardId: cardId,
canMultiSelect: canMultiSelect);
}
Future launchMiniProgram({
required String username,
String? path,
WXMiniProgramType miniProgramType = WXMiniProgramType.release,
}) async {
return FluwxPlatform.instance.launchMiniProgram(
username: username, path: path, miniProgramType: miniProgramType);
}
Future<String?> getExtMsg() async {
return FluwxPlatform.instance.getExtMsg();
}
Future<bool> pay({
required String appId,
required String partnerId,
required String prepayId,
required String packageValue,
required String nonceStr,
required int timestamp,
required String sign,
String? signType,
String? extData,
}) async {
return FluwxPlatform.instance.pay(
appId: appId,
partnerId: partnerId,
prepayId: prepayId,
packageValue: packageValue,
nonceStr: nonceStr,
timestamp: timestamp,
sign: sign,
signType: signType,
extData: extData);
}
Future<bool> payWithHongKongWallet({required String prepayId}) async {
return FluwxPlatform.instance.payWithHongKongWallet(prepayId: prepayId);
}
subscribeResponse(Function(WeChatResponse response) listener) {
_responseListeners.add(listener);
}
unsubscribeResponse(Function(WeChatResponse response) listener) {
_responseListeners.remove(listener);
}
}
差异被折叠。
/*
* Copyright (c) 2020. OpenFlutter Project
* Copyright (c) 2023. OpenFlutter Project
*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor
* license agreements. See the NOTICE file distributed with this work for
* additional information regarding copyright ownership. The ASF licenses this
* file to you under the Apache License, Version 2.0 (the "License"); you may not
* file to you under the Apache License, Version 2.0 (the 'License'); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* distributed under the License is distributed on an 'AS IS' BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
import 'package:flutter_test/flutter_test.dart';
import 'package:fluwx/src/share/share_models.dart';
import 'package:fluwx/src/wechat_enums.dart';
void main() {
test('create WeChatTextModel', () {
var model = WeChatShareTextModel('text', scene: WeChatScene.FAVORITE);
expect(model.source, 'text');
expect(model.scene, WeChatScene.FAVORITE);
});
// In order to *not* need this ignore, consider extracting the "web" version
// of your plugin as a separate package, instead of inlining it in the same
// package as the core of your plugin.
// ignore: avoid_web_libraries_in_flutter
import 'dart:html' as html show window;
test('WeChatTextModel toMap', () {
var map = WeChatShareTextModel('text', scene: WeChatScene.FAVORITE).toMap();
expect(map['source'], 'text');
expect(map['scene'], 2);
});
import 'package:flutter_web_plugins/flutter_web_plugins.dart';
import 'method_channel/fluwx_platform_interface.dart';
/// A web implementation of the FluwxPlatform of the Fluwx plugin.
class FluwxWeb extends FluwxPlatform {
/// Constructs a FluwxWeb
FluwxWeb();
static void registerWith(Registrar registrar) {
FluwxPlatform.instance = FluwxWeb();
}
}
/*
* Copyright (c) 2023. OpenFlutter Project
*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor
* license agreements. See the NOTICE file distributed with this work for
* additional information regarding copyright ownership. The ASF licenses this
* file to you under the Apache License, Version 2.0 (the 'License'); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an 'AS IS' BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
import 'package:fluwx/fluwx.dart';
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
import 'fluwx_method_channel.dart';
abstract class FluwxPlatform extends PlatformInterface {
/// Constructs a FluwxPlatform.
FluwxPlatform() : super(token: _token);
static final Object _token = Object();
static FluwxPlatform _instance = MethodChannelFluwx();
/// The default instance of [FluwxPlatform] to use.
///
/// Defaults to [MethodChannelFluwx].
static FluwxPlatform get instance => _instance;
/// Platform-specific implementations should set this with their own
/// platform-specific class that extends [FluwxPlatform] when
/// they register themselves.
static set instance(FluwxPlatform instance) {
PlatformInterface.verifyToken(instance, _token);
_instance = instance;
}
Stream<WeChatResponse> get responseEventHandler {
throw UnimplementedError('responseEventHandler has not been implemented.');
}
Future<bool> get isWeChatInstalled {
throw UnimplementedError('isWeChatInstalled has not been implemented.');
}
Future<bool> openWeChatApp() {
throw UnimplementedError('openWeChatApp() has not been implemented.');
}
Future<bool> registerWxApi({
required String appId,
bool doOnIOS = true,
bool doOnAndroid = true,
String? universalLink,
}) {
throw UnimplementedError('registerWxApi() has not been implemented.');
}
Future<String?> getExtMsg() {
throw UnimplementedError('getExtMsg() has not been implemented.');
}
Future<bool?> startLog({WXLogLevel logLevel = WXLogLevel.unspecific}) {
throw UnimplementedError('startLog() has not been implemented.');
}
Future<bool?> stopLog() {
throw UnimplementedError('stopLog() has not been implemented.');
}
Future<bool> share(WeChatShareModel what) {
throw UnimplementedError('share() has not been implemented.');
}
Future<bool> sendAuth(
{required String scope,
String state = 'state',
bool nonAutomatic = false}) {
throw UnimplementedError('sendAuth() has not been implemented.');
}
Future<bool> authByPhoneLogin({
required String scope,
String state = 'state',
}) async {
throw UnimplementedError('authByPhoneLogin() has not been implemented.');
}
Future<bool> authByQRCode({
required String appId,
required String scope,
required String nonceStr,
required String timestamp,
required String signature,
String? schemeData,
}) async {
throw UnimplementedError('authByQRCode() has not been implemented.');
}
Future<bool> stopWeChatAuthByQRCode() async {
throw UnimplementedError(
'stopWeChatAuthByQRCode() has not been implemented.');
}
Future<bool> launchMiniProgram({
required String username,
String? path,
WXMiniProgramType miniProgramType = WXMiniProgramType.release,
}) {
throw UnimplementedError('launchMiniProgram() has not been implemented.');
}
Future<bool> pay({
required String appId,
required String partnerId,
required String prepayId,
required String packageValue,
required String nonceStr,
required int timestamp,
required String sign,
String? signType,
String? extData,
}) {
throw UnimplementedError('pay() has not been implemented.');
}
Future<bool> payWithHongKongWallet({required String prepayId}) async {
throw UnimplementedError(
'payWithHongKongWallet() has not been implemented.');
}
Future<bool> subscribeMsg({
required String appId,
required int scene,
required String templateId,
String? reserved,
}) async {
throw UnimplementedError('subscribeWeChatMsg() has not been implemented.');
}
Future<bool> autoDeDuct({
required String appId,
required String mchId,
required String planId,
required String contractCode,
required String requestSerial,
required String contractDisplayAccount,
required String notifyUrl,
required String version,
required String sign,
required String timestamp,
String returnApp = '3',
int businessType = 12,
}) async {
throw UnimplementedError('autoDeDuct() has not been implemented.');
}
Future<bool> autoDeductV2(
Map<String, String> queryInfo, {
int businessType = 12,
}) async {
throw UnimplementedError('autoDeductV2() has not been implemented.');
}
Future<bool> openCustomerServiceChat(
{required String url, required String corpId}) {
throw UnimplementedError(
'openCustomerServiceChat() has not been implemented.');
}
Future<bool> openBusinessView(
{required String businessType, required String query}) async {
throw UnimplementedError('openBusinessView() has not been implemented.');
}
Future<bool> checkSupportOpenBusinessView() async {
throw UnimplementedError(
'checkSupportOpenBusinessView() has not been implemented.');
}
Future<bool> openInvoice(
{required String appId,
required String cardType,
String locationId = "",
String cardId = "",
String canMultiSelect = "1"}) async {
throw UnimplementedError('openInvoice() has not been implemented.');
}
}
......@@ -22,7 +22,7 @@ import 'dart:typed_data';
const String _errCode = 'errCode';
const String _errStr = 'errStr';
typedef BaseWeChatResponse _WeChatResponseInvoker(Map argument);
typedef _WeChatResponseInvoker = WeChatResponse Function(Map argument);
Map<String, _WeChatResponseInvoker> _nameAndResponseMapper = {
'onShareResponse': (Map argument) => WeChatShareResponse.fromMap(argument),
......@@ -50,11 +50,11 @@ Map<String, _WeChatResponseInvoker> _nameAndResponseMapper = {
WeChatOpenInvoiceResponse.fromMap(argument),
};
class BaseWeChatResponse {
BaseWeChatResponse._(this.errCode, this.errStr);
sealed class WeChatResponse {
WeChatResponse._(this.errCode, this.errStr);
/// Create response from the response pool.
factory BaseWeChatResponse.create(String name, Map argument) {
factory WeChatResponse.create(String name, Map argument) {
var result = _nameAndResponseMapper[name];
if (result == null) {
throw ArgumentError("Can't found instance of $name");
......@@ -68,14 +68,15 @@ class BaseWeChatResponse {
bool get isSuccessful => errCode == 0;
}
class WeChatOpenInvoiceResponse extends BaseWeChatResponse {
class WeChatOpenInvoiceResponse extends WeChatResponse {
String? cardItemList;
WeChatOpenInvoiceResponse.fromMap(Map map)
: cardItemList = map["cardItemList"],
super._(map[_errCode], map[_errStr]);
}
class WeChatShareResponse extends BaseWeChatResponse {
class WeChatShareResponse extends WeChatResponse {
WeChatShareResponse.fromMap(Map map)
: type = map['type'],
super._(map[_errCode], map[_errStr]);
......@@ -83,7 +84,7 @@ class WeChatShareResponse extends BaseWeChatResponse {
final int type;
}
class WeChatAuthResponse extends BaseWeChatResponse {
class WeChatAuthResponse extends WeChatResponse {
WeChatAuthResponse.fromMap(Map map)
: type = map['type'],
country = map['country'],
......@@ -115,7 +116,7 @@ class WeChatAuthResponse extends BaseWeChatResponse {
1432;
}
class WeChatLaunchMiniProgramResponse extends BaseWeChatResponse {
class WeChatLaunchMiniProgramResponse extends WeChatResponse {
WeChatLaunchMiniProgramResponse.fromMap(Map map)
: type = map['type'],
extMsg = map['extMsg'],
......@@ -125,7 +126,7 @@ class WeChatLaunchMiniProgramResponse extends BaseWeChatResponse {
final String? extMsg;
}
class WeChatPaymentResponse extends BaseWeChatResponse {
class WeChatPaymentResponse extends WeChatResponse {
WeChatPaymentResponse.fromMap(Map map)
: type = map['type'],
extData = map['extData'],
......@@ -135,7 +136,7 @@ class WeChatPaymentResponse extends BaseWeChatResponse {
final String? extData;
}
class WeChatOpenCustomerServiceChatResponse extends BaseWeChatResponse {
class WeChatOpenCustomerServiceChatResponse extends WeChatResponse {
WeChatOpenCustomerServiceChatResponse.fromMap(Map map)
: extMsg = map['extMsg'],
super._(map[_errCode], map[_errStr]);
......@@ -143,7 +144,7 @@ class WeChatOpenCustomerServiceChatResponse extends BaseWeChatResponse {
final String? extMsg;
}
class WeChatOpenBusinessViewResponse extends BaseWeChatResponse {
class WeChatOpenBusinessViewResponse extends WeChatResponse {
final String? extMsg;
final String? openid;
final String? businessType;
......@@ -157,7 +158,7 @@ class WeChatOpenBusinessViewResponse extends BaseWeChatResponse {
super._(map[_errCode], map[_errStr]);
}
class WeChatSubscribeMsgResponse extends BaseWeChatResponse {
class WeChatSubscribeMsgResponse extends WeChatResponse {
WeChatSubscribeMsgResponse.fromMap(Map map)
: openid = map['openid'],
templateId = map['templateId'],
......@@ -173,25 +174,23 @@ class WeChatSubscribeMsgResponse extends BaseWeChatResponse {
final int scene;
}
class WeChatOpenBusinessWebviewResponse extends BaseWeChatResponse {
class WeChatOpenBusinessWebviewResponse extends WeChatResponse {
WeChatOpenBusinessWebviewResponse.fromMap(Map map)
: type = map['type'],
errCode = map[_errCode],
businessType = map['businessType'],
resultInfo = map['resultInfo'],
super._(map[_errCode], map[_errStr]);
final int? type;
final int errCode;
final int? businessType;
final String resultInfo;
}
class WeChatAuthByQRCodeFinishedResponse extends BaseWeChatResponse {
class WeChatAuthByQRCodeFinishedResponse extends WeChatResponse {
WeChatAuthByQRCodeFinishedResponse.fromMap(Map map)
: authCode = map['authCode'],
qrCodeErrorCode = (_authByQRCodeErrorCodes[_errCode] ??
AuthByQRCodeErrorCode.UNKNOWN),
AuthByQRCodeErrorCode.unknown),
super._(map[_errCode], map[_errStr]);
final String? authCode;
......@@ -199,7 +198,7 @@ class WeChatAuthByQRCodeFinishedResponse extends BaseWeChatResponse {
}
///[qrCode] in memory.
class WeChatAuthGotQRCodeResponse extends BaseWeChatResponse {
class WeChatAuthGotQRCodeResponse extends WeChatResponse {
WeChatAuthGotQRCodeResponse.fromMap(Map map)
: qrCode = map['qrCode'],
super._(map[_errCode], map[_errStr]);
......@@ -207,13 +206,13 @@ class WeChatAuthGotQRCodeResponse extends BaseWeChatResponse {
final Uint8List? qrCode;
}
class WeChatQRCodeScannedResponse extends BaseWeChatResponse {
class WeChatQRCodeScannedResponse extends WeChatResponse {
WeChatQRCodeScannedResponse.fromMap(Map map)
: super._(map[_errCode], map[_errStr]);
}
// 获取微信打开App时携带的参数
class WeChatShowMessageFromWXRequest extends BaseWeChatResponse {
class WeChatShowMessageFromWXRequest extends WeChatResponse {
WeChatShowMessageFromWXRequest.fromMap(Map map)
: extMsg = map['extMsg'],
super._(0, '');
......@@ -222,21 +221,21 @@ class WeChatShowMessageFromWXRequest extends BaseWeChatResponse {
}
enum AuthByQRCodeErrorCode {
OK, // WechatAuth_Err_OK(0)
NORMAL_ERR, // WechatAuth_Err_NormalErr(-1)
NETWORK_ERR, // WechatAuth_Err_NetworkErr(-2)
JSON_DECODE_ERR, // WechatAuth_Err_JsonDecodeErr(-3), WechatAuth_Err_GetQrcodeFailed on iOS
CANCEL, // WechatAuth_Err_Cancel(-4)
TIMEOUT, // WechatAuth_Err_Timeout(-5)
AUTH_STOPPED, // WechatAuth_Err_Auth_Stopped(-6), Android only
UNKNOWN
ok, // WechatAuth_Err_OK(0)
normalErr, // WechatAuth_Err_NormalErr(-1)
networkErr, // WechatAuth_Err_NetworkErr(-2)
jsonDecodeErr, // WechatAuth_Err_JsonDecodeErr(-3), WechatAuth_Err_GetQrcodeFailed on iOS
cancel, // WechatAuth_Err_Cancel(-4)
timeout, // WechatAuth_Err_Timeout(-5)
authStopped, // WechatAuth_Err_Auth_Stopped(-6), Android only
unknown
}
const Map<int, AuthByQRCodeErrorCode> _authByQRCodeErrorCodes = {
0: AuthByQRCodeErrorCode.OK,
-1: AuthByQRCodeErrorCode.NORMAL_ERR,
-2: AuthByQRCodeErrorCode.NETWORK_ERR,
-3: AuthByQRCodeErrorCode.JSON_DECODE_ERR,
-4: AuthByQRCodeErrorCode.CANCEL,
-5: AuthByQRCodeErrorCode.AUTH_STOPPED
0: AuthByQRCodeErrorCode.ok,
-1: AuthByQRCodeErrorCode.normalErr,
-2: AuthByQRCodeErrorCode.networkErr,
-3: AuthByQRCodeErrorCode.jsonDecodeErr,
-4: AuthByQRCodeErrorCode.cancel,
-5: AuthByQRCodeErrorCode.authStopped
};
/*
* Copyright (c) 2020. OpenFlutter Project
* Copyright (c) 2023. OpenFlutter Project
*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor
* license agreements. See the NOTICE file distributed with this work for
......@@ -16,6 +16,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
import 'package:fluwx/fluwx.dart';
const String _scene = "scene";
......@@ -29,24 +30,24 @@ const String _messageAction = "messageAction";
const String _compressThumbnail = "compressThumbnail";
const String _msgSignature = "msgSignature";
mixin WeChatShareBaseModel {
Map toMap();
sealed class WeChatShareModel {
Map<String, dynamic> toMap();
}
/// [source] the text you want to send to WeChat
/// [scene] the target you want to send
class WeChatShareTextModel implements WeChatShareBaseModel {
class WeChatShareTextModel extends WeChatShareModel {
WeChatShareTextModel(
this.source, {
this.scene = WeChatScene.SESSION,
this.scene = WeChatScene.session,
this.mediaTagName,
this.messageAction,
this.messageExt,
this.msgSignature,
String? description,
String? title,
}) : this.title = title ?? source,
this.description = description ?? source;
}) : title = title ?? source,
description = description ?? source;
final String source;
final WeChatScene scene;
......@@ -58,7 +59,7 @@ class WeChatShareTextModel implements WeChatShareBaseModel {
final String? msgSignature;
@override
Map toMap() {
Map<String, dynamic> toMap() {
return {
_scene: scene.index,
_source: source,
......@@ -75,10 +76,10 @@ class WeChatShareTextModel implements WeChatShareBaseModel {
/// the default value is [MINI_PROGRAM_TYPE_RELEASE]
/// [hdImagePath] only works on iOS, not sure the relationship
/// between [thumbnail] and [hdImagePath].
class WeChatShareMiniProgramModel implements WeChatShareBaseModel {
class WeChatShareMiniProgramModel extends WeChatShareModel {
WeChatShareMiniProgramModel(
{required this.webPageUrl,
this.miniProgramType = WXMiniProgramType.RELEASE,
this.miniProgramType = WXMiniProgramType.release,
required this.userName,
this.path = "/",
this.title,
......@@ -111,10 +112,10 @@ class WeChatShareMiniProgramModel implements WeChatShareBaseModel {
final String? msgSignature;
@override
Map toMap() {
Map<String, dynamic> toMap() {
return {
'webPageUrl': webPageUrl,
"miniProgramType": miniProgramType.toNativeInt(),
"miniProgramType": miniProgramType.value,
"userName": userName,
"path": path,
"title": title,
......@@ -133,11 +134,11 @@ class WeChatShareMiniProgramModel implements WeChatShareBaseModel {
/// [source] the image you want to send to WeChat
/// [scene] the target you want to send
/// [thumbnail] the preview of your image, will be created from [scene] if null.
class WeChatShareImageModel implements WeChatShareBaseModel {
class WeChatShareImageModel extends WeChatShareModel {
WeChatShareImageModel(this.source,
{WeChatImage? thumbnail,
this.title,
this.scene = WeChatScene.SESSION,
this.scene = WeChatScene.session,
this.description,
this.mediaTagName,
this.messageAction,
......@@ -158,7 +159,7 @@ class WeChatShareImageModel implements WeChatShareBaseModel {
final String? msgSignature;
@override
Map toMap() {
Map<String, dynamic> toMap() {
return {
_scene: scene.index,
_source: source.toMap(),
......@@ -175,7 +176,7 @@ class WeChatShareImageModel implements WeChatShareBaseModel {
/// if [musicUrl] and [musicLowBandUrl] are both provided,
/// only [musicUrl] will be used.
class WeChatShareMusicModel implements WeChatShareBaseModel {
class WeChatShareMusicModel extends WeChatShareModel {
WeChatShareMusicModel(
{this.musicUrl,
this.musicLowBandUrl,
......@@ -187,7 +188,7 @@ class WeChatShareMusicModel implements WeChatShareBaseModel {
this.mediaTagName,
this.messageAction,
this.messageExt,
this.scene = WeChatScene.SESSION,
this.scene = WeChatScene.session,
this.compressThumbnail = true,
this.msgSignature})
: assert(musicUrl != null || musicLowBandUrl != null);
......@@ -207,7 +208,7 @@ class WeChatShareMusicModel implements WeChatShareBaseModel {
final String? msgSignature;
@override
Map toMap() {
Map<String, dynamic> toMap() {
return {
_scene: scene.index,
"musicUrl": musicUrl,
......@@ -227,9 +228,9 @@ class WeChatShareMusicModel implements WeChatShareBaseModel {
/// if [videoUrl] and [videoLowBandUrl] are both provided,
/// only [videoUrl] will be used.
class WeChatShareVideoModel implements WeChatShareBaseModel {
class WeChatShareVideoModel extends WeChatShareModel {
WeChatShareVideoModel(
{this.scene = WeChatScene.SESSION,
{this.scene = WeChatScene.session,
this.videoUrl,
this.videoLowBandUrl,
this.title = "",
......@@ -256,7 +257,7 @@ class WeChatShareVideoModel implements WeChatShareBaseModel {
final String? msgSignature;
@override
Map toMap() {
Map<String, dynamic> toMap() {
return {
_scene: scene.index,
"videoUrl": videoUrl,
......@@ -274,13 +275,13 @@ class WeChatShareVideoModel implements WeChatShareBaseModel {
/// [webPage] url you want to send to wechat
/// [thumbnail] logo of your website
class WeChatShareWebPageModel implements WeChatShareBaseModel {
class WeChatShareWebPageModel extends WeChatShareModel {
WeChatShareWebPageModel(
this.webPage, {
this.title = "",
String? description,
this.thumbnail,
this.scene = WeChatScene.SESSION,
this.scene = WeChatScene.session,
this.mediaTagName,
this.messageAction,
this.messageExt,
......@@ -301,7 +302,7 @@ class WeChatShareWebPageModel implements WeChatShareBaseModel {
final String? msgSignature;
@override
Map toMap() {
Map<String, dynamic> toMap() {
return {
_scene: scene.index,
"webPage": webPage,
......@@ -319,13 +320,13 @@ class WeChatShareWebPageModel implements WeChatShareBaseModel {
/// [source] the file you want to share, [source.suffix] is necessary on iOS.
/// [scene] can't be [WeChatScene.TIMELINE], otherwise, sharing nothing.
/// send files to WeChat
class WeChatShareFileModel implements WeChatShareBaseModel {
class WeChatShareFileModel extends WeChatShareModel {
WeChatShareFileModel(
this.source, {
this.title = "",
this.description = "",
this.thumbnail,
this.scene = WeChatScene.SESSION,
this.scene = WeChatScene.session,
this.mediaTagName,
this.messageAction,
this.messageExt,
......@@ -345,7 +346,7 @@ class WeChatShareFileModel implements WeChatShareBaseModel {
final String? msgSignature;
@override
Map toMap() {
Map<String, dynamic> toMap() {
return {
_scene: scene.index,
_source: source.toMap(),
......
/*
* Copyright (c) 2020. OpenFlutter Project
* Copyright (c) 2023. OpenFlutter Project
*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor
* license agreements. See the NOTICE file distributed with this work for
......@@ -17,44 +17,29 @@
* the License.
*/
/// [WXMiniProgramType.RELEASE]正式版
/// [WXMiniProgramType.TEST]测试版
/// [WXMiniProgramType.PREVIEW]预览版
enum WXMiniProgramType { RELEASE, TEST, PREVIEW }
/// [WeChatScene.SESSION]会话
/// [WeChatScene.TIMELINE]朋友圈
/// [WeChatScene.FAVORITE]收藏
enum WeChatScene { SESSION, TIMELINE, FAVORITE }
extension MiniProgramTypeExtensions on WXMiniProgramType {
int toNativeInt() {
switch (this) {
case WXMiniProgramType.PREVIEW:
return 2;
case WXMiniProgramType.TEST:
return 1;
case WXMiniProgramType.RELEASE:
return 0;
default:
return 0;
}
}
/// [WXMiniProgramType.release]正式版
/// [WXMiniProgramType.test]测试版
/// [WXMiniProgramType.preview]预览版
enum WXMiniProgramType {
release(0),
test(1),
preview(2);
final int value;
const WXMiniProgramType(this.value);
}
/// [WeChatScene.session]会话
/// [WeChatScene.timeline]朋友圈
/// [WeChatScene.favorite]收藏
enum WeChatScene { session, timeline, favorite }
/// 打印日常的日志
/// 打印详细的日志
enum WXLogLevel { NORMAL, DETAIL }
enum WXLogLevel {
normal(1),
unspecific(0);
final int level;
extension LogLevelExtensions on WXLogLevel {
int toNativeInt() {
switch (this) {
case WXLogLevel.DETAIL:
return 1;
case WXLogLevel.NORMAL:
return 0;
default:
return 0;
}
}
const WXLogLevel(this.level);
}
/*
* Copyright (c) 2020. OpenFlutter Project
* Copyright (c) 2023. OpenFlutter Project
*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor
* license agreements. See the NOTICE file distributed with this work for
......@@ -47,37 +47,33 @@ class WeChatImage extends WeChatFile {
class WeChatFile {
/// [source] must begin with http or https
WeChatFile.network(
String source, {
String this.source, {
String? suffix,
}) : assert(source.startsWith('http')),
source = source,
schema = FileSchema.NETWORK,
schema = FileSchema.network,
suffix = source.readSuffix(suffix, defaultSuffixTxt);
///[source] path of the image, like '/asset/image.pdf?package=flutter',
///the query param package in [source] only available when you want to specify the package of image
WeChatFile.asset(
String source, {
String this.source, {
String? suffix,
}) : assert(source.trim().isNotEmpty),
this.source = source,
this.schema = FileSchema.ASSET,
this.suffix = source.readSuffix(suffix, defaultSuffixTxt);
schema = FileSchema.asset,
suffix = source.readSuffix(suffix, defaultSuffixTxt);
WeChatFile.file(
File source, {
String suffix = defaultSuffixTxt,
}) : source = source.path,
schema = FileSchema.FILE,
schema = FileSchema.file,
suffix = source.path.readSuffix(suffix, defaultSuffixTxt);
WeChatFile.binary(
Uint8List source, {
String suffix = defaultSuffixTxt,
Uint8List this.source, {
this.suffix = defaultSuffixTxt,
}) : assert(suffix.trim().isNotEmpty),
source = source,
schema = FileSchema.BINARY,
suffix = suffix;
schema = FileSchema.binary;
final dynamic source;
final FileSchema schema;
......@@ -88,11 +84,11 @@ class WeChatFile {
/// Types of image, usually there are for types listed below.
///
/// [NETWORK] is online images.
/// [ASSET] is flutter asset image.
/// [BINARY] is binary image, shall be be [Uint8List]
/// [FILE] is local file, usually not comes from flutter asset.
enum FileSchema { NETWORK, ASSET, FILE, BINARY }
/// [network] is online images.
/// [asset] is flutter asset image.
/// [binary] is binary image, shall be be [Uint8List]
/// [file] is local file, usually not comes from flutter asset.
enum FileSchema { network, asset, file, binary }
extension _FileSuffix on String {
/// returns [suffix] if [suffix] not blank.
......
name: fluwx
description: The capability of implementing WeChat SDKs in Flutter. With Fluwx, developers can use WeChatSDK easily, such as sharing, payment, lanuch mini program and etc.
version: 3.13.1
homepage: https://github.com/JarvanMo/fluwx
version: 0.0.1
homepage:
environment:
sdk: ">=2.12.0 <3.0.0"
flutter: ">=1.12.0"
sdk: '>=3.1.0-26.0.dev <4.0.0'
flutter: ">=3.3.0"
dependencies:
flutter:
sdk: flutter
flutter_web_plugins:
sdk: flutter
plugin_platform_interface: ^2.0.2
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^2.0.0
# 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 packages.
flutter:
# This section identifies this Flutter project as a plugin project.
# The androidPackage and pluginClass identifiers should not ordinarily
# be modified. They are used by the tooling to maintain consistency when
# The 'pluginClass' specifies the class (in Java, Kotlin, Swift, Objective-C, etc.)
# which should be registered in the plugin registry. This is required for
# using method channels.
# The Android 'package' specifies package in which the registered class is.
# This is required for using method channels on Android.
# The 'ffiPlugin' specifies that native code should be built and bundled.
# This is required for using `dart:ffi`.
# All these are used by the tooling to maintain consistency when
# adding or updating assets for this project.
plugin:
platforms:
......@@ -31,6 +41,9 @@ flutter:
pluginClass: FluwxPlugin
ios:
pluginClass: FluwxPlugin
web:
pluginClass: FluwxWeb
fileName: fluwx_web.dart
# To add assets to your plugin package, add an assets section, like this:
# assets:
......@@ -41,7 +54,7 @@ flutter:
# https://flutter.dev/assets-and-images/#from-packages
#
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/assets-and-images/#resolution-aware.
# https://flutter.dev/assets-and-images/#resolution-aware
# To add custom fonts to your plugin package, add a fonts section here,
# in this "flutter" section. Each entry in this list should have a
......
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:fluwx/fluwx.dart' as fluwx;
void main() {
const MethodChannel channel = MethodChannel('com.jarvanmo/fluwx');
TestWidgetsFlutterBinding.ensureInitialized();
setUp(() {
channel.setMockMethodCallHandler((MethodCall methodCall) async {
if (methodCall.method == 'registerApp') {
if (methodCall.arguments['appId'] == 'wx13124324324') {
return Future.value(true);
} else {
return Future.value(false);
}
} else if (methodCall.method == 'shareText') {
channel.invokeMethod(
'onShareResponse',
{'type': 1, 'errCode': 1, 'errStr': 'hehe'},
);
return Future.value(true);
} else if (methodCall.method == 'shareImage') {
channel.invokeMethod(
'onShareResponse',
{'type': 1, 'errCode': 0, 'errStr': ''},
);
return Future.value(true);
}
return '42';
});
});
tearDown(() {
channel.setMockMethodCallHandler(null);
});
group('register', () {
test('success', () async {
expect(await fluwx.registerWxApi(appId: 'wx13124324324'), true);
});
test('failed', () async {
expect(await fluwx.registerWxApi(appId: 'wx131256'), false);
});
});
group('share', () {
test('text', () async {
expect(
await fluwx.shareToWeChat(fluwx.WeChatShareTextModel('text')),
true,
);
});
test('shareImage', () async {
expect(
await fluwx.shareToWeChat(
fluwx.WeChatShareImageModel(
fluwx.WeChatImage.network('http://flutter.dev'),
),
),
true,
);
});
});
group('learn', () {
test('description', () async {
print('argumentsss');
});
});
}
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:fluwx/src/method_channel/fluwx_method_channel.dart';
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
MethodChannelFluwx platform = MethodChannelFluwx();
const MethodChannel channel = MethodChannel('fluwx');
setUp(() {
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler(
channel,
(MethodCall methodCall) async {
return '42';
},
);
});
tearDown(() {
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler(channel, null);
});
test('getPlatformVersion', () async {
});
}
import 'package:flutter_test/flutter_test.dart';
import 'package:fluwx/fluwx.dart';
import 'package:fluwx/src/method_channel/fluwx_method_channel.dart';
import 'package:fluwx/src/method_channel/fluwx_platform_interface.dart';
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
class MockFluwxPlatform
with MockPlatformInterfaceMixin
implements FluwxPlatform {
@override
Future<bool> authByPhoneLogin(
{required String scope, String state = 'state'}) {
// TODO: implement authByPhoneLogin
throw UnimplementedError();
}
@override
Future<bool> authByQRCode(
{required String appId,
required String scope,
required String nonceStr,
required String timestamp,
required String signature,
String? schemeData}) {
// TODO: implement authByQRCode
throw UnimplementedError();
}
@override
Future<bool> autoDeDuct(
{required String appId,
required String mchId,
required String planId,
required String contractCode,
required String requestSerial,
required String contractDisplayAccount,
required String notifyUrl,
required String version,
required String sign,
required String timestamp,
String returnApp = '3',
int businessType = 12}) {
// TODO: implement autoDeDuct
throw UnimplementedError();
}
@override
Future<bool> autoDeductV2(Map<String, String> queryInfo,
{int businessType = 12}) {
// TODO: implement autoDeductV2
throw UnimplementedError();
}
@override
Future<bool> checkSupportOpenBusinessView() {
// TODO: implement checkSupportOpenBusinessView
throw UnimplementedError();
}
@override
Future<String?> getExtMsg() {
// TODO: implement getExtMsg
throw UnimplementedError();
}
@override
Future<bool> get isWeChatInstalled => Future.value(false);
@override
Future<bool> launchMiniProgram(
{required String username,
String? path,
WXMiniProgramType miniProgramType = WXMiniProgramType.release}) {
// TODO: implement launchMiniProgram
throw UnimplementedError();
}
@override
Future<bool> openBusinessView(
{required String businessType, required String query}) {
// TODO: implement openBusinessView
throw UnimplementedError();
}
@override
Future<bool> openCustomerServiceChat(
{required String url, required String corpId}) {
// TODO: implement openCustomerServiceChat
throw UnimplementedError();
}
@override
Future<bool> openInvoice(
{required String appId,
required String cardType,
String locationId = "",
String cardId = "",
String canMultiSelect = "1"}) {
// TODO: implement openInvoice
throw UnimplementedError();
}
@override
Future<bool> openWeChatApp() {
// TODO: implement openWeChatApp
throw UnimplementedError();
}
@override
Future<bool> pay(
{required String appId,
required String partnerId,
required String prepayId,
required String packageValue,
required String nonceStr,
required int timestamp,
required String sign,
String? signType,
String? extData}) {
// TODO: implement pay
throw UnimplementedError();
}
@override
Future<bool> payWithHongKongWallet({required String prepayId}) {
// TODO: implement payWithHongKongWallet
throw UnimplementedError();
}
@override
Future<bool> registerWxApi(
{required String appId,
bool doOnIOS = true,
bool doOnAndroid = true,
String? universalLink}) {
// TODO: implement registerWxApi
throw UnimplementedError();
}
@override
Future<bool> sendAuth(
{required String scope,
String state = 'state',
bool nonAutomatic = false}) {
// TODO: implement sendAuth
throw UnimplementedError();
}
@override
Future<bool> share(WeChatShareModel what) {
// TODO: implement share
throw UnimplementedError();
}
@override
Future<bool?> startLog({WXLogLevel logLevel = WXLogLevel.unspecific}) {
// TODO: implement startLog
throw UnimplementedError();
}
@override
Future<bool?> stopLog() {
// TODO: implement stopLog
throw UnimplementedError();
}
@override
Future<bool> stopWeChatAuthByQRCode() {
// TODO: implement stopWeChatAuthByQRCode
throw UnimplementedError();
}
@override
Future<bool> subscribeMsg(
{required String appId,
required int scene,
required String templateId,
String? reserved}) {
// TODO: implement subscribeMsg
throw UnimplementedError();
}
@override
// TODO: implement responseEventHandler
Stream<WeChatResponse> get responseEventHandler => throw UnimplementedError();
}
void main() {
final FluwxPlatform initialPlatform = FluwxPlatform.instance;
test('$MethodChannelFluwx is the default instance', () {
expect(initialPlatform, isInstanceOf<MethodChannelFluwx>());
});
test('isWeChatInstalled', () async {
Fluwx fluwxPlugin = Fluwx();
MockFluwxPlatform fakePlatform = MockFluwxPlatform();
FluwxPlatform.instance = fakePlatform;
expect(await fluwxPlugin.isWeChatInstalled, false);
});
}
/*
* Copyright (c) 2020. OpenFlutter Project
*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor
* license agreements. See the NOTICE file distributed with this work for
* additional information regarding copyright ownership. The ASF licenses this
* file to you under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
import 'package:flutter_test/flutter_test.dart';
import 'package:fluwx/fluwx.dart';
void main() {
group('create response', () {
test('WeChatShareResponse', () {
var response = BaseWeChatResponse.create(
'onShareResponse',
{'type': 1, 'errCode': 1, 'errStr': 'hehe'},
);
expect(response is WeChatShareResponse, true);
var casted = response as WeChatShareResponse;
expect(casted.type, 1);
expect(casted.errCode, 1);
expect(casted.errStr, 'hehe');
});
test('WeChatAuthResponse', () {
var response = BaseWeChatResponse.create('onAuthResponse', {
'type': 1,
'errCode': 1,
'errStr': 'hehe',
'country': 'cn',
'lang': 'lang',
'code': 'code',
'state': 'ok'
});
expect(response is WeChatAuthResponse, true);
var casted = response as WeChatAuthResponse;
expect(casted.type, 1);
expect(casted.errCode, 1);
expect(casted.errStr, 'hehe');
expect(casted.country, 'cn');
expect(casted.lang, 'lang');
expect(casted.code, 'code');
expect(casted.state, 'ok');
});
test('onLaunchMiniProgramResponse', () {
var response = BaseWeChatResponse.create(
'onLaunchMiniProgramResponse',
{'type': 1, 'errCode': 1, 'errStr': 'hehe', 'extMsg': 'extMsg'},
);
expect(response is WeChatLaunchMiniProgramResponse, true);
var casted = response as WeChatLaunchMiniProgramResponse;
expect(casted.type, 1);
expect(casted.errCode, 1);
expect(casted.errStr, 'hehe');
expect(casted.extMsg, 'extMsg');
});
test('WeChatPaymentResponse', () {
var response = BaseWeChatResponse.create(
'onPayResponse',
{'type': 1, 'errCode': 1, 'errStr': 'hehe', 'extData': 'extData'},
);
expect(response is WeChatPaymentResponse, true);
var casted = response as WeChatPaymentResponse;
expect(casted.type, 1);
expect(casted.errCode, 1);
expect(casted.errStr, 'hehe');
expect(casted.extData, 'extData');
});
test('WeChatSubscribeMsgResponse', () {
var response = BaseWeChatResponse.create('onSubscribeMsgResp', {
'type': 1,
'errCode': 1,
'errStr': 'hehe',
'openid': '425235131',
'templateId': '4252345',
'action': 'action',
'reserved': 'reserved',
'scene': 1
});
expect(response is WeChatSubscribeMsgResponse, true);
var casted = response as WeChatSubscribeMsgResponse;
expect(casted.errCode, 1);
expect(casted.errStr, 'hehe');
expect(casted.openid, '425235131');
expect(casted.templateId, '4252345');
expect(casted.action, 'action');
expect(casted.reserved, 'reserved');
expect(casted.scene, 1);
});
test('WeChatAutoDeductResponse', () {
var response = BaseWeChatResponse.create('onAutoDeductResponse', {
'type': 1,
'errCode': 0,
'errStr': 'hehe',
'businessType': 2,
'resultInfo': 'resultInfo'
});
expect(response is WeChatOpenBusinessWebviewResponse, true);
var casted = response as WeChatOpenBusinessWebviewResponse;
assert(casted.isSuccessful);
expect(casted.type, 1);
expect(casted.errCode, 0);
expect(casted.errStr, 'hehe');
expect(casted.resultInfo, 'resultInfo');
expect(casted.businessType, 2);
});
});
}
/*
* Copyright (c) 2020. OpenFlutter Project
*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor
* license agreements. See the NOTICE file distributed with this work for
* additional information regarding copyright ownership. The ASF licenses this
* file to you under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
import 'package:flutter_test/flutter_test.dart';
import 'package:fluwx/fluwx.dart';
void main() {
test('test create WeChatShareImageModel with thumbnail', () {
var image = WeChatImage.network('http://openflutter.dev/fluwx.png');
var thumbnail = WeChatImage.network('http://openflutter.dev/fluwx.png');
var model = WeChatShareImageModel(
image,
scene: WeChatScene.FAVORITE,
thumbnail: thumbnail,
);
expect(model.source, image);
expect(model.scene, WeChatScene.FAVORITE);
expect(model.thumbnail, thumbnail);
});
test('test create WeChatShareImageModel without thumbnail', () {
var image = WeChatImage.network('http://openflutter.dev/fluwx.png');
var model = WeChatShareImageModel(image, scene: WeChatScene.FAVORITE);
expect(model.source, image);
expect(model.scene, WeChatScene.FAVORITE);
expect(model.thumbnail, image);
});
test('test WeChatShareImageModel toMap', () {
var image = WeChatImage.network('http://openflutter.dev/fluwx.png');
var thumbnail = WeChatImage.network('http://openflutter.dev/fluwx.png');
var map = WeChatShareImageModel(
image,
scene: WeChatScene.FAVORITE,
thumbnail: thumbnail,
).toMap();
assert(map['thumbnail'] != null);
expect(map['thumbnail']['source'], 'http://openflutter.dev/fluwx.png');
});
}
/*
* Copyright (c) 2020. OpenFlutter Project
*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor
* license agreements. See the NOTICE file distributed with this work for
* additional information regarding copyright ownership. The ASF licenses this
* file to you under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
import 'package:flutter_test/flutter_test.dart';
import 'package:fluwx/fluwx.dart';
void main() {
group("construct", () {
test("non default values", () {
var thumbnail = WeChatImage.network("http://openflutter.dev/fluwx.png");
var model = WeChatShareMiniProgramModel(
webPageUrl: "http://openflutter.dev",
miniProgramType: WXMiniProgramType.PREVIEW,
withShareTicket: true,
thumbnail: thumbnail,
userName: "userName",
path: "path",
hdImagePath: thumbnail);
expect(model.webPageUrl, "http://openflutter.dev");
expect(model.miniProgramType, WXMiniProgramType.PREVIEW);
expect(model.thumbnail, thumbnail);
expect(model.hdImagePath, thumbnail);
expect(model.path, "path");
expect(model.userName, "userName");
});
test("default values", () {
var thumbnail = WeChatImage.network("http://openflutter.dev/fluwx.png");
var model = WeChatShareMiniProgramModel(
webPageUrl: "http://openflutter.dev",
userName: "userName",
thumbnail: thumbnail);
expect(model.webPageUrl, "http://openflutter.dev");
expect(model.miniProgramType, WXMiniProgramType.RELEASE);
expect(model.thumbnail, null);
expect(model.path, "/");
expect(model.userName, "userName");
});
});
group("toMap", () {
test("with thumbnail", () {
var thumbnail = WeChatImage.network("http://openflutter.dev/fluwx.png");
var map = WeChatShareMiniProgramModel(
webPageUrl: "http://openflutter.dev",
miniProgramType: WXMiniProgramType.PREVIEW,
withShareTicket: true,
thumbnail: thumbnail,
userName: "userName",
path: "path")
.toMap();
expect(map["webPageUrl"], "http://openflutter.dev");
expect(map["miniProgramType"], 2);
expect(map["thumbnail"]["source"], "http://openflutter.dev/fluwx.png");
expect(map["path"], "path");
expect(map["userName"], "userName");
});
test("without thumbnail", () {
var thumbnail = WeChatImage.network("http://openflutter.dev/fluwx.png");
var map = WeChatShareMiniProgramModel(
webPageUrl: "http://openflutter.dev",
miniProgramType: WXMiniProgramType.PREVIEW,
withShareTicket: true,
thumbnail: thumbnail,
userName: "userName",
path: "path")
.toMap();
expect(map["webPageUrl"], "http://openflutter.dev");
expect(map["miniProgramType"], 2);
expect(map["thumbnail"], null);
expect(map["path"], "path");
expect(map["userName"], "userName");
});
});
}
/*
* Copyright (c) 2020. OpenFlutter Project
*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor
* license agreements. See the NOTICE file distributed with this work for
* additional information regarding copyright ownership. The ASF licenses this
* file to you under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
import 'package:flutter_test/flutter_test.dart';
import 'package:fluwx/src/wechat_file.dart';
void main() {
test('test WeChatImage.fromNetwork', () {
var withSuffixImage = WeChatImage.network(
'http://image.openflutter.dev/fluwx.png',
);
expect(withSuffixImage.source, 'http://image.openflutter.dev/fluwx.png');
expect(withSuffixImage.suffix, '.png');
expect(FileSchema.NETWORK, withSuffixImage.schema);
var withNoSuffixNoUrlSuffixImage = WeChatImage.network(
'http://image.openflutter.dev/fluwx',
);
expect(
'http://image.openflutter.dev/fluwx',
withNoSuffixNoUrlSuffixImage.source,
);
expect(withNoSuffixNoUrlSuffixImage.suffix, '.jpeg');
expect(FileSchema.NETWORK, withSuffixImage.schema);
var withSpecifiedSuffixImage = WeChatImage.network(
'http://image.openflutter.dev/fluwx.jpeg',
suffix: '.png',
);
expect(
withSpecifiedSuffixImage.source,
'http://image.openflutter.dev/fluwx.jpeg',
);
expect(withSpecifiedSuffixImage.suffix, '.png');
expect(withSpecifiedSuffixImage.schema, FileSchema.NETWORK);
});
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论