mirror of
https://github.com/RxReader/tencent_kit.git
synced 2025-06-17 16:38:03 +08:00
整理
This commit is contained in:
@ -4,6 +4,9 @@ import 'dart:io';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
|
||||
import 'package:tencent_kit/tencent_kit.dart';
|
||||
import 'package:tencent_kit_example/model/api/tencent_user_info_resp.dart';
|
||||
import 'package:tencent_kit_example/model/unionid/tencent_unionid_resp.dart';
|
||||
import 'package:tencent_kit_example/tencent.dart';
|
||||
|
||||
const String _TENCENT_APPID = 'your tencent appId';
|
||||
|
||||
|
20
example/lib/model/api/tencent_api_resp.dart
Normal file
20
example/lib/model/api/tencent_api_resp.dart
Normal file
@ -0,0 +1,20 @@
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
|
||||
abstract class TencentApiResp {
|
||||
const TencentApiResp({
|
||||
required this.ret,
|
||||
this.msg,
|
||||
});
|
||||
|
||||
/// 网络请求成功发送至服务器,并且服务器返回数据格式正确
|
||||
/// 这里包括所请求业务操作失败的情况,例如没有授权等原因导致
|
||||
static const int RET_SUCCESS = 0;
|
||||
|
||||
@JsonKey(
|
||||
defaultValue: RET_SUCCESS,
|
||||
)
|
||||
final int ret;
|
||||
final String? msg;
|
||||
|
||||
bool get isSuccessful => ret == RET_SUCCESS;
|
||||
}
|
97
example/lib/model/api/tencent_user_info_resp.dart
Normal file
97
example/lib/model/api/tencent_user_info_resp.dart
Normal file
@ -0,0 +1,97 @@
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
import 'package:tencent_kit_example/model/api/tencent_api_resp.dart';
|
||||
|
||||
part 'tencent_user_info_resp.g.dart';
|
||||
|
||||
@JsonSerializable(
|
||||
explicitToJson: true,
|
||||
fieldRename: FieldRename.snake,
|
||||
)
|
||||
class TencentUserInfoResp extends TencentApiResp {
|
||||
const TencentUserInfoResp({
|
||||
required int ret,
|
||||
String? msg,
|
||||
this.isLost,
|
||||
this.nickname,
|
||||
this.gender,
|
||||
this.genderType,
|
||||
this.province,
|
||||
this.city,
|
||||
this.year,
|
||||
this.constellation,
|
||||
this.figureurl,
|
||||
this.figureurl1,
|
||||
this.figureurl2,
|
||||
this.figureurlQq,
|
||||
this.figureurlQq1,
|
||||
this.figureurlQq2,
|
||||
this.figureurlType,
|
||||
this.isYellowVip,
|
||||
this.vip,
|
||||
this.yellowVipLevel,
|
||||
this.level,
|
||||
this.isYellowYearVip,
|
||||
}) : super(ret: ret, msg: msg);
|
||||
|
||||
factory TencentUserInfoResp.fromJson(Map<String, dynamic> json) =>
|
||||
_$TencentUserInfoRespFromJson(json);
|
||||
|
||||
final int? isLost;
|
||||
final String? nickname;
|
||||
final String? gender; // 男/女
|
||||
final int? genderType; // 男/女 - 1
|
||||
final String? province;
|
||||
final String? city;
|
||||
final String? year;
|
||||
final String? constellation;
|
||||
final String? figureurl;
|
||||
@JsonKey(
|
||||
name: 'figureurl_1',
|
||||
)
|
||||
final String? figureurl1;
|
||||
@JsonKey(
|
||||
name: 'figureurl_2',
|
||||
)
|
||||
final String? figureurl2;
|
||||
final String? figureurlQq; // 140 * 140
|
||||
@JsonKey(
|
||||
name: 'figureurl_qq_1',
|
||||
)
|
||||
final String? figureurlQq1; // 大小为40×40像素的QQ头像URL。
|
||||
@JsonKey(
|
||||
name: 'figureurl_qq_2',
|
||||
)
|
||||
final String?
|
||||
figureurlQq2; // 大小为100×100像素的QQ头像URL。需要注意,不是所有的用户都拥有QQ的100x100的头像,但40x40像素则是一定会有。
|
||||
final String? figureurlType;
|
||||
final String? isYellowVip;
|
||||
final String? vip;
|
||||
final String? yellowVipLevel;
|
||||
final String? level;
|
||||
final String? isYellowYearVip;
|
||||
|
||||
bool get isMale => gender == '男';
|
||||
|
||||
bool get isFemale => gender == '女';
|
||||
|
||||
String? get headImgUrl {
|
||||
if (figureurlQq?.isNotEmpty ?? false) {
|
||||
return figureurlQq;
|
||||
}
|
||||
if (figureurlQq2?.isNotEmpty ?? false) {
|
||||
return figureurlQq2;
|
||||
}
|
||||
if (figureurlQq1?.isNotEmpty ?? false) {
|
||||
return figureurlQq1;
|
||||
}
|
||||
if (figureurl2?.isNotEmpty ?? false) {
|
||||
return figureurl2;
|
||||
}
|
||||
if (figureurl1?.isNotEmpty ?? false) {
|
||||
return figureurl1;
|
||||
}
|
||||
return figureurl;
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() => _$TencentUserInfoRespToJson(this);
|
||||
}
|
61
example/lib/model/api/tencent_user_info_resp.g.dart
Normal file
61
example/lib/model/api/tencent_user_info_resp.g.dart
Normal file
@ -0,0 +1,61 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'tencent_user_info_resp.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
TencentUserInfoResp _$TencentUserInfoRespFromJson(Map<String, dynamic> json) {
|
||||
return TencentUserInfoResp(
|
||||
ret: json['ret'] as int? ?? 0,
|
||||
msg: json['msg'] as String?,
|
||||
isLost: json['is_lost'] as int?,
|
||||
nickname: json['nickname'] as String?,
|
||||
gender: json['gender'] as String?,
|
||||
genderType: json['gender_type'] as int?,
|
||||
province: json['province'] as String?,
|
||||
city: json['city'] as String?,
|
||||
year: json['year'] as String?,
|
||||
constellation: json['constellation'] as String?,
|
||||
figureurl: json['figureurl'] as String?,
|
||||
figureurl1: json['figureurl_1'] as String?,
|
||||
figureurl2: json['figureurl_2'] as String?,
|
||||
figureurlQq: json['figureurl_qq'] as String?,
|
||||
figureurlQq1: json['figureurl_qq_1'] as String?,
|
||||
figureurlQq2: json['figureurl_qq_2'] as String?,
|
||||
figureurlType: json['figureurl_type'] as String?,
|
||||
isYellowVip: json['is_yellow_vip'] as String?,
|
||||
vip: json['vip'] as String?,
|
||||
yellowVipLevel: json['yellow_vip_level'] as String?,
|
||||
level: json['level'] as String?,
|
||||
isYellowYearVip: json['is_yellow_year_vip'] as String?,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$TencentUserInfoRespToJson(
|
||||
TencentUserInfoResp instance) =>
|
||||
<String, dynamic>{
|
||||
'ret': instance.ret,
|
||||
'msg': instance.msg,
|
||||
'is_lost': instance.isLost,
|
||||
'nickname': instance.nickname,
|
||||
'gender': instance.gender,
|
||||
'gender_type': instance.genderType,
|
||||
'province': instance.province,
|
||||
'city': instance.city,
|
||||
'year': instance.year,
|
||||
'constellation': instance.constellation,
|
||||
'figureurl': instance.figureurl,
|
||||
'figureurl_1': instance.figureurl1,
|
||||
'figureurl_2': instance.figureurl2,
|
||||
'figureurl_qq': instance.figureurlQq,
|
||||
'figureurl_qq_1': instance.figureurlQq1,
|
||||
'figureurl_qq_2': instance.figureurlQq2,
|
||||
'figureurl_type': instance.figureurlType,
|
||||
'is_yellow_vip': instance.isYellowVip,
|
||||
'vip': instance.vip,
|
||||
'yellow_vip_level': instance.yellowVipLevel,
|
||||
'level': instance.level,
|
||||
'is_yellow_year_vip': instance.isYellowYearVip,
|
||||
};
|
35
example/lib/model/unionid/tencent_unionid_resp.dart
Normal file
35
example/lib/model/unionid/tencent_unionid_resp.dart
Normal file
@ -0,0 +1,35 @@
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
|
||||
part 'tencent_unionid_resp.g.dart';
|
||||
|
||||
@JsonSerializable(
|
||||
explicitToJson: true,
|
||||
fieldRename: FieldRename.snake,
|
||||
)
|
||||
class TencentUnionidResp {
|
||||
const TencentUnionidResp({
|
||||
required this.error,
|
||||
this.errorDescription,
|
||||
this.clientId,
|
||||
this.openid,
|
||||
this.unionid,
|
||||
});
|
||||
|
||||
factory TencentUnionidResp.fromJson(Map<String, dynamic> json) =>
|
||||
_$TencentUnionidRespFromJson(json);
|
||||
|
||||
@JsonKey(
|
||||
defaultValue: ERROR_SUCCESS,
|
||||
)
|
||||
final int error;
|
||||
final String? errorDescription;
|
||||
final String? clientId;
|
||||
final String? openid;
|
||||
final String? unionid;
|
||||
|
||||
static const int ERROR_SUCCESS = 0;
|
||||
|
||||
bool get isSuccessful => error == ERROR_SUCCESS;
|
||||
|
||||
Map<String, dynamic> toJson() => _$TencentUnionidRespToJson(this);
|
||||
}
|
26
example/lib/model/unionid/tencent_unionid_resp.g.dart
Normal file
26
example/lib/model/unionid/tencent_unionid_resp.g.dart
Normal file
@ -0,0 +1,26 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'tencent_unionid_resp.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
TencentUnionidResp _$TencentUnionidRespFromJson(Map<String, dynamic> json) {
|
||||
return TencentUnionidResp(
|
||||
error: json['error'] as int? ?? 0,
|
||||
errorDescription: json['error_description'] as String?,
|
||||
clientId: json['client_id'] as String?,
|
||||
openid: json['openid'] as String?,
|
||||
unionid: json['unionid'] as String?,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$TencentUnionidRespToJson(TencentUnionidResp instance) =>
|
||||
<String, dynamic>{
|
||||
'error': instance.error,
|
||||
'error_description': instance.errorDescription,
|
||||
'client_id': instance.clientId,
|
||||
'openid': instance.openid,
|
||||
'unionid': instance.unionid,
|
||||
};
|
69
example/lib/tencent.dart
Normal file
69
example/lib/tencent.dart
Normal file
@ -0,0 +1,69 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:tencent_kit/tencent_kit.dart';
|
||||
import 'package:tencent_kit_example/model/api/tencent_user_info_resp.dart';
|
||||
import 'package:tencent_kit_example/model/unionid/tencent_unionid_resp.dart';
|
||||
|
||||
extension MixerTencent on Tencent {
|
||||
|
||||
/// 用户信息
|
||||
/// https://wiki.connect.qq.com/get_user_info
|
||||
Future<TencentUserInfoResp> getUserInfo({
|
||||
required String appId,
|
||||
required String openid,
|
||||
required String accessToken,
|
||||
}) {
|
||||
return HttpClient()
|
||||
.getUrl(Uri.parse(
|
||||
'https://graph.qq.com/user/get_user_info?access_token=$accessToken&oauth_consumer_key=$appId&openid=$openid'))
|
||||
.then((HttpClientRequest request) {
|
||||
return request.close();
|
||||
}).then((HttpClientResponse response) async {
|
||||
if (response.statusCode == HttpStatus.ok) {
|
||||
final ContentType? contentType = response.headers.contentType;
|
||||
final Encoding encoding =
|
||||
Encoding.getByName(contentType?.charset) ?? utf8;
|
||||
final String content = await encoding.decodeStream(response);
|
||||
return TencentUserInfoResp.fromJson(
|
||||
json.decode(content) as Map<String, dynamic>);
|
||||
}
|
||||
throw HttpException(
|
||||
'HttpResponse statusCode: ${response.statusCode}, reasonPhrase: ${response.reasonPhrase}.');
|
||||
});
|
||||
}
|
||||
|
||||
/// UnionID
|
||||
/// https://wiki.connect.qq.com/unionid%E4%BB%8B%E7%BB%8D
|
||||
Future<TencentUnionidResp> getUnionId({
|
||||
required String accessToken,
|
||||
String unionid = '1',
|
||||
}) {
|
||||
return HttpClient()
|
||||
.getUrl(Uri.parse(
|
||||
'https://graph.qq.com/oauth2.0/me?access_token=$accessToken&unionid=$unionid'))
|
||||
.then((HttpClientRequest request) {
|
||||
return request.close();
|
||||
}).then((HttpClientResponse response) async {
|
||||
if (response.statusCode == HttpStatus.ok) {
|
||||
final ContentType? contentType = response.headers.contentType;
|
||||
final Encoding encoding =
|
||||
Encoding.getByName(contentType?.charset) ?? utf8;
|
||||
final String callback = await encoding.decodeStream(response);
|
||||
// 腾讯有毒 callback( $json );
|
||||
final RegExp exp = RegExp(r'callback\( (.*) \)\;');
|
||||
final Match? match = exp.firstMatch(callback);
|
||||
if (match?.groupCount == 1) {
|
||||
final String? content = match!.group(1);
|
||||
if (content != null) {
|
||||
return TencentUnionidResp.fromJson(
|
||||
json.decode(content) as Map<String, dynamic>);
|
||||
}
|
||||
}
|
||||
}
|
||||
throw HttpException(
|
||||
'HttpResponse statusCode: ${response.statusCode}, reasonPhrase: ${response.reasonPhrase}.');
|
||||
});
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user