Dart/Flutter-如何获得自epoch以来的第二名:Twitter API错误代码135(时间戳超出界限)



你好,希望你身体健康。最近,我在发布推文的时候使用Twitter API时遇到了一个问题。根据这里的文档,我的请求必须在其标头中包含一个字段oauth_timestamp,这是自epoch以来的秒数(自Unix epoch以来秒数)。

使用Dart(Flutter),我检索自epoch以来经过的毫秒数,然后将其除以1000,以获得以秒为单位的值。例如:

final oAuthTimestamp =
Uri.encodeComponent('${DateTime.now().millisecondsSinceEpoch / 1000}');

值必须以百分比编码,这就是为什么我将Uri.encodeComponent()方法中的整个日期。

但奇怪的是,Twitter API向我发送了一个错误,告诉我我的时间戳超出了界限,我不明白为什么会出现这个错误。

{"errors":[{"code":135,"message":"Timestamp out of bounds."}]}

你能帮我解决这个错误吗?告诉我我犯的错误。

谢谢。

下面是我使用Twitter API 发布推文的方法

Future<void> tweet() async {
final httpMethod = 'POST';
final baseURL = 'https://api.twitter.com/1.1/statuses/update.json';
final status =
Uri.encodeComponent('Hello this is my first Tweet using Twitter API');
final includeEntities = Uri.encodeComponent('true');
final oAuthConsumerKey = Uri.encodeComponent('my_consumer_key');  //hidded for security purpose
final consumerSecretKey = Uri.encodeComponent('my_consumer_secret_key');  //hidded for security purpose
final oAuthNonce = Uri.encodeComponent(generateRandomString());  //METHOD TO GENERATE RANDOM STRING ATTACHED BELOW
final oAuthSignatureMethod = Uri.encodeComponent('HMAC-SHA1');
final oAuthTimestamp =
Uri.encodeComponent('${DateTime.now().millisecondsSinceEpoch / 1000}');
final accessToken = await _twitterAuthService.accessToken; //GETTING MY CURRENT USER ACCESS TOKEN
final secretToken = await _twitterAuthService.secretToken; //GETTING MY CURRENT USER SECRET TOKEN
final oAuthSecretToken = Uri.encodeComponent(secretToken);
final oAuthToken = Uri.encodeComponent(accessToken);
final oAuthVersion = Uri.encodeComponent('1.0');
//THIS MY PERCENTAGE ENCODED FIELDS KEY NAME 
final includeEntitiesField = Uri.encodeComponent('include_entities');
final oAuthConsumerKeyField = Uri.encodeComponent('oauth_consumer_key');
final oAuthNonceField = Uri.encodeComponent('oauth_nonce');
final oAuthSignatureField = Uri.encodeComponent('oauth_signature');
final oAuthSignatureMethodField =
Uri.encodeComponent('oauth_signature_method');
final oAuthTimestampField = Uri.encodeComponent('oauth_timestamp');
final oAuthTokenField = Uri.encodeComponent('oauth_token');
final oAuthVersionField = Uri.encodeComponent('oauth_version');
final statusField = Uri.encodeComponent('status');
final parameterString = Uri.encodeComponent(
'$includeEntitiesField=$includeEntities&$oAuthConsumerKeyField=$oAuthConsumerKey&$oAuthNonceField=$oAuthNonce&$oAuthSignatureMethodField=$oAuthSignatureMethod&$oAuthTimestampField=$oAuthTimestamp&$oAuthTokenField=$oAuthToken&$oAuthVersionField=$oAuthVersion&$statusField=$status');
final encodedBaseUrl = Uri.encodeComponent(baseURL);
final signatureBaseString = '$httpMethod&$encodedBaseUrl&$parameterString';
final signingKey = '$consumerSecretKey&$oAuthSecretToken';
final hmacSCHA1 = Hmac(sha1, convert.utf8.encode(signingKey))
.convert(convert.utf8.encode(signatureBaseString));
final oAuthSignature =
Uri.encodeComponent(convert.base64.encode(hmacSCHA1.bytes));
final finalUrl = '$baseURL?$statusField=$status';
final headerString =
'OAuth $oAuthConsumerKeyField="$oAuthConsumerKey", $oAuthNonceField="$oAuthNonce", $oAuthSignatureField=$oAuthSignature, $oAuthSignatureMethodField=$oAuthSignatureMethod, $oAuthTimestampField=$oAuthTimestamp, $oAuthTokenField=$oAuthToken, $oAuthVersionField=$oAuthVersion';

final response = await _client.post(finalUrl,
headers: {Fields.authorization.toLowerCase(): headerString});
print('REQUEST RESPONSE. nbody = ${response.body}');
}

这是我用来生成oauth_nonce:的方法

String generateRandomString() {
final random = Random();
final chars =
'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz1234567890';
final generatedString = String.fromCharCodes(
Iterable.generate(
42,
(_) {
final generatedChars = chars.codeUnitAt(random.nextInt(chars.length));
return generatedChars;
},
),
);
return generatedString;
}

有用的链接:推特API文档发布推文并创建oauth_signature

p.S:我的hmac-sha1加密的unsing密码

我解决了阻止我使用Twitter API发布推文的问题。

首先:我保持了检索自epoch 以来经过的时间(以秒为单位)的方式

final oAuthTimestamp = Uri.encodeComponent('${DateTime.now().millisecondsSinceEpoch / 1000}');

第二:

我收到一个来自Twitter API的错误,告诉我{"errors":[{"code":32,"message":"Could not authenticate you."}]}

我只是在创建参数字符串时删除了include_entities字段

之前

final parameterString = Uri.encodeComponent(
'$includeEntitiesField=$includeEntities&$oAuthConsumerKeyField=$oAuthConsumerKey&$oAuthNonceField=$oAuthNonce&$oAuthSignatureMethodField=$oAuthSignatureMethod&$oAuthTimestampField=$oAuthTimestamp&$oAuthTokenField=$oAuthToken&$oAuthVersionField=$oAuthVersion&$statusField=$status');

之后

final parameterString = Uri.encodeComponent(
'$oAuthConsumerKeyField=$oAuthConsumerKey&$oAuthNonceField=$oAuthNonce&$oAuthSignatureMethodField=$oAuthSignatureMethod&$oAuthTimestampField=$oAuthTimestamp&$oAuthTokenField=$oAuthToken&$oAuthVersionField=$oAuthVersion&$statusField=$status');

老实说,我不知道为什么这个include_entities字段会在身份验证过程中产生错误。但是在文档中,include_entitys=true包含在创建签名的步骤中(oauth_signature)

所以凭直觉我去掉了这个字段,因为我不了解它的作用。然后一切都开始正常运转。Twitter开发人员应该查看他们的文档,并更明确地说明这个include_entities字段的有用性。

感谢所做的一切

相关内容

最新更新