主题
添加依赖
dart
dependencies:
args: ^2.5.0
http: ^0.13.5
intl: ^0.18.0
convert: ^3.0.0
crypto: ^3.0.6
dart
import 'dart:convert';
import 'dart:math';
import 'package:convert/convert.dart';
import 'package:crypto/crypto.dart';
import 'package:http/http.dart' as http;
import 'package:intl/intl.dart';
class UpgradeRequest {
final String fileKey;
final int versionCode;
final int appointVersionCode;
final String devModelKey;
final String devKey;
UpgradeRequest({
required this.fileKey,
required this.versionCode,
this.appointVersionCode = 0,
this.devModelKey = '',
this.devKey = '',
});
Map<String, dynamic> toJson() => {
'fileKey': fileKey,
'versionCode': versionCode,
'appointVersionCode': appointVersionCode,
'devModelKey': devModelKey,
'devKey': devKey,
};
}
class UpgradeResponse {
final int code;
final String msg;
final dynamic data;
UpgradeResponse({
required this.code,
required this.msg,
required this.data,
});
@override
String toString() {
return '''
UpgradeResponse:
code: $code
msg: $msg
data: ${_formatData(data)}
''';
}
String _formatData(dynamic data) {
if (data == null) return 'null';
if (data is Map || data is List) {
return const JsonEncoder.withIndent(' ').convert(data);
}
return data.toString();
}
factory UpgradeResponse.fromJson(Map<String, dynamic> json) =>
UpgradeResponse(
code: json['code'],
msg: json['msg'],
data: json['data'],
);
}
const accessKey = 'a1';
const secretKey = 'a2';
const apiUrl = 'http://api.upgrade.toolsetlink.com/v1/file/upgrade';
void main() async {
// 1. 构造请求体
final requestBody = UpgradeRequest(
fileKey: 'key1',
versionCode: 1,
devModelKey: '12312',
devKey: '12312',
);
// 2. 序列化请求体
final bodyStr = jsonEncode(requestBody.toJson());
// 3. 生成请求参数
// 获取当前时间并转换为上海时区 RFC3339 时间格式
DateTime now = DateTime.now().toUtc().add(const Duration(hours: 8));
String timestamp = DateFormat("yyyy-MM-dd'T'HH:mm:ss").format(now) + "+08:00";
final nonce = generateNonce();
final uri = '/v1/file/upgrade';
// 4. 生成签名
final signature = generateSignature(
body: bodyStr,
nonce: nonce,
secretKey: secretKey,
timestamp: timestamp,
uri: uri,
);
// 5. 创建HTTP请求
final client = http.Client();
try {
final response = await client.post(
Uri.parse(apiUrl),
headers: {
'X-Timestamp': timestamp,
'X-Nonce': nonce,
'X-AccessKey': accessKey,
'X-Signature': signature,
'Content-Type': 'application/json',
},
body: bodyStr,
);
// 6. 处理响应
print('Status Code: ${response.statusCode}');
if (response.body.isNotEmpty) {
final result = UpgradeResponse.fromJson(
jsonDecode(response.body) as Map<String, dynamic>,
);
print('Response: ${result.toString()}');
}
} finally {
client.close();
}
}
// 生成随机Nonce (16位十六进制)
String generateNonce() {
final random = Random.secure();
final bytes = List<int>.generate(8, (_) => random.nextInt(256));
return hex.encode(bytes);
}
// 生成请求签名
String generateSignature({
required String body,
required String nonce,
required String secretKey,
required String timestamp,
required String uri,
}) {
final parts = <String>[];
if (body.isNotEmpty) {
parts.add('body=$body');
}
parts.addAll([
'nonce=$nonce',
'secretKey=$secretKey',
'timestamp=$timestamp',
'url=$uri',
]);
final signStr = parts.join('&');
final bytes = md5.convert(utf8.encode(signStr)).bytes;
return hex.encode(bytes);
}