Unverified 提交 d9e7add8 authored 作者: JarvanMo's avatar JarvanMo 提交者: GitHub

Merge pull request #196 from OpenFlutter/v2.0

V2.0
......@@ -6,6 +6,7 @@
* Android增加新的Action以防微信打开小程序出错不会返回原app的问题
* iOS改用Pod引用微信SDK
* iOS隐藏一些header
* kotlin 1.3.70
## 1.2.1+2
* iOS的StringUtil重命名了
......
......@@ -70,17 +70,21 @@ And you have to understand the difference between debug signature and release si
- [Basic knowledge](./docs/BASIC_KNOWLEDGE.md)
- [Share](./docs/SHARE.md)
- [Payment](./dosc/PAYMENT.md)
- [Payment](./docs/PAYMENT.md)
- [Auth](./docs/AUTH.md)
For more capabilities, you can read the public functions of `fluwx`.
### Donate
## QA
[These questions maybe help](./docs/QA.md)
## Donate
Buy the writer a cup of coffee。
<img src="https://github.com/JarvanMo/ImagesStore/blob/master/common/wx.jpeg" height="300"> <img src="https://github.com/JarvanMo/ImagesStore/blob/master/common/ali.jpeg" height="300">
### Subscribe Us On WeChat
## Subscribe Us On WeChat
![subscribe](https://github.com/JarvanMo/ImagesStore/blob/master/fluwx/wx_subscription.png)
## LICENSE
......
......@@ -9,7 +9,7 @@
`Fluwx` 是一个[微信SDK](https://developers.weixin.qq.com/doc/oplatform/Mobile_App/Resource_Center_Homepage.html)插件,它允许开发者调用
[微信原生SDK ](https://developers.weixin.qq.com/doc/oplatform/Mobile_App/Resource_Center_Homepage.html).
> Join QQ Group now: 892398530。
> 加入我们的QQ群: 892398530。
## 能力
......@@ -68,17 +68,21 @@ registerWxApi(appId: "wxd930ea5d5a228f5f",universalLink: "https://your.univerall
- [基础知识](./docs/BASIC_KNOWLEDGE_CN.md)
- [分享](./docs/SHARE_CN.md)
- [支付](./dosc/PAYMENT_CN.md)
- [支付](./docs/PAYMENT_CN.md)
- [登录](./docs/AUTH_CN.md)
对于更多功能,可以查看源码。
### 捐助
## QA
[这些问题可能对你有帮助](./docs/QA_CN.md)
## 捐助
开源不易,请作者喝杯咖啡。
<img src="https://github.com/JarvanMo/ImagesStore/blob/master/common/wx.jpeg" height="300"> <img src="https://github.com/JarvanMo/ImagesStore/blob/master/common/ali.jpeg" height="300">
### 关注公众号
## 关注公众号
![subscribe](https://github.com/JarvanMo/ImagesStore/blob/master/fluwx/wx_subscription.png)
## LICENSE
......
......@@ -2,7 +2,7 @@ group 'com.jarvan.fluwx'
version '1.0-SNAPSHOT'
buildscript {
ext.kotlin_version = '1.3.61'
ext.kotlin_version = '1.3.70'
repositories {
google()
jcenter()
......
......@@ -63,6 +63,7 @@ public class FluwxPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
shareHandler?.onDestroy()
authHandler?.removeAllListeners()
}
override fun onDetachedFromActivity() {
......
......@@ -15,7 +15,6 @@
*/
package com.jarvan.fluwx.handlers
import com.tencent.mm.opensdk.diffdev.DiffDevOAuthFactory
import com.tencent.mm.opensdk.diffdev.OAuthErrCode
import com.tencent.mm.opensdk.diffdev.OAuthListener
......@@ -39,11 +38,11 @@ internal class FluwxAuthHandler(private val methodChannel: MethodChannel) {
}
override fun onAuthGotQrcode(p0: String?, p1: ByteArray) {
methodChannel.invokeMethod("onAuthGotQRCode", p1)
methodChannel.invokeMethod("onAuthGotQRCode", mapOf("errCode" to 0, "qrCode" to p1))
}
override fun onQrcodeScanned() {
methodChannel.invokeMethod("onQRCodeScanned", null)
methodChannel.invokeMethod("onQRCodeScanned", mapOf("errCode" to 0))
}
}
......@@ -59,7 +58,6 @@ internal class FluwxAuthHandler(private val methodChannel: MethodChannel) {
req.openId = call.argument("openId")
}
result.success(WXAPiHandler.wxApi?.sendReq(req))
}
......@@ -82,5 +80,4 @@ internal class FluwxAuthHandler(private val methodChannel: MethodChannel) {
fun removeAllListeners() {
qrCodeAuth.removeAllListeners()
}
}
\ No newline at end of file
......@@ -123,7 +123,7 @@ internal interface FluwxShareHandler : CoroutineScope {
private fun shareImage(call: MethodCall, result: MethodChannel.Result) {
launch {
val map: Map<String, Any> = call.argument("source") ?: mapOf()
val sourceImage = WeChatImage.createWeChatImage(map, assetFileDescriptor((map["source"] as? String).orEmpty()), context)
val sourceImage = WeChatImage.createWeChatImage(map, assetFileDescriptor)
val thumbData = readThumbnailByteArray(call)
val sourceByteArray = sourceImage.readByteArray()
......@@ -249,13 +249,14 @@ internal interface FluwxShareHandler : CoroutineScope {
private suspend fun readThumbnailByteArray(call: MethodCall): ByteArray? {
val thumbnailMap: Map<String, Any>? = call.argument(keyThumbnail)
return thumbnailMap?.run {
val thumbnailImage = WeChatImage.createWeChatImage(thumbnailMap, assetFileDescriptor((thumbnailMap["source"] as? String).orEmpty()), context)
val thumbnailImage = WeChatImage.createWeChatImage(thumbnailMap, assetFileDescriptor)
val thumbnailImageIO = ImagesIOIml(thumbnailImage)
compressThumbnail(thumbnailImageIO)
}
}
private suspend fun compressThumbnail(ioIml: ImagesIO) = ioIml.compressedByteArray(context, SHARE_IMAGE_THUMB_LENGTH)
// SESSION, TIMELINE, FAVORITE
private fun setCommonArguments(call: MethodCall, req: SendMessageToWX.Req, msg: WXMediaMessage) {
msg.messageAction = call.argument<String?>("messageAction")
......
package com.jarvan.fluwx.io
import android.content.Context
import android.content.res.AssetFileDescriptor
import android.util.Log
import kotlinx.coroutines.Dispatchers
......@@ -125,23 +124,12 @@ interface WeChatImage {
// ASSET,
// FILE,
// BINARY,
fun createWeChatImage(params: Map<String, Any>, assetFileDescriptor: AssetFileDescriptor, context: Context): WeChatImage {
fun createWeChatImage(params: Map<String, Any>, assetFileDescriptor: (String) -> AssetFileDescriptor): WeChatImage {
// Map toMap() => {"source": source, "schema": schema.index, "suffix": suffix};
val suffix = (params["suffix"] as String?) ?: ".jpeg"
return when ((params["schema"] as? Int) ?: 0) {
0 -> WeChatNetworkImage(source = (params["source"] as? String).orEmpty(), suffix = suffix)
1 -> {
// val source = (params["source"] as? String).orEmpty()
// val uri = Uri.parse(source)
// val packageName = uri.getQueryParameter("package")
// val subPath = if (packageName.isNullOrBlank()) {
// flutterAssets.getAssetFilePathBySubpath(uri.path.orEmpty())
// } else {
// flutterAssets.getAssetFilePathBySubpath(uri.path.orEmpty(), packageName)
// }
WeChatAssetImage(source = assetFileDescriptor, suffix = suffix)
}
1 -> WeChatAssetImage(source = assetFileDescriptor(((params["source"] as? String).orEmpty())), suffix = suffix)
2 -> WeChatFileImage(source = (params["source"] as? String).orEmpty(), suffix = suffix)
3 -> WeChatMemoryImage(source = (params["source"] as? ByteArray)
?: byteArrayOf(), suffix = suffix)
......
## WeChat Not Installed on iOS?
if you have installed WeChat on your iPhone but you still catch an exception called "wechat not installed",just add the following
code to your *info.plist*:
```xml
<key>LSApplicationQueriesSchemes</key>
<array>
<string>weixin</string>
</array>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
```
## Can't Launch WeChat on Android?
Check your signature please.
## Failed to notify project evalution listener
[Failed to notify project evalution listener](https://www.jianshu.com/p/f74fed94be96)
## Can't receive response after upgrading to 1.0.0 on iOS
There's no need to override `AppDelegate` since `fluwx 1.0.0`. If you have did thad before, please remove
the following code in your `AppDelegate`:
```objective-c
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
return [WXApi handleOpenURL:url delegate:[FluwxResponseHandler defaultManager]];
}
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary<NSString*, id> *)options
{
return [WXApi handleOpenURL:url delegate:[FluwxResponseHandler defaultManager]];
}
```
If you have to override these two functions,make sure you have called the `super`:
```objective-c
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
return [super application:application openURL:url sourceApplication:sourceApplication annotation:annotation];
}
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary<NSString*, id> *)options
{
return [super application:application openURL:url options:options];
}
```
**!!!!请先看[文档](https://github.com/OpenFlutter/fluwx/blob/master/README_CN.md),再看常见Q&A,再查看issue,自我排查错误,方便你我他。依然无法解决的问题可以加群提问, QQ Group:892398530。!!!!**
## 常见Q&A
#### Fluwx调起失败?
请检查APPID、包名、以及App签名是否一致。debug 和release的签名默认不一样,请注意。
#### Android Flutter编译失败
1、检查Kotlin版本,打开```build.gradle```文件,查看以下配置
```
buildscript {
······
ext.kotlin_version = '1.3.11'
······
}
```
确保项目中使用的Kotlin版本符合要求;
2、检查Android目录下```build.gradle```文件中gradle插件版本:```classpath 'com.android.tools.build:gradle:3.2.1'``````gradle-wrapper.properties```文件中的gradle版本是否匹配:```distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip```,两者的匹配规则见Android官网:[Update Gradle](https://developer.android.com/studio/releases/gradle-plugin.html#updating-gradle)
#### WeChat Not Installed on iOS?
iOS 9系统策略更新,限制了http协议的访问,此外应用需要在“Info.plist”中将要使用的URL Schemes列为白名单,才可正常检查其他应用是否安装。
受此影响,当你的应用在iOS 9中需要使用微信SDK的相关能力(分享、收藏、支付、登录等)时,需要在“Info.plist”里增加如下代码:
```xml
<key>LSApplicationQueriesSchemes</key>
<array>
<string>weixin</string>
</array>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
```
#### 如果没有安装微信,微信登录不了,导致iOS审核失败
fluwx提供了检查用户是否安装微信的方法:```isWeChatInstalled()```,iOS使用微信相关功能前,务必先检查微信是否安装。
#### Failed to notify project evalution listener
[Failed to notify project evalution listener](https://www.jianshu.com/p/f74fed94be96)
#### isWeChatInstalled返回false
请查看该 [issue](https://github.com/OpenFlutter/fluwx/issues/34) ,检查```AppDelegate```中配置是否正确。
#### Kotlin报错:XXX is only available since Kotlin 1.3 and cannot be used in Kotlin 1.2
1、请检查IDE安装的Kotlin插件版本是否符合fluwx要求:AS打开设置-->Plugin-->Koltin查看插件版本;
2、请检查项目中使用的Kotlin版本:打开```build.gradle```文件,查看以下配置
```
buildscript {
······
ext.kotlin_version = '1.3.11'
······
}
```
#### listen监听多次调用
请查看该 [issue](https://github.com/OpenFlutter/fluwx/issues/36) 。这个问题是由于listen被多次注册导致的,使用者自己代码的问题,非fluwx导致的,请在合适的时机将listen cancel掉:
```
StreamSubscription<WeChatAuthResponse> _wxlogin;
_wxlogin = fluwx.responseFromAuth.listen((val) {})
@override
void dispose() {
_wxlogin.cancel();
}
```
#### 分享完成或者取消分享后App崩溃
如果你手动注册了```WXEntryActivity```and```WXPayEntryActivity```,请检查```Manifest```中包名是否写对了。
#### IOS编译错误:No such module 'fluwx'
如果项目本身是在Android环境配置的,移到iOS的环境的时候,会出现该问题,请按照正常步骤配置。
#### 支付成功后,按物理按键或手机自动返回商户APP,监听不到返回数据
有人反应会出现```fluwx.responseFromPayment.listen```监听无效,无法获取支付结果,建议可以直接向服务器查询是否成功。
#### iOS报错:Specs satisfying the `fluwx (from `.symlinks/plugins/fluwx/ios`)` dependency were found, but they required a higher minimum deployment target.
请在在pod file里将iOS项目deployment target改到9.0。
#### ResponseType与Dio插件中的命名冲突
使用as的方式导包即可:```import 'package:fluwx/fluwx.dart' as fluwx;```
差异被折叠。
buildscript {
ext.kotlin_version = '1.3.50'
ext.kotlin_version = '1.3.70'
repositories {
google()
jcenter()
......
......@@ -35,3 +35,5 @@ Icon?
/Flutter/Generated.xcconfig
/Flutter/flutter_export_environment.sh
.gradle
\ No newline at end of file
......@@ -4,11 +4,7 @@
#import "FluwxAuthHandler.h"
#import "WXApi.h"
#import "WechatAuthSDK.h"
#import "FluwxPlugin.h"
#import "WXApiRequestHandler.h"
#import "WechatAuthSDK.h"
@implementation FluwxAuthHandler
WechatAuthSDK *_qrauth;
......@@ -30,7 +26,9 @@ FlutterMethodChannel *_fluwxMethodChannel = nil;
[WXApiRequestHandler sendAuthRequestScope:call.arguments[@"scope"]
State:(call.arguments[@"state"] == (id) [NSNull null]) ? nil : call.arguments[@"state"]
OpenID:(openId == (id) [NSNull null]) ? nil : openId completion:^(BOOL done) {result(@(done));}];
OpenID:(openId == (id) [NSNull null]) ? nil : openId completion:^(BOOL done) {
result(@(done));
}];
}
- (void)authByQRCode:(FlutterMethodCall *)call result:(FlutterResult)result {
......@@ -51,7 +49,7 @@ FlutterMethodChannel *_fluwxMethodChannel = nil;
}
- (void)onQrcodeScanned {
[_fluwxMethodChannel invokeMethod:@"onQRCodeScanned" arguments:nil];
[_fluwxMethodChannel invokeMethod:@"onQRCodeScanned" arguments:@{@"errCode": @0}];
}
- (void)onAuthGotQrcode:(UIImage *)image {
......@@ -60,7 +58,7 @@ FlutterMethodChannel *_fluwxMethodChannel = nil;
// imageData = UIImageJPEGRepresentation(image, 1);
// }
[_fluwxMethodChannel invokeMethod:@"onAuthGotQRCode" arguments:imageData];
[_fluwxMethodChannel invokeMethod:@"onAuthGotQRCode" arguments:@{@"errCode": @0, @"qrCode": imageData}];
}
- (void)onAuthFinish:(int)errCode AuthCode:(nullable NSString *)authCode {
......
......@@ -99,8 +99,7 @@ Future<bool> shareToWeChat(WeChatShareBaseModel model) async {
/// Once AuthCode got, you need to request Access_Token
/// For more information please visit:
/// * https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419317851&token=
Future<bool> sendWeChatAuth(
{String openId, @required String scope, String state}) async {
Future<bool> sendWeChatAuth({@required String scope, String state}) async {
assert(scope != null && scope.trim().isNotEmpty);
return await _channel
.invokeMethod("sendAuth", {"scope": scope, "state": state});
......@@ -194,6 +193,39 @@ Future<bool> autoDeDuctWeChat(
});
}
/// Sometimes WeChat is not installed on users's devices.However we can
/// request a QRCode so that we can get AuthCode by scanning the QRCode
/// All required params must not be null or empty
/// [schemeData] only works on iOS
/// see * https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=215238808828h4XN&token=&lang=zh_CN
Future<bool> authWeChatByQRCode(
{@required String appId,
@required String scope,
@required String nonceStr,
@required String timeStamp,
@required String signature,
String schemeData}) async {
assert(appId != null && appId.isNotEmpty);
assert(scope != null && scope.isNotEmpty);
assert(nonceStr != null && nonceStr.isNotEmpty);
assert(timeStamp != null && timeStamp.isNotEmpty);
assert(signature != null && signature.isNotEmpty);
return await _channel.invokeMethod("authByQRCode", {
"appId": appId,
"scope": scope,
"nonceStr": nonceStr,
"timeStamp": timeStamp,
"signature": signature,
"schemeData": schemeData
});
}
/// stop [authWeChatByQRCode]
Future<bool> stopWeChatAuthByQRCode() async {
return await _channel.invokeMethod("stopAuthByQRCode");
}
Future _methodHandler(MethodCall methodCall) {
var response =
BaseWeChatResponse.create(methodCall.method, methodCall.arguments);
......
......@@ -17,6 +17,8 @@
* the License.
*/
import 'dart:typed_data';
const String _errCode = "errCode";
const String _errStr = "errStr";
......@@ -32,6 +34,12 @@ Map<String, _WeChatResponseInvoker> _nameAndResponseMapper = {
WeChatSubscribeMsgResponse.fromMap(argument),
"onAutoDeductResponse": (Map argument) =>
WeChatAutoDeductResponse.fromMap(argument),
"onAuthByQRCodeFinished": (Map argument) =>
WeChatAuthByQRCodeFinishedResponse.fromMap(argument),
"onAuthGotQRCode": (Map argument) =>
WeChatAuthGotQRCodeResponse.fromMap(argument),
"onQRCodeScanned": (Map argument) =>
WeChatQRCodeScannedResponse.fromMap(argument),
};
class BaseWeChatResponse {
......@@ -139,3 +147,57 @@ class WeChatAutoDeductResponse extends BaseWeChatResponse {
resultInfo = map["resultInfo"],
super._(map[_errCode], map[_errStr]);
}
class WeChatAuthByQRCodeFinishedResponse extends BaseWeChatResponse {
final String authCode;
final AuthByQRCodeErrorCode qrCodeErrorCode;
WeChatAuthByQRCodeFinishedResponse.fromMap(Map map)
: authCode = map["authCode"],
qrCodeErrorCode = (_authByQRCodeErrorCodes[_errCode] ??
AuthByQRCodeErrorCode.UNKNOWN),
super._(map[_errCode], map[_errStr]);
}
///[qrCode] in memory.
class WeChatAuthGotQRCodeResponse extends BaseWeChatResponse {
final Uint8List qrCode;
WeChatAuthGotQRCodeResponse.fromMap(Map map)
: qrCode = map["qrCode"],
super._(map[_errCode], map[_errStr]);
}
class WeChatQRCodeScannedResponse extends BaseWeChatResponse {
WeChatQRCodeScannedResponse.fromMap(Map map)
: super._(map[_errCode], map[_errStr]);
}
///WechatAuth_Err_OK(0),
///WechatAuth_Err_NormalErr(-1),
///WechatAuth_Err_NetworkErr(-2),
///WechatAuth_Err_JsonDecodeErr(-3),
///WechatAuth_Err_Cancel(-4),
///WechatAuth_Err_Timeout(-5),
///WechatAuth_Err_Auth_Stopped(-6);
///[AuthByQRCodeErrorCode.JSON_DECODE_ERR] means WechatAuth_Err_GetQrcodeFailed when platform is iOS
///only Android will get [AUTH_STOPPED]
enum AuthByQRCodeErrorCode {
OK,
NORMAL_ERR,
NETWORK_ERR,
JSON_DECODE_ERR,
CANCEL,
TIMEOUT,
AUTH_STOPPED,
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
};
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论