Dart/Flutter - 如何获得纪元以来的第二个:Twitter API 错误代码 135(时间戳超出范围)
Dart/Flutter - How to get second since epoch : Twitter API error code 135 ( Timestamp out of bounds)
你好,希望你一切都好。
最近,我在使用 Twitter API 时恰恰在发布推文时遇到问题。
根据文档 here,我的请求必须在其 header 中包含一个字段 oauth_timestamp,这是自纪元以来的秒数(seconds since Unix 时代)。
使用 Dart(Flutter),我检索自纪元以来经过的毫秒数,然后除以 1000 以获得该值(以秒为单位)。
例如:
final oAuthTimestamp =
Uri.encodeComponent('${DateTime.now().millisecondsSinceEpoch / 1000}');
The values must be encoded in percentage encoding, that's why I put
the whole date in the Uri.encodeComponent() method.
但奇怪的是 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;
}
有用link:Twitter API documentation to POST a Tweet and Create a oauth_signature
P.S:我的 unsing cypto 用于 hmac-sha1 加密
我解决了阻止我使用 Twitter API 发布推文的问题。
首先:
我保留了检索自纪元以来经过的时间(以秒为单位)的方式
final oAuthTimestamp = Uri.encodeComponent('${DateTime.now().millisecondsSinceEpoch / 1000}');
最后是:
我从 Twitter API 收到一条错误消息告诉我 {"errors":[{"code":32,"message":"Could not authenticate you."}]}
我只是在创建 parameterString
时删除了 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_entities=true 包含在 creating a signature (oauth_signature 的步骤中)
所以我凭直觉删除了这个字段,因为我不明白它的作用。然后一切开始正常工作。 Twitter 开发人员应该查看他们的文档并更明确地说明此 include_entities 字段的用途。
谢谢你所做的一切
你好,希望你一切都好。 最近,我在使用 Twitter API 时恰恰在发布推文时遇到问题。 根据文档 here,我的请求必须在其 header 中包含一个字段 oauth_timestamp,这是自纪元以来的秒数(seconds since Unix 时代)。
使用 Dart(Flutter),我检索自纪元以来经过的毫秒数,然后除以 1000 以获得该值(以秒为单位)。 例如:
final oAuthTimestamp =
Uri.encodeComponent('${DateTime.now().millisecondsSinceEpoch / 1000}');
The values must be encoded in percentage encoding, that's why I put the whole date in the Uri.encodeComponent() method.
但奇怪的是 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;
}
有用link:Twitter API documentation to POST a Tweet and Create a oauth_signature
P.S:我的 unsing cypto 用于 hmac-sha1 加密
我解决了阻止我使用 Twitter API 发布推文的问题。
首先: 我保留了检索自纪元以来经过的时间(以秒为单位)的方式
final oAuthTimestamp = Uri.encodeComponent('${DateTime.now().millisecondsSinceEpoch / 1000}');
最后是:
我从 Twitter API 收到一条错误消息告诉我 {"errors":[{"code":32,"message":"Could not authenticate you."}]}
我只是在创建 parameterString
时删除了 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_entities=true 包含在 creating a signature (oauth_signature 的步骤中)
所以我凭直觉删除了这个字段,因为我不明白它的作用。然后一切开始正常工作。 Twitter 开发人员应该查看他们的文档并更明确地说明此 include_entities 字段的用途。
谢谢你所做的一切