how to pass access token in a http request with flutter? - flutter

i would like to create a campaign using marketing API, here is the Curl code, i want to transform into an http post request:
AND MY HTTP REQUEST with the model class
Future<Campaign> createCampaign(String name,String objective,String
status) async {
final http.Response response = await http.post(
'https://graph.facebook.com/v7.0/act_<AD_ACCOUNT_ID>/campaigns',
headers: {HttpHeaders.authorizationHeader: "Basic },
body: jsonEncode(<String, String>{
'name': name,
'objective': objective,
'status': status
}),
);
if (response.statusCode == 201) {
return Campaign.fromJson(json.decode(response.body));
} else {
throw Exception('Failed to create Campaign.');
}
}
class Campaign {
final String name;
final String objective;
final String status;
final Map <String,dynamic> special_ad_categories;
final Map<String,dynamic> access_token;
Campaign({this.name,this.objective,this.status,this.special_ad_categories,
this.access_token});
factory Campaign.fromJson(Map<String, dynamic> json) {
return Campaign(
name: json['name'],
objective: json['objective'],
status: json['status'],
special_ad_categories: json['special_ad_categories'],
access_token: json['access_token'],
);
}
}

Try using dio package. It has API to send form data.
import 'dart:convert';
import 'dart:io';
import 'package:dio/dio.dart' as dio;
const AD_ACCOUNT_ID = '...';
const ACCESS_TOKEN = '...';
Future<Campaign> createCampaign(String name, String objective, String status, String categories) async {
try {
final formData = dio.FormData.fromMap({
'name': name,
'objective': objective,
'status': status,
'special_ad_categories': categories,
'access_token': ACCESS_TOKEN
});
final response = await dio.Dio().post(
'https://graph.facebook.com/v7.0/act_$AD_ACCOUNT_ID/campaigns',
data: formData,
);
if (response.statusCode == HttpStatus.created) {
return Campaign.fromJson(jsonDecode(response.data));
} else {
throw Exception('Failed to create Campaign.');
}
} on dio.DioError {
throw Exception('Failed to create Campaign.');
}
}
// example of calling: createCampaign('test', 'LINK_CLICKS', 'PAUSED', 'NONE');
Don't forget to replace AD_ACCOUNT_ID and ACCESS_TOKEN.

All parameters are in body. Try like this:
Future<http.Response> fetchAlbum() {
return http.post(
'https://your-url',
body: {
'name': name,
'objective': objective,
'status': status,
'special_ad_categories': [],
'access_token': accessToken,
},
);
}

I think you missed the account id in
'https://graph.facebook.com/v7.0/act_<AD_ACCOUNT_ID>/campaigns'

Related

Api request returns 415 but it doesnt have media files

I try to add an address to a server with this API, but the problem is it's returning an Error 415 message in the images, but I don't send any media files, I just send a JSON map like shown in the images as well.
although it works in the postman it returns this error in the emulator.
this is the function of the API request
Future addAddress(Placemark placemark) async {
try {
String token = DataSaver.getData(tokenKey);
Uri uri = Uri.parse("$url$usersTag/$uid$addressTag");
var response = await http
.post(
uri,
headers: <String, String>{
'userId': uid,
"Authorization": "Bearer $token",
},
body: json.encode(AddressCredintials.fromPlacemark(placemark)),
)
.timeout(timeoutDuration, onTimeout: () {
log("request TimeOut");
return http.Response('Error', 408);
});
print(response.body.toString());
if (response.statusCode == 200) {
log("address added");
} else {
print(response.statusCode);
}
} catch (e) {
print(e);
} }
this is the class I am using.
class AddressCredintials {
String govID;
String cityID;
String? villageID;
String street;
String? building;
String? apartment;
AddressCredintials(
{this.apartment,
this.building,
required this.street,
required this.cityID,
required this.govID,
this.villageID});
factory AddressCredintials.fromPlacemark(Placemark placemark) {
return AddressCredintials(
street: placemark.street,
cityID: placemark.city.id,
govID: placemark.government.id,
apartment: placemark.apartment,
building: placemark.building,
villageID: placemark.village != null ? placemark.village!.id : null);
}
Map toJson() {
return {
"governorateId": govID,
"cityId": cityID,
"areaId": villageID,
"street": street,
"buildingNo": building,
"appartmentNo": apartment
};
}
}
Add to the header this value
"content-type": "application/json"
and in case your response is also a json add this
"accept": "application/json"

Authorization with apikey in headers using dio and generated client libraries by openapi-generator-dart

I created client libraries in a flutter project using the DioNext generator from openapi-generator-dart.
The api I am trying to communicate with uses an apikey as the authentication method and it uses it in the url, i.e when I am accessing the api through my Google Chrome browser:
https://api.hotelsexample.com/hotelfinder/v1/countries/en_US/hotels/A000293?apikey=9dhsu8d8-an9c-d40e1-a11c-5s84ddewda5
Now the method generated to get, i.e. a hotel, by DioNext looks like the following, and there are many endpoints like this, so I do not want to change the generated code:
Future<Response<Hotel>> hotelGET({
required String countryId,
required String hotelId,
BuiltList<String>? fieldsFilter,
CancelToken? cancelToken,
Map<String, dynamic>? headers,
Map<String, dynamic>? extra,
ValidateStatus? validateStatus,
ProgressCallback? onSendProgress,
ProgressCallback? onReceiveProgress,
}) async {
final _path = r'/countries/{countryId}/hotels/{hotelId}'.replaceAll('{' r'countryId' '}', countryId.toString()).replaceAll('{' r'hotelId' '}', hotelId.toString());
final _options = Options(
method: r'GET',
headers: <String, dynamic>{
...?headers,
},
extra: <String, dynamic>{
'secure': <Map<String, String>>[
{
'type': 'apiKey',
'name': 'apikey',
'keyName': 'apikey',
'where': 'query',
},
],
...?extra,
},
validateStatus: validateStatus,
);
final _queryParameters = <String, dynamic>{
if (fieldsFilter != null) r'fieldsFilter': encodeCollectionQueryParameter<String>(_serializers, fieldsFilter, const FullType(BuiltList, [FullType(String)]), format: ListFormat.multi,),
};
final _response = await _dio.request<Object>(
_path,
options: _options,
queryParameters: _queryParameters,
cancelToken: cancelToken,
onSendProgress: onSendProgress,
onReceiveProgress: onReceiveProgress,
);
Hotel _responseData;
try {
const _responseType = FullType(Hotel);
_responseData = _serializers.deserialize(
_response.data!,
specifiedType: _responseType,
) as Hotel;
} catch (error, stackTrace) {
throw DioError(
requestOptions: _response.requestOptions,
response: _response,
type: DioErrorType.other,
error: error,
)..stackTrace = stackTrace;
}
return Response<Hotel>(
data: _responseData,
headers: _response.headers,
isRedirect: _response.isRedirect,
requestOptions: _response.requestOptions,
redirects: _response.redirects,
statusCode: _response.statusCode,
statusMessage: _response.statusMessage,
extra: _response.extra,
);
}
Now, when I try to call the api using the following method:
void getmyhotel() async {
final api = Hotelsexample().getReferencesApi();
final countryId = "en_US";
final hotelId = "A000293";
try {
final response = await api.hotelGET(
countryId: countryId,
hotelId: hotelId,
headers: {"apikey": "9dhsu8d8-an9c-d40e1-a11c-5s84ddewda5"});
print(answer);
} catch (e) {
print(
"Exception: $e\n");
}
}
I get the error of an invalid apikey, so the apikey is not recognized by the api server.
Where do I have to place the apikey in my code?
Thank you very much!
You have to pass it as query instead of header.
All right, I solved the problem.
This time I downloaded the latest version of https://github.com/OpenAPITools/openapi-generator.
It is a .jar file. I used the instructions on the github page to generate the files out of the .jar file and now I have client libraries, which are upgraded to null safety and do not need the use of dio.
With the code
defaultApiClient.getAuthentication<ApiKeyAuth>("apikey")!.apiKey =
"9dhsu8d8-an9c-d40e1-a11c-5s84ddewda5";
I can now pass the apikey!

Make a post HTTP

I follow the below code, but it seems not to work:
var body = jsonEncode(<String, String>{
'uid': uid,
'limit': '10',
'offset': '2',
'action': 'feed',
});
final response = await http.post(
Uri.parse('http://abc.or/fb/selectPosts.php'),
body: body,
);
if (response.statusCode == 200) {
List<Post> posts = [];
// If the server did return a 200 OK response,
// then parse the JSON.
print((jsonDecode(response.body)));
return List<Post>.from(jsonDecode(response.body));
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to update album.');
}
My API looks like this: http:/abc.or/fb/post.php?uid=aaaa&limit=10&offset=2&action=feed
try this.
import 'package:http/http.dart';
...
static const urlPrefix = 'https://jsonplaceholder.typicode.com';
...
Future<void> makePostRequest() async {
final url = Uri.parse('$urlPrefix/posts');
final headers = {"Content-type": "application/json"};
final json = '{"title": "Hello", "body": "body text", "userId": 1}';
final response = await post(url, headers: headers, body: json);
print('Status code: ${response.statusCode}');
print('Body: ${response.body}');
}
Those are query fields not request body fields.
They are passed in the link or as queryparematers in a Uri
final response = await http.get(
Uri(
path: <your url without the queries(http://abc)>,
query: <Your queries as they are in the string (uid=aaaa&limit=10&offset=2&action=feed), you can use string interpolation to fix the values in or better still use queryparematers, not both>
queryParameters : <String, dynamic>{ 'uid': uid, 'limit': 10, 'offset': 2, 'action': feed },)
);
I use a get method which should be the standard for such url. Do confirm from whoever wrote the api if it is a uses a get or post method.

Get object data from future flutter

I have to check the email and password with the rest API that is going well. The problem is my future is returning a class object that has a token. I need that that for other screen and after login navigate to other screens.
Future<LoginResponse> createLoginState(String email, String password) async {
final http.Response response = await http.post(
'https://www.polestarkw.com/api/login',
headers: <String, String>{
'Accept': 'application/json',
//'content-type' : 'application/json'
},
body: {
"email":email ,
"password":password ,
});
if (response.statusCode == 200) {
// print(response.body);
LoginResponse loginResponse=LoginResponse.fromJson(json.decode(response.body)) ;
return loginResponse;
} else {
throw Exception('Failed to create album.');
}
}
class LoginResponse {
Object _data;
String token_type;
String expires_in;
String access_token;
String refresh_token;
LoginResponse(
{this.token_type, this.expires_in, this.access_token, this.refresh_token});
LoginResponse.fromJson(Map<String, dynamic> json) {
token_type = json['token_type'];
expires_in = json['expires_in'];
access_token = json['access_token'];
refresh_token = json['refresh_token'];
}
}
I need this loginResponse object on my other page. Here is using a future instance.
_futureJwt = createLoginState(emailController.text, pwdController.text);
how to get data from _futureJwt.
The code should go something like this
Future<LoginResponse> createLoginState(String email, String password) async {
final http.Response response = await http.post(
'https://www.polestarkw.com/api/login',
headers: <String, String>{
'Accept': 'application/json',
//'content-type' : 'application/json'
},
body: {
"email":email ,
"password":password ,
});
if (response.statusCode == 200) {
// print(response.body);
LoginResponse loginResponse=fromJson(json.decode(response.body)) ;
return loginResponse;
} else {
throw Exception('Failed to create album.');
}
}
LoginResponse fromJson(Map<String, dynamic> json) {
token_type = json['token_type'];
expires_in = json['expires_in'];
access_token = json['access_token'];
refresh_token = json['refresh_token'];
return LoginResponse(token_type,expires_in,access_token,refresh_token);
}
class LoginResponse {
Object _data;
String token_type;
String expires_in;
String access_token;
String refresh_token;
LoginResponse(
{this.token_type, this.expires_in, this.access_token, this.refresh_token});
}
The above code should work in the way u have written it too but I am not sure since I use this way
Then you can use this like
LoginResponse _futureJwt = await createLoginState(emailController.text, pwdController.text);
var token_type = _futureJwt.token_type;
var expires_in = _futureJwt.expires_in;
var access_token = _futureJwt.access_token;
var refresh_token = _futureJwt.refresh_token;
As simple as that. If you do not want to wait for the Future, you can use .then like this
createLoginState(emailController.text, pwdController.text).then((_futureJwt){
var token_type = _futureJwt.token_type;
var expires_in = _futureJwt.expires_in;
var access_token = _futureJwt.access_token;
var refresh_token = _futureJwt.refresh_token;
});
Use FutureBuilder.
Then you can use AsyncSnapshot to access hasData(), hasError() and get the data like so:
#override
Widget build(BuildContext context) {
Future<String> exampleFuture = Future.delayed(Duration(seconds: 2), "value")
return FutureBuilder(
future: exampleFuture,
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
if (snapshot.hasError) {
return Text("error");
} else if (!snapshot.hasData) {
return Text("loading");
} else {
return Text(snapshot.data);
}
});
}

how to post form data request using flutter in http package

I want to send form data in flutter using the HTTP package. Getting the error:FormatException: Unexpected character (at character 1)
I/flutter (30465):
I am sending the form data in the HTTP post request.
Future<void> authethicate(
String schoolName,
String password,
) async {
try {
final url = 'https://yobimx.com/citykey/api/users/login';
final response = await http.post(url, body: {
'email': 'usamashafiq199#outlook.com',
'password': '123',
}, headers: {
"Content-Type": "application/x-www-form-urlencoded",
});
print(
json.decode(response.body),
);
final responseData = json.decode(response.body);
} catch (error) {
print(error);
}
}
I have to use a multipart request for request. Thanks for your help.
Future<void> authethicate(
String schoolName,
String password,
) async {
try {
final url = Uri.parse('https://yobimx.com/citykey/api/users/login');
Map<String, String> requestBody = <String, String>{
'email': 'usamashafiq199#outlook.com',
'password': '123'
};
var request = http.MultipartRequest('POST', url)
..fields.addAll(requestBody);
var response = await request.send();
final respStr = await response.stream.bytesToString();
print(
jsonDecode(respStr),
);
print("This is the Status Code$respStr");
var encoded = json.decode(respStr);
print(encoded['status']);
print('This is the userId${encoded['data']['user_id']}');
} catch (error) {
print(error);
}
}