您的位置:首页 > 编程语言 > Java开发

网建短信通 使用java调用API发送短信时总是返回-41,关键的关键,仅在于一个问号:(

2019-08-22 17:07 309 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/qq_41885819/article/details/100019477

今天突发奇想做一个定时给女朋友发送表白短信的功能,发送短信的接口很多,不过基本都是收费的,情有可原。在网建短信通平台(http://sms.webchinese.cn/default.shtml)可以非常找到各语言的示例代码。我自己没有采用默认版本的jar包,直接在maven里面加载了对应包的最新版本,那么,问题就来了,特别是org.apache.httpcomponents在4.0后应该有了较大的更新,很多方法就不能直接使用,测试了很久返回值都是-41,按照平台API可以知道,显示的是:手机号为空,下面是部分代码:

import java.io.IOException;
import java.util.LinkedList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

public class SendMessageService {
// 接口地址
private Log logger = LogFactory.getLog(this.getClass());
private HttpClient httpClient = null;
private HttpPost httpPost = null;
private long startTime = 0L;
private long endTime = 0L;
private int status = 0;
//测试方法
public static void main(String[] args) {
SendMessageService ac = new SendMessageService("http://utf8.api.smschinese.cn/");
List<NameValuePair> list = new LinkedList<NameValuePair>();
//设置用户名
NameValuePair param1 = new BasicNameValuePair("Uid", "xxx");
//设置秘钥,这个秘钥不是你用户名密码,要去网站上查看
NameValuePair param2 = new BasicNameValuePair("Key", "xxx");
//设置收信人号码
NameValuePair param3 = new BasicNameValuePair("smsMob", "xxx");
//设置短信内容,内容中不宜出现空格等特殊符号
NameValuePair param4 = new BasicNameValuePair("smsText", "xxx");
list.add(param1);
list.add(param2);
list.add(param3);
list.add(param4);
System.out.println(ac.post(list));
System.out.println(ac.getStatus());
}
//构造方法
public SendMessageService(String url) {
if (url != null) {
this.apiURL = url;
}
if (apiURL != null) {
RequestConfig config = RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD_STRICT).build();
this.httpClient = HttpClients.custom().setDefaultRequestConfig(config).build();
this.httpPost = new HttpPost(apiURL);
}
}
//调用接口API
public String post(List<NameValuePair> list) {
String body = null;
if (this.httpPost != null & list != null ) {
try {
UrlEncodedFormEntity entityParam = new UrlEncodedFormEntity(list, "UTF-8");
httpPost.setEntity(entityParam);
this.startTime = System.currentTimeMillis();
HttpResponse response = httpClient.execute(this.httpPost);
this.endTime = System.currentTimeMillis();
int statusCode = response.getStatusLine().getStatusCode();
logger.info("statusCode:" + statusCode);
logger.info("调用API 花费时间(单位:毫秒):" + (this.endTime - this.startTime));
if (statusCode != HttpStatus.SC_OK) {
logger.error("Method failed:" + response.getStatusLine());
this.status = 1;
}
// Read the response body
body = EntityUtils.toString(response.getEntity());
} catch (IOException e) {
// 网络错误
this.status = 3;
} finally {
logger.info("调用接口状态:" + this.status);
}
}
return body;
}
/**
* 0.成功 1.执行方法失败 2.协议错误 3.网络错误
* @return the status
*/
public int getStatus() {
return this.status;
}
public long getStartTime() {
return this.startTime;
}
public long getEndTime() {
return this.endTime;
}
}

既然不能识别请求信息中的电话号码,即请求参数,那么肯定是在配置参数时有问题。所以得查看httpClient源码一探究竟,根据一骨碌的继承关系,最终找到了org.apache.http.client.utils.URLEncodedUtils这个工具类中。

public static String format(
final List <? extends NameValuePair> parameters,
final String charset) {
return format(parameters, QP_SEP_A, charset);
}
public static String format(
final List <? extends NameValuePair> parameters,
final char parameterSeparator,
final String charset) {
final StringBuilder result = new StringBuilder();
for (final NameValuePair parameter : parameters) {
final String encodedName = encodeFormFields(parameter.getName(), charset);
final String encodedValue = encodeFormFields(parameter.getValue(), charset);
if (result.length() > 0) {
result.append(parameterSeparator);
}
result.append(encodedName);
if (encodedValue != null) {
result.append(NAME_VALUE_SEPARATOR);
result.append(encodedValue);
}
}
return result.toString();
}

从第二个format方法可以看到,就是把参数名和参数值取出来,中间连接一个“&”,等等,是不是差点什么,第一个参数与前面URL之间的“?”呢??果然,在声明URL的时候加上一个问号直接解决问题:http://utf8.api.smschinese.cn/?,这样在后续的拼接过程后,才能正确的读取参数。
另外,更加简单粗暴的方法是直接在声明URL的时候,加上对应的参数信息,就可以一步到位了,但是这样不是特别利于代码的维护及扩展。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: