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

今天突发奇想做一个定时给女朋友发送表白短信的功能,发送短信的接口很多,不过基本都是收费的,情有可原。在网建短信通平台(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的时候,加上对应的参数信息,就可以一步到位了,但是这样不是特别利于代码的维护及扩展。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

穿条秋裤到处跑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值