I want to send an sms that contains arabic letter but when I send the sms. It is being sent like this: ???????
Is there any solution to this problem?
Thanks.
Code:
try{
String twilioSID="AC2be050f87d26aa4b44186c50f6e610e2";
String twilioSecret="abc123";
String urlStr = "https://api.twilio.com/2010-04-01/Accounts/"+twilioSID+"/Messages.json";
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(urlStr);
String base64EncodedCredentials = "Basic "
+ Base64.encodeToString(
("AC2be050f87d26aa4b44186c50f6e610e2" + ":" + "abc123").getBytes(),
Base64.NO_WRAP);
httppost.setHeader("Authorization", base64EncodedCredentials);
String randomCode2 = UUID.randomUUID().toString().substring(0, 5);
String getmob = getIntent().getStringExtra("mob");
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("From", "+1334254136528"));
nameValuePairs.add(new BasicNameValuePair("To", getmob));
nameValuePairs.add(new BasicNameValuePair("Body", "كود السحب على الهدية \n" +
"("+randomCode2+")\n" +
"احتفظ بيه"));
try {
httppost.setEntity(new UrlEncodedFormEntity(
nameValuePairs));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
Twilio developer evangelist here.
There are a few things I need to tell you here.
First, please never share your Auth Token publicly. With your Account SID and Auth Token a malicious user could abuse your account. I recommend you immediately change your Auth Token to avoid any attacks.
Next up, you have tagged this Android, so I assume you are doing this in an Android application. You should not make calls directly to the Twilio API from an Android application. This is because to do so you need to include your Auth Token. In this case a malicious user could decompile your Android app and extract your Auth Token and use it to abuse your account. Instead, you should build a server application that can store your credentials and make requests to the Twilio API. Here's a blog post on how to send an SMS from Android with Twilio.
Finally, for when you come to build your server side integration to Twilio, you are using the wrong API endpoint. The URL you build up is:
String urlStr = "https://"+twilioSID+":"+twilioSecret+"#api.twilio.com/2010-04-01/Accounts/"+twilioSID+"/SMS/Messages";
This is using the very old and deprecated /SMS/Messages endpoint. Instead, you should be using the more recent Messages resource, with a URL like this:
https://api.twilio.com/2010-04-01/Accounts/{AccountSid}/Messages.json
The /SMS/Messages endpoint did not handle characters outside of ASCII, but the Messages resource can handle any unicode characters.
Since you will be building a server-side integration, I can recommend that you use one of the Twilio helper libraries which make it easier to make requests to the right resource.
Related
I've tried to connect to our SharePoint and POST some data to a list.
A user can interact with a Web-App and send some Information. These data will be send to a Java-Web-Interface running on a tomcat. The Java-Code should connect to our SharePoint and post the data in the list. Today, I read a lot of tutorials and ressources on the web... Most of them are deprecated ore discuss lightly different situations! SO! My mind whispered: "Go on and visit stackoverflow." And here I am, asking this question:
The Situation is described above. I call a web-Interface vie JS (angularJS) and pass an E-Mail-Adress which the user enters in the front-end. Here it goes in:
#Path("webservice")
public class SetEmail {
#POST
#Path("/SetEmail")
#Consumes(MediaType.APPLICATION_JSON + ";charset=UTF-8")
#Produces("text/plain")
public String addItem(String incoming) throws ClientProtocolException, IOException, AuthenticationException{
String result = "error";
JSONObject jsonObj = new JSONObject(incoming);
String listName = "Leads";
String username = "...";
char[] password= new char[]{'...', '...', ...};
String website = "...";
Now, after all I read, I have to get the DigestValue from SharePoint, because I want to make a POST-Request:
//Get the Digestvalue.
CredentialsProvider provider = new BasicCredentialsProvider();
provider.setCredentials(AuthScope.ANY, new NTCredentials(username, password.toString(), "http://...", "https://..."));
HttpClient client = HttpClientBuilder.create().setDefaultCredentialsProvider(provider).build();
HttpPost httpPost = new HttpPost(website + "_api/contextinfo");
httpPost.addHeader("Accept", "application/json;odata=verbose");
httpPost.addHeader("content-type", "application/json;odata=verbose");
httpPost.addHeader("X-ClientService-ClientTag", "SDK-JAVA");
HttpResponse response = client.execute(httpPost);
byte[] content = EntityUtils.toByteArray(response.getEntity());
String jsonString = new String(content, "UTF-8");
System.out.println(response);
JSONObject json = new JSONObject(jsonString);
String FormDigestValue = json.getJSONObject("d").getJSONObject("GetContextWebInformation").getString("FormDigestValue");
After getting the Digest, I am able to execute the actual request:
//POST the data.
CloseableHttpClient client2 = HttpClients.createDefault();
HttpPost httpPost2 = new HttpPost(website + "_api/web/lists/GetByTitle(" + listName + ")");
httpPost2.setEntity(new StringEntity("test post"));
NTCredentials creds = new NTCredentials(username, password.toString(), "http://...", "https://...");
httpPost2.addHeader(new BasicScheme().authenticate(creds, httpPost2, null));
httpPost2.addHeader("X-RequestDigest", FormDigestValue);
httpPost2.addHeader("Accept", "application/json;odata=verbose");
httpPost2.addHeader("Content-Type", "application/json;odata=verbose");
CloseableHttpResponse response2 = client2.execute(httpPost2);
System.out.println(response2);
client2.close();
}
}
I know this isn't the most beautiful Code and yes, I am not an Java expert. My Problems are:
I don't know weather all of these code-Fragments are up to date or
weather I am using deprecated ones. Perhaps someone is able to
enlighten me.
I am using HttpClient from Apache. To me it looked like the most
usable library. Is that right?
Everytime I execute the Action on the front-end and my Code starts
running, I am getting an HTTP 401 Unauthorized error. I tried
various Kinds of Code but none worked well.
HttpResponseProxy{HTTP/1.1 401 Unauthorized [Server: Microsoft-IIS/8.0, SPR..
Perhaps someone has the Patience to tell me how to do it. Thank you.
Whoa... you are really trying some black magic here ;) - I would suggest you to get your HTTP POST / GET in a tool like Postman or some other REST tool working and then return to your code.
I don't know exactly what you are trying to achieve, but it might be easier to go via powershell (if you are trying to create a migration script) or JavaScript (if you are on a website).
Be aware that authentication differs in SharePoint online and SharePoint on premise... this is also customizable by your company (you can for example implement forms-based auth as well). Be sure to know what YOUR SharePoint is using. (Or share some more info, so we can help)
I got the authorization code following this document. But when I tried to get access token, I always got errors. Can anyone help me ?
public String AccessToken()
{
String accessToken = "";
StringBuilder strBuild = new StringBuilder();
String authURL = "https://accounts.google.com/o/oauth2/token?";
String code = "4/SVisuz_x*********************";
String client_id = "******************e.apps.googleusercontent.com";
String client_secret = "*******************";
String redirect_uri = "urn:ietf:wg:oauth:2.0:oob";
String grant_type="authorization_code";
strBuild.append("code=").append(code)
.append("&client_id=").append(client_id)
.append("&client_secret=").append(client_secret)
.append("&redirect_uri=").append(redirect_uri)
.append("&grant_type=").append(grant_type);
System.out.println(strBuild.toString());
try{
URL obj = new URL(authURL);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setDoOutput(true);
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
con.setRequestProperty("Host", "www.googleapis.com");
//BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(con.getOutputStream()));
//bw.write(strBuild.toString());
//bw.close();
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
wr.writeBytes(strBuild.toString());
wr.flush();
wr.close();
//OutputStreamWriter out = new OutputStreamWriter(con.getOutputStream());
System.out.println(con.getResponseCode());
System.out.println(con.getResponseMessage());
} catch (Exception e)
{
System.out.println("Error.");
}
return "";
}
when I ran this code, the output is:
400
Bad Request
How to get access token using gmail api?
Ans: As per your following tutorial, you are using OAuth 2.0. So there is a basic pattern for accessing a Google API using OAuth 2.0. It follows 4 steps:
Obtain OAuth 2.0 credentials from the Google Developers Console.
Obtain an access token from the Google Authorization Server.
Send the access token to an API.
Refresh the access token, if necessary.
For details, you can follow the tutorial - Using OAuth 2.0 to Access Google APIs
You have to visit the Google Developers Console to obtain OAuth 2.0 credentials such as a client ID and client secret that are known to both Google and your application
Root Cause Analysis:
Issue-1:
After studying your code, some lacking are found. If your code runs smoothly, then the code always give an empty string. Because your AccessToken() method always return return "";
Issue-2:
catch (Exception e)
{
System.out.println("Error.");
}
Your try catch block is going exception block. Because, it seems that you have not completed your code properly. You have missed encoding as well as using JSONObject which prepares the access token. So it is giving output as
Error.
Solution:
I got that your code is similar with this tutorial
As your code needs more changes to solve your issue. So I offer you to use LinkedHashMap or ArrayList. Those will provide easier way to make solution. So I give you 2 sample code to make your life easier. You can choose any of them. You need to change refresh_token, client id, client secret and grant type as yours.
private String getAccessToken()
{
try
{
Map<String,Object> params = new LinkedHashMap<>();
params.put("grant_type","refresh_token");
params.put("client_id",[YOUR CLIENT ID]);
params.put("client_secret",[YOUR CLIENT SECRET]);
params.put("refresh_token",[YOUR REFRESH TOKEN]);
StringBuilder postData = new StringBuilder();
for(Map.Entry<String,Object> param : params.entrySet())
{
if(postData.length() != 0)
{
postData.append('&');
}
postData.append(URLEncoder.encode(param.getKey(),"UTF-8"));
postData.append('=');
postData.append(URLEncoder.encode(String.valueOf(param.getValue()),"UTF-8"));
}
byte[] postDataBytes = postData.toString().getBytes("UTF-8");
URL url = new URL("https://accounts.google.com/o/oauth2/token");
HttpURLConnection con = (HttpURLConnection)url.openConnection();
con.setDoOutput(true);
con.setUseCaches(false);
con.setRequestMethod("POST");
con.getOutputStream().write(postDataBytes);
BufferedReader reader = new BufferedReader(new InputStreamReader(con.getInputStream()));
StringBuffer buffer = new StringBuffer();
for (String line = reader.readLine(); line != null; line = reader.readLine())
{
buffer.append(line);
}
JSONObject json = new JSONObject(buffer.toString());
String accessToken = json.getString("access_token");
return accessToken;
}
catch (Exception ex)
{
ex.printStackTrace();
}
return null;
}
For accessing google play android developer api, you need to pass the
previous refresh token to get access token
private String getAccessToken(String refreshToken){
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost("https://accounts.google.com/o/oauth2/token");
try
{
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(4);
nameValuePairs.add(new BasicNameValuePair("grant_type", "refresh_token"));
nameValuePairs.add(new BasicNameValuePair("client_id", GOOGLE_CLIENT_ID));
nameValuePairs.add(new BasicNameValuePair("client_secret", GOOGLE_CLIENT_SECRET));
nameValuePairs.add(new BasicNameValuePair("refresh_token", refreshToken));
post.setEntity(new UrlEncodedFormEntity(nameValuePairs));
org.apache.http.HttpResponse response = client.execute(post);
BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
StringBuffer buffer = new StringBuffer();
for (String line = reader.readLine(); line != null; line = reader.readLine())
{
buffer.append(line);
}
JSONObject json = new JSONObject(buffer.toString());
String accessToken = json.getString("access_token");
return accessToken;
}
catch (IOException e) { e.printStackTrace(); }
return null;
}
Resource Link:
Unable to get the subscription information from Google Play Android Developer API
Using java.net.URLConnection to fire and handle HTTP requests
How to send HTTP request GET/POST in Java
Hope that, this samples and resource link will help you to solve your issue and get access of access token.
What is 400 bad request?
Ans: It indicates that the query was invalid. Parent ID was missing or the combination of dimensions or metrics requested was not valid.
Recommended Action: You need to make changes to the API query in order for it to work.
For HTTP/1.1 400 Bad Request error, you can go through my another
answer. It will help you to make sense about which host you
need to use and which conditions you need to apply.
Why token expires? What is the limit of token?
A token might stop working for one of these reasons:
The user has revoked access.
The token has not been used for six months.
The user changed passwords and the token contains Gmail, Calendar,
Contacts, or Hangouts scopes.
The user account has exceeded a certain number of token requests.
There is currently a limit of 25 refresh tokens per user account per client. If the limit is reached, creating a new token automatically invalidates the oldest token without warning. This limit does not apply to service accounts.
Which precautions should be followed?
Precautions - 1:
Some requests require an authentication step where the user logs in
with their Google account. After logging in, the user is asked whether
they are willing to grant the permissions that your application is
requesting. This process is called user consent.
If the user grants the permission, the Google Authorization Server
sends your application an access token (or an authorization code that
your application can use to obtain an access token). If the user does
not grant the permission, the server returns an error.
Precautions - 2:
If an access token is issued for the Google+ API, it does not grant
access to the Google Contacts API. You can, however, send that access
token to the Google+ API multiple times for similar operations.
Precautions - 3:
An access token typically has an expiration date of 1 hour, after
which you will get an error if you try to use it. Google Credential
takes care of automatically "refreshing" the token, which simply means
getting a new access token.
Save refresh tokens in secure long-term storage and continue to use
them as long as they remain valid. Limits apply to the number of
refresh tokens that are issued per client-user combination, and per
user across all clients, and these limits are different. If your
application requests enough refresh tokens to go over one of the
limits, older refresh tokens stop working.
You are not using the right endpoint. Try to change the authURL to https://www.googleapis.com/oauth2/v4/token
From the documentation:
To make this token request, send an HTTP POST request to the /oauth2/v4/token endpoint
The actual request might look like the following:
POST /oauth2/v4/token HTTP/1.1
Host: www.googleapis.com
Content-Type: application/x-www-form-urlencoded
code=4/v6xr77ewYqhvHSyW6UJ1w7jKwAzu&
client_id=8819981768.apps.googleusercontent.com&
client_secret=your_client_secret&
redirect_uri=https://oauth2-login-demo.appspot.com/code&
grant_type=authorization_code
Reference https://developers.google.com/identity/protocols/OAuth2InstalledApp#handlingtheresponse
For me your request is fine, I tried it using Curl, I also get a 'HTTP/1.1 400 Bad Request' with the reason why it failed 'invalid_grant' :
curl -X POST https://www.googleapis.com/oauth2/v4/token -d 'code=4/SVisuz_x*********************&client_id=*******************7vet.apps.googleusercontent.com&client_secret=***************&redirect_uri=https://oauth2-login-demo.appspot.com/code&grant_type=authorization_code'
I receive (HTTP/1.1 400 Bad Request) :
{
"error": "invalid_grant",
"error_description": "Code was already redeemed."
}
Now using HttpClient from Apache :
URL obj = new URL(authURL);
HttpClient client = HttpClientBuilder.create().build();
HttpPost post = new HttpPost(authURL);
post.addHeader("Content-Type", "application/x-www-form-urlencoded");
post.addHeader("Host", "www.googleapis.com");
post.setEntity(new StringEntity(strBuild.toString()));
HttpResponse resp = client.execute(post);
System.out.println(resp.getStatusLine());
System.out.println(EntityUtils.toString(resp.getEntity()));
I see in my console :
HTTP/1.1 400 Bad Request
{
"error": "invalid_grant",
"error_description": "Code was already redeemed."
}
Are you sure the code you are using is still valid ? Can you try with a new one ?
Firstly, you must look this page :
https://developers.google.com/gmail/api/auth/web-server#create_a_client_id_and_client_secret
The value you see in the query parameter code is a string you have to post to google in order to get the access token.
After the web server receives the authorization code, it may exchange the authorization code for an access token and a refresh token. This request is an HTTPS POST to the URL https://www.googleapis.com/oauth2/v3/token
POST /oauth2/v3/token HTTP/1.1
content-type: application/x-www-form-urlencoded
code=4/v4-CqVXkhiTkn9uapv6V0iqUmelHNnbLRr1EbErzkQw#&redirect_uri=&client_id=&scope=&client_secret=************&grant_type=authorization_code
https://developers.google.com/identity/protocols/OAuth2WebServer
I think I understand what's wrong:
as #newhouse said, you should POST to https://www.googleapis.com/oauth2/v4/token and not https://accounts.google.com/o/oauth2/token (#newhouse I gave you a +1 :) )
(https://www.googleapis.com/oauth2/v4/token is for getting the authorization_code and https://accounts.google.com/o/oauth2/token is for getting the code).
You can't use the same code more than once.
Everything else seems in order so, if you keep getting 400, you are probably trying to use the code you got more than one time (then you'll get 400 every time, again and again).
* You should also lose the con.setRequestProperty("Host", "www.googleapis.com");
Refer : https://developers.google.com/android-publisher/authorization
You already have authorization code that is called "refresh token". Please keep it in safe place. You can use "refresh token" to generate "access token".
To get "access token", please make a post request to following URL
https://accounts.google.com/o/oauth2/token
Parameters:
grant_type
client_id
client_secret
refresh_token
where "grant_type" should be "refresh_token"
We are using PHP to do same, here is PHP's code for your reference
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_URL => 'https://accounts.google.com/o/oauth2/token',
CURLOPT_USERAGENT => 'Pocket Experts Services',
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => array(
"grant_type" => "refresh_token",
"client_id" => $GOOGLE_CLIENT_ID,
"client_secret" => $GOOGLE_CLIENT_SECRET,
"refresh_token" => $GOOGLE_REFRESH_TOKEN,
)));
// Send the request & save response to $resp
$resp = curl_exec($curl);
Hope it will help you.
the low security methode was temporary and i couldn't use it in production but I found an article that made it easier using node here
with an example code and it works perfect
I am trying to update email alias for different users. I am able to authenticate, get the code and then get the access token. I am sending the access token in the HTTP POST request as a Header. I am using Java & Apache HTTPClient to make the RESTful call. Here is the code snippet (Only relevant code shown).
if (httpClient != null) {
String apiURL = getApiURL();
apiURL = MessageFormat.format(apiURL, "firstname.lastname#company.com");
// apiURL = https://api.box.com/2.0/users/firstname.lastname#company.com/email_aliases
// firstname.lastname#company.com does exist in the Box Account
HttpPost post = new HttpPost(apiURL);
post.addHeader("Authorization", "Bearer "+accessToken);
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("email", "updateemail#company.com"));
post.setEntity(new UrlEncodedFormEntity(nameValuePairs, Charset.defaultCharset()));
HttpEntity entity = post.getEntity();
ResponseHandler<String> responseHandler = new BasicResponseHandler();
String responseFromBox = httpClient.execute(post, responseHandler);
writeResponse(response, responseFromBox);
if (responseFromBox != null) {
if (logger.isDebugEnabled()) {
logger.debug("apiURL-->"+apiURL);
logger.debug(responseFromBox);
}
}
}
The problem is that the response I get is some HTML code that says "The page you were viewing has expired. Please go back and try your request again." I was expecting some JSON string.
What I am doing incorrect? In the Post request instead of sending the email address I used the user id. But I get the same error.
In fact when I try to fetch the email alias of a user using the HTTP GET request I get an error "Not Found". The user does exist. I have an admin control. I can see them.
Thanks
Raj
Try a get on /users to get the array of all your users in the enterprise first. Is that working for you? If not, can you do a get on /users/me? If you can't get the former, then your API key may not have the "manage an enterprise" grant setup for it. You have to set that up in the app management, where you setup your OAuth2 callback URL.
Not sure why you are getting HTML back. That usually only happens on badly formed requests that our servers can't even parse, like you are hitting the wrong URL.
Just a reminder, OAuth2 URL is different from the API URL. 1st is https://www.box.com/api/oauth2/.... 2nd is https://api.box.com/2.0/...
As for setting the Email alias, that's entirely possible, once you know the ID of the user you are trying to set the alias for. Documentation is here
I was using the NameValuePair instead of the JSON string that was being expected. So I removed the following
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("email", "updateemail#company.com"));
post.setEntity(new UrlEncodedFormEntity(nameValuePairs, Charset.defaultCharset()));
and added
String json = "{\"email\":\"firstname.lastname#company.com\"}";
StringEntity entity = new StringEntity(json, Charset.defaultCharset());
post.setEntity(entity);
and then things started to work!
I have submitted an app to Amazon for approval, they came back with this:
"This app appears to be sending unencrypted, sensitive information. In this instance, the E-MAIL and PASSWORD, is being sent in clear text. Please update the app to encrypt all sensitive information."
On the server side, I encrypt the password in my database using the sha1() PHP method (pretty standard). I am assuming they want the password/email String that Java passes to be encrypted while in transit to the web service. I assume? If this is the case, I need to decrypt the data (specifically the email because this needs to be stored in my DB in plain text.
Has anyone seen this Amazon inquiry before? And is my explanation of it correct? And if so, is there a way in Java to temporary encrypt data while in transit?
Here is a sample in how I do it:
insertParam = new ArrayList<NameValuePair>();
insertParam.add(new BasicNameValuePair("Email", Email));
insertParam.add(new BasicNameValuePair("Password", Password));
insertParam.add(new BasicNameValuePair("Username", Username));
try {
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url_select);
httpPost.setEntity(new UrlEncodedFormEntity(insertParam));
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
is = httpEntity.getContent();
}
EDIT:
Looks like HTTPS is the way to go.
Amazon's requirement seems somewhat conservative, but could be best met by connecting to your web service via HTTPS instead of unencrypted HTTP. This is exactly what another StackOverflow user did in the end: Amazon AppStore Submission Failed: "Sensitive information like password is echoed in clear text without encryption"
While you could encrypt the data in your app, send it over the internet, and decrypt it on your server using a shared key, this is vulnerable to attackers that decompile your app to get the key.
Alternatively, you could generate a key pair, include the public key in the app and encrypt data with that, send it over the internet, and then use the private key on the server to decrypt the incoming data, but you're basically just re-implementing HTTPS manually.
At the end of the day, the "right" way to implement Amazon's requirement is to use HTTPS. Anything else is likely to be difficult to implement securely.
Please excuse my lack of knowledge on the topic, but I have very little, if any knowledge of networking, PHP, web requests, and such. Essentially, I want to send a string to a website for logging using $_GET variables. How can I send a string using this method, from inside the app?
(I can't self answer for another 6 hours, but if I COULD, here is what it would look like, with the code in the answer of course. Just didn't wan't to take away from the original question.)
In the end, the code found here worked.
The app sends a request to the web server, which then appends the string in the $_GET variable to a log file! Took a few hours to figure out though. :l
You can use the Apache Commons HttpClient library to make HTTP requests.
HTTP request URIs consist of a protocol scheme, host name, optional port, resource path, optional query, and optional fragment.
HttpGet httpget = new HttpGet(
"http://www.google.com/search?hl=en&q=httpclient&btnG=Google+Search&aq=f&oq=");
Query string can also be generated from individual parameters:
List<NameValuePair> qparams = new ArrayList<NameValuePair>();
qparams.add(new BasicNameValuePair("q", "httpclient"));
qparams.add(new BasicNameValuePair("btnG", "Google Search"));
qparams.add(new BasicNameValuePair("aq", "f"));
qparams.add(new BasicNameValuePair("oq", null));
URI uri = URIUtils.createURI("http", "www.google.com", -1, "/search",
URLEncodedUtils.format(qparams, "UTF-8"), null);
HttpGet httpget = new HttpGet(uri);
System.out.println(httpget.getURI());
wanstein is right, but the URIUtils.createURI is deprecated now (4.2.1), so it is better to use the URIBuilder:
URI uri = new URIBuilder()
.setFragment("http")
.setHost(HOST)
.setPath(path)
.setQuery(URLEncodedUtils.format(qparams, "UTF-8"))
.build();