应用申请详情步骤
首先将android项目一级目录下的build.grade中的ext.kotlin_version修改为1.4.10
// 将ext.kotlin_version 修改为1.4.10
buildscript {
ext.kotlin_version = '1.4.10'
}
然后在android项目二级目录app下的build.grade文件中添加如下依赖:
// 在dependencies中加入api依赖
dependencies {
api 'com.tencent.mm.ensdk:wechat-sdk-android-without-mta:+'
}
在lib目录下的services目录下创建weixin_service.dart文件
导入fluwx需要的相关文件fluwx.dart,并重命名为fluwx
import 'package:fluwx/fluwx.dart' as fluwx;
通过fluwx.dart文件中的registerWxApi方法注册微信SDK服务
await fluwx.registerWxApi(
appId: 'wxe99231e0b8e08dcf',
);
参数说明
判断是否安装微信程序,一般在IOS开发使用,android开发为非必选项
/// 如果安装微信程序,则继续下一步骤,否则直接返回错误信息
bool hasWeChat = await fluwx.isWeChatInstalled;
if (hasWeChat) {
...
}else{
处理错误;
}
微信授权是环节中最重要的一步,只有经过微信授权,才具备获取code的权限,才能正常执行后续步骤,**由于授权操作安全等级较高,所以在发起授权请求时,微信会对授权链接做正则强匹配校验,如果链接的参数顺序不对,授权页面将无法正常访问。**若用户同意授权,则页面将跳转至 redirect_uri/?code=CODE&state=STATE。
/// 微信授权操作
await fluwx.sendWeChatAuth(
scope: 'snsapi_userinfo', state: 'wechat_sdk_demo');
参数说明
在确保微信公众账号拥有授权作用域(scope参数)的权限的前提下(服务号获得高级接口后,默认拥有scope参数中的snsapi_base和snsapi_userinfo),才能获取code。并且code作为换取access_token的票据,每次用户授权带上的code将不一样,code只能使用一次,5分钟未被使用自动过期。
注:由于公众号的secret和获取到的access_token安全级别都非常高,必须只保存在服务器,不允许传给客户端。后续刷新access_token、通过access_token获取用户信息等步骤,也必须从服务器发起。
fluwx.weChatResponseEventHandler
.distinct((fluwx.BaseWeChatResponse a, fluwx.BaseWeChatResponse b) =>
a == b)
.listen((fluwx.BaseWeChatResponse event) async {
if (event is fluwx.WeChatAuthResponse) {
_code = event.code;
}else{
获取code失败,请检查参数是否填写错误,是否拥有scope参数对应的授权作用域权限
}
返回值说明
acces_token将获取的code作为兑换票据,将其作为HTTP请求的参数,向请求网址发送HTTP请求来获取access_token。
请求说明
/// Http().get()为封装好的函数
final dynamic res = await Http().get(
'',
data: {
'appid': 'wxe99231e0b8e08dcf',
'secret': '24bbdb8807d55e3c7aafb5bcd5ab62df',
'code': _code,
'grant_type': 'authorization_code'
});
请求网址
/// GET方式
参数说明
返回说明
正确返回
{
"access_token": "ACCESS_TOKEN",
"expires_in": 7200,
"refresh_token": "REFRESH_TOKEN",
"openid": "OPENID",
"scope": "SCOPE",
"unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
}
返回说明
错误返回
{
"errcode": 40029,
"errmsg": "invalid code"
}
返回说明
通过code兑换的access_token为String类型,需要将其转换成Json格式,便于操作和管理,String转换成Json的步骤如下:
将access_token包含的字段(即3.7中返回说明中正确返回和错误返回字段)放入转换网页中
检查字段是否符合格式要求
修改函数名称
检查字段类型是否正确
根据逻辑,判断字段能否为空
上述内容检查完毕,点击生成,自动生成需要的代码
在lib/models目录下创建wx_result_model.dart文件,将生成的代码粘贴进来
将获取到的access_token通过如下代码进行格式转换:
/// res即获取到的String类型的access_token
final WxAccessTokenResultModel wxAccessTokenResultModel =
WxAccessTokenResultModel.fromJson(
json.decode(res as String) as Map)
用户信息的获取将转换格式中的access_token作为兑换票据,将其作为请求参数向请求网址发送HTTP请求来获取用户信息。
请求说明
/// 通过HTTP请求获取用户信息
final dynamic userInfoResult = await Http().get(
'',
data: {
'access_token': wxAccessTokenResultModel.accessToken,
'openid': 'wxe99231e0b8e08dcf',
'lang': 'zh_CN'
});
请求网址
/// GET方式
参数说明
返回说明
正确返回
{
"openid": "OPENID",
"nickname": "NICKNAME",
"sex": 1,
"province": "PROVINCE",
"city": "CITY",
"country": "COUNTRY",
"headimgurl": "",
"privilege": ["PRIVILEGE1", "PRIVILEGE2"],
"unionid": " o6_bmasdasdsad6_2sgVt7hMZOPfL"
}
错误返回
{
"errcode": 40003,
"errmsg": "invalid openid"
}
返回说明
注:开发者最好保存 unionID 信息,以便以后在不同应用之间进行用户信息互通。
3.9中获取得到的用户信息仍然是String类型,需要将其解码成Json格式,便于以后的管理和调用,具体转换方式类似3.8,将用户信息中的字段通过网页转成Json格式,自动生成代码,在lib/models下创建wx_user_info_result.dart文件并粘贴代码,封装完成后,通过weixin_services.dart文件调用,具体调用代码如下:
/// 通过封装类WxUserInfoResult将返回的String类型用户信息转成Json格式
final WxUserInfoResult wxUserInfoResult = WxUserInfoResult.fromJson(
json.decode(userInfoResult as String) as Map);
@override
Future onInit() async {
///1.是否成功注册微信sdk,registerWxApi方法,其中appId为申请微信应用的Id
isBindWxSdk.value = await fluwx.registerWxApi(
appId: 'wxe99231e0b8e08dcf',
doOnAndroid: true,
);
///2.是否安装微信,isWeChatInstalled方法,若未安装则返回错误信息
bool hasWeChat = await fluwx.isWeChatInstalled;
if (hasWeChat) {
///3.微信授权
checkWxLogin.value = await fluwx.sendWeChatAuth(
scope: 'snsapi_userinfo', state: 'wechat_sdk_demo');
///4.获取code,weChatResponseEventHandler方法
fluwx.weChatResponseEventHandler
.distinct((fluwx.BaseWeChatResponse a, fluwx.BaseWeChatResponse b) =>
a == b)
.listen((fluwx.BaseWeChatResponse event) async {
if (event is fluwx.WeChatAuthResponse) {
_code = event.code;
///5.获取accessToken,通过HTTP请求获得
//get方法中的参数为url和data,url为请求数据的网址,data则为请求数据时必须的字段
final dynamic res = await Http().get(
'',
data: {
'appid': 'wxe99231e0b8e08dcf',
'secret': '24bbdb8807d55e3c7aafb5bcd5ab62df',
'code': _code,
'grant_type': 'authorization_code'
});
///封装类,通过该类才能把获取到的字符串数据转成Json格式的数据
final WxAccessTokenResultModel wxAccessTokenResultModel =
WxAccessTokenResultModel.fromJson(
json.decode(res as String) as Map);
//6.获取用户信息,同上述步骤
final dynamic userInfoResult = await Http().get(
'',
data: {
'access_token': wxAccessTokenResultModel.accessToken,
'openid': 'wxe99231e0b8e08dcf',
'lang': 'zh_CN'
});
final WxUserInfoResult wxUserInfoResult = WxUserInfoResult.fromJson(
json.decode(userInfoResult as String) as Map);
}
});
// 获取access token
} else {
print('该手机未安装微信程序');
}
super.onInit();
}
import 'dart:convert';
T? asT(dynamic value) {
if (value is T) {
return value;
}
return null;
}
class WxAccessTokenResultModel {
WxAccessTokenResultModel({
this.accessToken,
this.expiresIn,
this.refreshToken,
this.openid,
this.scope,
this.unionid,
this.errcode,
this.errmsg,
});
factory WxAccessTokenResultModel.fromJson(Map jsonRes) =>
WxAccessTokenResultModel(
accessToken: asT(jsonRes['access_token']),
expiresIn: asT(jsonRes['expires_in']),
refreshToken: asT(jsonRes['refresh_token']),
openid: asT(jsonRes['openid']),
scope: asT(jsonRes['scope']),
unionid: asT(jsonRes['unionid']),
errcode: asT(jsonRes['errcode']),
errmsg: asT(jsonRes['errmsg']),
);
final String? accessToken;
final int? expiresIn;
final String? refreshToken;
final String? openid;
final String? scope;
final String? unionid;
final int? errcode;
final String? errmsg;
@override
String toString() {
return jsonEncode(this);
}
Map toJson() => {
'access_token': accessToken,
'expires_in': expiresIn,
'refresh_token': refreshToken,
'openid': openid,
'scope': scope,
'unionid': unionid,
'errcode': errcode,
'errmsg': errmsg,
};
WxAccessTokenResultModel clone() => WxAccessTokenResultModel.fromJson(
asT
import 'dart:convert';
T? asT(dynamic value) {
if (value is T) {
return value;
}
return null;
}
class WxUserInfoResult {
WxUserInfoResult({
this.openid,
this.nickname,
this.sex,
this.province,
this.city,
this.country,
this.headimgurl,
this.privilege,
this.unionid,
this.errcode,
this.errmsg,
});
factory WxUserInfoResult.fromJson(Map jsonRes) {
final List? privilege =
jsonRes['privilege'] is List ? [] : null;
if (privilege != null) {
for (final dynamic item in jsonRes['privilege']!) {
if (item != null) {
privilege.add(asT(item)!);
}
}
}
return WxUserInfoResult(
openid: asT(jsonRes['openid']),
nickname: asT(jsonRes['nickname']),
sex: asT(jsonRes['sex']),
province: asT(jsonRes['province']),
city: asT(jsonRes['city']),
country: asT(jsonRes['country']),
headimgurl: asT(jsonRes['headimgurl']),
privilege: privilege,
unionid: asT(jsonRes['unionid']),
errcode: asT(jsonRes['errcode']),
errmsg: asT(jsonRes['errmsg']),
);
}
final String? openid;
final String? nickname;
final int? sex;
final String? province;
final String? city;
final String? country;
final String? headimgurl;
final List? privilege;
final String? unionid;
final int? errcode;
final String? errmsg;
@override
String toString() {
return jsonEncode(this);
}
Map toJson() => {
'openid': openid,
'nickname': nickname,
'sex': sex,
'province': province,
'city': city,
'country': country,
'headimgurl': headimgurl,
'privilege': privilege,
'unionid': unionid,
'errcode': errcode,
'errmsg': errmsg,
};
WxUserInfoResult clone() => WxUserInfoResult.fromJson(
asT