微信开发整合日记(6)

微信公众号红包支付接口的使用

本篇介绍微信商户平台中的红包发送接口
1.准备阶段
需要一个开通了微信支付的公众号,并且在产品中心中开通微信红包功能,并且设置好基本设置,注意IP地址一定要是调用接口的服务器的正确的外网地址,防刷等级和每个用户限量按自己的需要配置就可以了.
2.开发
在微信的开发文档中我们可以看到,红包的请求和微信返回的数据都是XML格式的,所以我们首先要写一个工具类能够将XML转化成我们能够读取的格式和把类转化成XML格式,在这里我使用的是xstream,也可以使用其他的工具,sxtream有一个BUG,会导致生成XML文件时,会把"-"变成"--",解决办法可以直接用replace替换成"-",另外需要注意编码格式,一定要全部都使用同一个格式,不然会导致调用接口时返回错误
格式转换工具类好了之后需要写HTTP请求的工具类,红包发送接口需要在请求中携带证书信息,首先我们从微信开发文档中下载证书,下载有4个格式的证书,JAVA的话使用.p12格式的文件,将文件放入一个目录下,如C:\\apiclient_cert.p12目录下,保存好目录路径.我们在文档中可以看见,红包支付需要的数据如下图

还有三个参数并不是必须的,我们选择忽略掉,其他参数如下
1).nonce_str:随即字符串,自己设置
2).sign:签名,这个需要设置好所有参数之后加密产生
3).商户订单号:组成为商户号加上日期再加上10位一天内不能重复的数字,后面10位数字可以用时间戳截取后10位数字完全可以使用
4).商户号:重要的数据,在微信商户平台中可以查看,妥善保管
5).appid:公众号ID
6).商户名称:自己设置
7).re_openid:接受红包的用户ID
8).IP:当前服务器外网IP地址
其他参数按需设置
参数设置好了之后保存在项目中,也可以保存在properties文件中
然后我们需要获取签名sign,跟微信其他签名一样,将所有需要使用的参数按参数名ASCII码从小到大排序,如果参数为空则不参加排序,注意区分大小写,排序好之后需要加上一个key值,这个key值是在微信商户平台中的账户中心中的API安全中设置,我们得到的字符串应如下所示
act_name=XXXX&client_ip=100.100.100.80&mch_billno=23233&mch_id=1394445702&nonce_str=3223&re_openid=3322321213&remark=xxxx&send_name=XXXXX&total_amount=100&total_num=1&wishing=XXXXX&wxappid=WXX32DD&key=qwertyuioplkjhgfdsazxcvbnmWW
      注意一定要加上KEY值,然后使用MD5加密,注意此处的编码格式,微信提供了一个网站供我们测试签名http://mch.weixin.qq.com/wiki/tools/signverify/
HTTP请求工具我们使用httpclient,需要加入两个包,pom文件如下

我们的代
	public static String sendRedpack(String url,RedpackVo vo) throws IOException, NoSuchAlgorithmException, IllegalArgumentException, IllegalAccessException{
		String content = vo.toString(vo);
		content = content + "key=" + Constants.KEY;
		MessageDigest md = MessageDigest.getInstance("MD5");
		md.update(content.getBytes("UTF-8"));
		byte[] digest = md.digest();

		StringBuffer hexstr = new StringBuffer();
		String shaHex = "";
		for (int i = 0; i < digest.length; i++) {
			shaHex = Integer.toHexString(digest[i] & 0xFF);
			if (shaHex.length() < 2) {
				hexstr.append(0);
			}
			hexstr.append(shaHex);
		}
		vo.setSign(hexstr.toString());
		String params = MessageUtil.redpackToXml(vo).replace("__", "_");
		String result = "";
		FileInputStream instream = null;
		CloseableHttpClient httpclient = null;
		BufferedReader br = null;
		try{
			KeyStore keyStore = KeyStore.getInstance("PKCS12");
			instream = new FileInputStream(new File(Constants.getCertLocalPath()));
			keyStore.load(instream, Constants.getCertPassword().toCharArray());
			SSLContext sslContext = SSLContexts.custom().loadKeyMaterial(keyStore, Constants.getCertPassword().toCharArray()).build();
			SSLConnectionSocketFactory sslcsf = new SSLConnectionSocketFactory(sslContext,new String[]{"TLSv1"},null,SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
			httpclient = HttpClients.custom().setSSLSocketFactory(sslcsf).build();
			HttpPost httpPost = new HttpPost(url);
			StringEntity reqEntity = new StringEntity(params,"UTF-8");
			httpPost.setEntity(reqEntity);
			CloseableHttpResponse response = httpclient.execute(httpPost);
			HttpEntity entity = response.getEntity();
			if(entity != null){
				br = new BufferedReader(new InputStreamReader(entity.getContent(),"UTF-8"));
				String text;
				while((text = br.readLine()) != null){
					result+=text;
				}
			}
		}catch(Exception e){
			throw new RuntimeException();
		}finally{
			if(instream != null)
				instream.close();
			if(br != null)
				br.close();
			if(httpclient != null)
				httpclient.close();
		}
		return result;
	}
messageUtil和redpackVo是我自己封装的类,按自己的需要来封装
package com.pub.vo;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;

import com.framework.util.DateFormat;
import com.framework.util.PropertiesLoader;

public class RedpackVo {
	
	private String act_name;
	
	private String client_ip;
	
	private String mch_billno;

	private String mch_id;

	private String nonce_str;
	
	private String re_openid;
	
	private String remark;
	
	private String send_name;

	private String sign;

	private Integer total_amount;

	private Integer total_num;

	private String wishing;
	
	private String wxappid;

	public String getNonce_str() {
		return nonce_str;
	}

	public void setNonce_str(String nonce_str) {
		this.nonce_str = nonce_str;
	}

	public String getSign() {
		return sign;
	}

	public void setSign(String sign) {
		this.sign = sign;
	}

	public String getMch_billno() {
		return mch_billno;
	}

	public void setMch_billno(String mch_billno) {
		this.mch_billno = mch_billno;
	}

	public String getMch_id() {
		return mch_id;
	}

	public void setMch_id(String mch_id) {
		this.mch_id = mch_id;
	}

	public String getWxappid() {
		return wxappid;
	}

	public void setWxappid(String wxappid) {
		this.wxappid = wxappid;
	}

	public String getSend_name() {
		return send_name;
	}

	public void setSend_name(String send_name) {
		this.send_name = send_name;
	}

	public String getRe_openid() {
		return re_openid;
	}

	public void setRe_openid(String re_openid) {
		this.re_openid = re_openid;
	}

	public Integer getTotal_amount() {
		return total_amount;
	}

	public void setTotal_amount(Integer total_amount) {
		this.total_amount = total_amount;
	}

	public Integer getTotal_num() {
		return total_num;
	}

	public void setTotal_num(Integer total_num) {
		this.total_num = total_num;
	}

	public String getWishing() {
		return wishing;
	}

	public void setWishing(String wishing) {
		this.wishing = wishing;
	}

	public String getClient_ip() {
		return client_ip;
	}

	public void setClient_ip(String client_ip) {
		this.client_ip = client_ip;
	}

	public String getAct_name() {
		return act_name;
	}

	public void setAct_name(String act_name) {
		this.act_name = act_name;
	}

	public String getRemark() {
		return remark;
	}

	public void setRemark(String remark) {
		this.remark = remark;
	}

	public RedpackVo(String openid,Integer amt){
		Properties p = PropertiesLoader.loadProperty("/application.properties");
		setAct_name(p.getProperty("ACT_NAME"));
		setClient_ip(p.getProperty("CLIENT_IP"));
		setMch_id(p.getProperty("MCH_ID"));
		setNonce_str(p.getProperty("NONCE_STR"));
		setRemark(p.getProperty("WISHING"));
		setWxappid(p.getProperty("APP_ID"));
		setWishing(p.getProperty("WISHING"));
		setSend_name(p.getProperty("SEND_NAME"));
		String time = String.valueOf(System.currentTimeMillis());
		setTotal_num(1);
		setRe_openid(openid);
		setTotal_amount(amt);
		setMch_billno(mch_id + DateFormat.getYmd() + time.substring(time.length()-10, time.length()));
	}
	
	public String toString(RedpackVo vo) throws IllegalArgumentException, IllegalAccessException{
		Class<? extends RedpackVo> clazz = vo.getClass();
		Field[] fields = clazz.getDeclaredFields();
		List<String> names = new ArrayList<String>();
		for (Field field : fields) {
			if(field.get(vo) != null){
				names.add(field.getName()+"="+field.get(vo)+"&");
			}
		}
		StringBuffer sb = new StringBuffer();
		String[] str = names.toArray(new String[names.size()]);
		Arrays.sort(str);
		for(int i =0; i<str.length ; i++){
			sb.append(str[i]);
		}
		return sb.toString();
	}

}

	@SuppressWarnings("unchecked")
	public static Map<String, String> parseXml(String connet) throws IOException, DocumentException {
		Map<String, String> map = new HashMap<String, String>();
		InputStream inputStream = new ByteArrayInputStream(connet.getBytes("UTF-8"));
		SAXReader reader = new SAXReader();
		Document document = reader.read(inputStream);

		Element root = document.getRootElement();
		List<Element> elementList = root.elements();
		for (Element e : elementList)
			map.put(e.getName(), e.getText());
		inputStream.close();
		inputStream = null;
		return map;
	}
到现在我们已经拥有了调用接口所需的一切条件,接下来我们写一个main方法测试一下
	public static void main(String[] args) throws NoSuchAlgorithmException, IllegalArgumentException, IllegalAccessException, IOException {
		String result = WxHttpHelper.sendRedpack(WechatHttplocal.sendredpack(), new RedpackVo("openid",1000));
	}
没错,调用的方法就是这么简单,因为我们前面已经把工具类都写完了,注意这里的金额是以分为单位的,写1000代表是发10元红包,微信设置发送红包最少1元,所以填100以下微信会返回错误代码
如果前面一切配置正常,微信一般会返回如下数据

失败则返回

微信红包接口开发结束,如有问题可以留言

忘记说了,证书密码一般是公众号的商户号,只要你没有修改默认都是这个
Constants.getCertLocalPath()证书的地址
Constants.getCertPassword()证书的密码,默认商户号

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值