在一定的逻辑下执行发送微信红包给用户,为了加深印象记录一下,友好的方法欢迎提出!

在微信支付-->开发者文档中,能看到  现金红包-->产品说明/操作指导的文档,如下

然后,这里需要注意的地方

在这里有请求的参数,根据这个封装需要的实体类,如下:

/*** 微信现金红包实体类* @author apple**/
public class WeixinRedPacket {private String nonce_str;//随机字符串,不长于32位private String sign;//签名private String mch_billno;//商户订单号   private String mch_id;//商户号 private String wxappid;//公众账号appid  private String nick_name;//必填字段private String send_name;//商户名称private String re_openid;//用户openid   private String total_amount;//付款金额  private String total_num;//红包发放总人数 必须为1private String wishing;//红包祝福语   private String client_ip;//Ip地址private String act_name;//活动名称private String remark;//备注private String consume_mch_id;//资金授权商户号 服务商替特约商户发放时使用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 getNick_name() {return nick_name;}public void setNick_name(String nick_name) {this.nick_name = nick_name;}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 String getTotal_amount() {return total_amount;}public void setTotal_amount(String total_amount) {this.total_amount = total_amount;}public String getTotal_num() {return total_num;}public void setTotal_num(String 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 String getConsume_mch_id() {return consume_mch_id;}public void setConsume_mch_id(String consume_mch_id) {this.consume_mch_id = consume_mch_id;}}

随后,需要生成32位字符串

import java.net.InetAddress;/*** 生成32位字符串* */
public class UUIDHexGeneratorutil {private String sep = "";private static final int IP;private static short counter = (short) 0;private static final int JVM = (int) (System.currentTimeMillis() >>> 8);private static UUIDHexGeneratorutil uuidgen = new UUIDHexGeneratorutil();static {int ipadd;try {ipadd = toInt(InetAddress.getLocalHost().getAddress());} catch (Exception e) {ipadd = 0;}IP = ipadd;}public static UUIDHexGeneratorutil getInstance() {return uuidgen;}public static int toInt(byte[] bytes) {int result = 0;for (int i = 0; i < 4; i++) {result = (result << 8) - Byte.MIN_VALUE + (int) bytes[i];}return result;}protected String format(int intval) {String formatted = Integer.toHexString(intval);StringBuffer buf = new StringBuffer("00000000");buf.replace(8 - formatted.length(), 8, formatted);return buf.toString();}protected String format(short shortval) {String formatted = Integer.toHexString(shortval);StringBuffer buf = new StringBuffer("0000");buf.replace(4 - formatted.length(), 4, formatted);return buf.toString();}protected int getJVM() {return JVM;}protected synchronized short getCount() {if (counter < 0) {counter = 0;}return counter++;}protected int getIP() {return IP;}protected short getHiTime() {return (short) (System.currentTimeMillis() >>> 32);}protected int getLoTime() {return (int) System.currentTimeMillis();}public String generate() {return new StringBuffer(36).append(format(getIP())).append(sep).append(format(getJVM())).append(sep).append(format(getHiTime())).append(sep).append(format(getLoTime())).append(sep).append(format(getCount())).toString();}/*** @param args*/public static void main(String[] args) {String id;UUIDHexGeneratorutil uuid = UUIDHexGeneratorutil.getInstance();for(int i = 0;i<100;i++){id = uuid.generate();}}
}

可以测试一下,是否生成了字符串。

以下是MD5和发送红包,导包的时候需要注意。

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;import javax.net.ssl.SSLContext;import org.apache.commons.codec.digest.DigestUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;import com.ttantu.weixin.entity.WeixinRedPacket;/**
* 功能:MD5签名处理核心文件,不需要修改
* 说明:
* 以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。
* */
public class MD5 {/*** 签名字符串* @param text 需要签名的字符串* @param key 密钥* @param input_charset 编码格式* @return 签名结果*/public static String sign(String text, String key, String input_charset) {text = text + key;return DigestUtils.md5Hex(getContentBytes(text, input_charset));}/*** 签名字符串* @param text 需要签名的字符串* @param sign 签名结果* @param key 密钥* @param input_charset 编码格式* @return 签名结果*/public static boolean verify(String text, String sign, String key, String input_charset) {text = text + key;String mysign = DigestUtils.md5Hex(getContentBytes(text, input_charset));if(mysign.equals(sign)) {return true;}else {return false;}}/*** @param content* @param charset* @return* @throws SignatureException* @throws UnsupportedEncodingException */private static byte[] getContentBytes(String content, String charset) {if (charset == null || "".equals(charset)) {return content.getBytes();}try {return content.getBytes(charset);} catch (UnsupportedEncodingException e) {throw new RuntimeException("MD5签名过程中出现错误,指定的编码集不对,您目前指定的编码集是:" + charset);}}//   }/*** 生成6位或10位随机数* param codeLength(多少位)* @return*/private String createCode(int codeLength) {String code="";for(int i=0; i<codeLength; i++) {code += (int)(Math.random() * 9);}return code;}/*  private static boolean isValidChar(char ch) {  if ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z')|| (ch >= 'a' && ch <= 'z'))  return true;  if ((ch >= 0x4e00 && ch <= 0x7fff) || (ch >= 0x8000 && ch <= 0x952f))  return true;// 简体中文汉字编码  return false;  }*//** * 除去数组中的空值和签名参数* @param sArray 签名参数组* @return 去掉空值与签名参数后的新签名参数组*/public static Map<String, String> paraFilter(Map<String, String> sArray) {Map<String, String> result = new HashMap<String, String>();if (sArray == null || sArray.size() <= 0) {return result;}for (String key : sArray.keySet()) {String value = sArray.get(key);if (value == null || value.equals("") || key.equalsIgnoreCase("sign")|| key.equalsIgnoreCase("sign_type")) {continue;}result.put(key, value);}return result;}/** * 把数组所有元素排序,并按照“参数=参数值”的模式用“&”字符拼接成字符串* @param params 需要排序并参与字符拼接的参数组* @return 拼接后字符串*/public static String createLinkString(Map<String, String> params) {List<String> keys = new ArrayList<String>(params.keySet());Collections.sort(keys);String prestr = "";for (int i = 0; i < keys.size(); i++) {String key = keys.get(i);String value = params.get(key);if (i == keys.size() - 1) {//拼接时,不包括最后一个&字符prestr = prestr + key + "=" + value;} else {prestr = prestr + key + "=" + value + "&";}}return prestr;}/*** 发送现金红包* @throws KeyStoreException * @throws IOException * @throws CertificateException * @throws NoSuchAlgorithmException * @throws UnrecoverableKeyException * @throws KeyManagementException * @throws DocumentException */public void sendRedPack() throws KeyStoreException, NoSuchAlgorithmException, IOException,KeyManagementException, UnrecoverableKeyException, DocumentException, CertificateException {// 获取uuid作为随机字符串  UUIDHexGeneratorutilUUIDHexGeneratorutil uuidGenerator = new UUIDHexGeneratorutil();String nonceStr = uuidGenerator.generate();String today = new SimpleDateFormat("yyyyMMdd").format(new Date());String code = createCode(10);String mch_id = "11111111111";//商户号String appid = "wxwswsw23d3c";String opendid = "wbibwxslocvbnyui89"; //发送给指定微信用户的openidWeixinRedPacket sendRedPackPo = new WeixinRedPacket();String totalAmount = "1";sendRedPackPo.setNonce_str(nonceStr);sendRedPackPo.setMch_billno(mch_id + today + code);sendRedPackPo.setMch_id(mch_id);sendRedPackPo.setWxappid(appid);sendRedPackPo.setSend_name("商户名称");//商户名称sendRedPackPo.setRe_openid(opendid);sendRedPackPo.setTotal_amount(totalAmount);sendRedPackPo.setTotal_num("1");sendRedPackPo.setWishing("恭喜发财");//红包祝福语sendRedPackPo.setClient_ip("192.168.1.1"); //调用接口的机器Ip地址sendRedPackPo.setAct_name("新年快乐");//活动名称sendRedPackPo.setRemark("新年快乐");//备注信息//把请求参数打包成数组Map<String, String> sParaTemp = new HashMap<String, String>();sParaTemp.put("mch_billno", sendRedPackPo.getMch_billno());sParaTemp.put("mch_id", sendRedPackPo.getMch_id());sParaTemp.put("wxappid", sendRedPackPo.getWxappid());sParaTemp.put("send_name", sendRedPackPo.getSend_name());sParaTemp.put("re_openid", sendRedPackPo.getRe_openid());sParaTemp.put("total_amount", sendRedPackPo.getTotal_amount());sParaTemp.put("total_num", sendRedPackPo.getTotal_num());sParaTemp.put("wishing", sendRedPackPo.getWishing());sParaTemp.put("client_ip", sendRedPackPo.getClient_ip());sParaTemp.put("act_name", sendRedPackPo.getAct_name());sParaTemp.put("remark", sendRedPackPo.getRemark());sParaTemp.put("nonce_str", sendRedPackPo.getNonce_str());//除去数组中的空值和签名参数Map<String, String> sPara = paraFilter(sParaTemp);String prestr = createLinkString(sPara); //把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串String key = "&key=jghjiughcgshxnamihdvhbxznkm"; //商户支付密钥String mysign = MD5.sign(prestr, key, "utf-8").toUpperCase();sendRedPackPo.setSign(mysign);// 文本消息对象转换成xml ??????????String respXml = MessageUtil.textMessageToXml(sendRedPackPo);//打印respXml发现,得到的xml中有“__”不对,应该替换成“_”respXml = respXml.replace("__", "_");// 将解析结果存储在HashMap中 Map<String, String> map = new HashMap<String, String>();KeyStore keyStore  = KeyStore.getInstance("PKCS12");FileInputStream instream = new FileInputStream(new File("D:/weixin/pay/gz_apiclient_cert.p12")); //此处为证书所放的绝对路径try {keyStore.load(instream, mch_id.toCharArray());} finally {instream.close();}// Trust own CA and all self-signed certsSSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, mch_id.toCharArray()).build();// Allow TLSv1 protocol onlySSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext,new String[] { "TLSv1" },null,SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();try {//发红包接口地址 HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack");StringEntity  reqEntity  = new StringEntity(respXml, "utf-8");// 设置类型  reqEntity.setContentType("application/x-www-form-urlencoded"); httpPost.setEntity(reqEntity);System.out.println("executing request" + httpPost.getRequestLine());CloseableHttpResponse response = httpclient.execute(httpPost);try {HttpEntity entity = response.getEntity();System.out.println(response.getStatusLine());if (entity != null) {// 从request中取得输入流InputStream inputStream = entity.getContent();// 读取输入流SAXReader reader = new SAXReader();Document document = reader.read(inputStream);// 得到xml根元素Element root = document.getRootElement();// 得到根元素的所有子节点List<Element> elementList = root.elements();// 遍历所有子节点for (Element e : elementList)map.put(e.getName(), e.getText());// 释放资源inputStream.close();inputStream = null;}EntityUtils.consume(entity);} finally {response.close();}} finally {httpclient.close();}// 返回状态码String return_code = map.get("return_code");// 返回信息String return_msg = map.get("return_msg");// 业务结果String result_code = map.get("result_code");// 错误代码String err_code = map.get("err_code");// 错误代码描述String err_code_des = map.get("err_code_des");/*** 根据以上返回码进行业务逻辑处理*/}

可以测试一下,仅此作为商户测试代码,根据需要再进行修改。

还有一个MessageUtil是将文本对象转换为xml。这个网上很多。借鉴了下。

import java.io.InputStream;
import java.io.Writer;
import java.util.HashMap;
import java.util.List;
import java.util.Map; import javax.servlet.http.HttpServletRequest; import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader; import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.core.util.QuickWriter;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import com.thoughtworks.xstream.io.xml.XppDriver;
import com.ttantu.weixin.entity.WeixinRedPacket; /** * 消息工具类 *  * @author liufeng * @date 2013-05-19 */
public class MessageUtil {/** * 返回消息类型:文本 */ public static final String RESP_MESSAGE_TYPE_TEXT = "text"; /** * 返回消息类型:音乐 */ public static final String RESP_MESSAGE_TYPE_MUSIC = "music"; /** * 返回消息类型:图文 */ public static final String RESP_MESSAGE_TYPE_NEWS = "news"; /** * 请求消息类型:文本 */ public static final String REQ_MESSAGE_TYPE_TEXT = "text"; /** * 请求消息类型:图片 */ public static final String REQ_MESSAGE_TYPE_IMAGE = "image"; /** * 请求消息类型:链接 */ public static final String REQ_MESSAGE_TYPE_LINK = "link"; /** * 请求消息类型:地理位置 */ public static final String REQ_MESSAGE_TYPE_LOCATION = "location"; /** * 请求消息类型:音频 */ public static final String REQ_MESSAGE_TYPE_VOICE = "voice"; /** * 请求消息类型:推送 */ public static final String REQ_MESSAGE_TYPE_EVENT = "event"; /** * 事件类型:subscribe(订阅) */ public static final String EVENT_TYPE_SUBSCRIBE = "subscribe"; /** * 事件类型:unsubscribe(取消订阅) */ public static final String EVENT_TYPE_UNSUBSCRIBE = "unsubscribe"; /** * 事件类型:CLICK(自定义菜单点击事件) */ public static final String EVENT_TYPE_CLICK = "CLICK"; /** * 解析微信发来的请求(XML) *  * @param request * @return * @throws Exception */ @SuppressWarnings("unchecked") public static Map<String, String> parseXml(HttpServletRequest request) throws Exception { // 将解析结果存储在HashMap中 Map<String, String> map = new HashMap<String, String>(); // 从request中取得输入流 InputStream inputStream = request.getInputStream(); // 读取输入流 SAXReader reader = new SAXReader(); Document document = reader.read(inputStream); // 得到xml根元素 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; } /** * 文本消息对象转换成xml *  * @param textMessage 文本消息对象 * @return xml */ public static String textMessageToXml(WeixinRedPacket textMessage) { xstream.alias("xml", textMessage.getClass()); return xstream.toXML(textMessage); } /** * 音乐消息对象转换成xml *  * @param musicMessage 音乐消息对象 * @return xml public static String musicMessageToXml(MusicMessage musicMessage) { xstream.alias("xml", musicMessage.getClass()); return xstream.toXML(musicMessage); }  /** * 图文消息对象转换成xml *  * @param newsMessage 图文消息对象 * @return xml public static String newsMessageToXml(NewsMessage newsMessage) { xstream.alias("xml", newsMessage.getClass()); xstream.alias("item", new Article().getClass()); return xstream.toXML(newsMessage); } *//** * 扩展xstream,使其支持CDATA块 *  * @date 2013-05-19 */ private static XStream xstream = new XStream(new XppDriver() { public HierarchicalStreamWriter createWriter(Writer out) { return new PrettyPrintWriter(out) { // 对所有xml节点的转换都增加CDATA标记 boolean cdata = true; @SuppressWarnings("unchecked") public void startNode(String name, Class clazz) { super.startNode(name, clazz); } protected void writeText(QuickWriter writer, String text) { if (cdata) { writer.write("<![CDATA["); writer.write(text); writer.write("]]>"); } else { writer.write(text); } } }; } });
}

根据自己的需要进行修改。

运行完这段代码,有返回码,可以看到失败原因。

Java商户发送微信红包给用户相关推荐

  1. java发红包功能_java封装发送微信红包API功能。

    WeChatRedPack java封装发送微信红包API功能. 1.目前支持两种红包类型 普通 裂变 2.目前对微信红包api的发送增加了金额校验,暂时未对发送频率做限制,后期会使用redis进行限 ...

  2. 使用Java实现发送微信消息(附源码)_此程序在手再也不怕对象跟你闹了

    使用Java实现发送微信消息(附源码)_此程序在手再也不怕对象跟你闹了 此程序在手再也不怕女朋友跟你闹了!!!!自从有了女朋友比如:早安.晚安之类的问候语可不能断,但是也难免有时候会忘记那么该咋么办呢 ...

  3. java写的微信红包算法--田小江

    写了一个微信红包的算法,记录一下,后续争取再优化一下,大佬们也帮忙看一下. import java.util.HashMap; import java.util.Map;public class WX ...

  4. java运气红包_教你用java做个微信红包,自己做运气王!

    */public class RedPacketUtil { //微信红包的最大值和最小值,和最大红包金额系数 private static final float MINMUM = 0.01f; p ...

  5. java商户平台微信支付宝支付_微信支付/支付宝支付/银联支付,对比加总结(Java服务端)...

    今天来讲讲支付. 工作到现在,接入过好几个项目的支付,其中涉及到了微信支付.支付宝支付.银联支付. 三种支付的对接感受其实整体上大同小异.都遵循同一个流程: 1).商户APP向商户服务器请求生成订单 ...

  6. Java后端发送微信公众号模版消息自创建公用类

    微信公众号模版消息 肯定很多人都被微信的开放平台折磨,我也一样无一例外,也是根据公司的业务踩的坑,后来花时间研究了几个小时算是搞明白了. 下边不多说直接上详细说明和demo 首先打开微信开发平台 微信 ...

  7. 微信服务号+支付+php,微信服务号发送营销红包给关注用户步骤及部分php代码

    微信红包 一.前言: 这里主要讲述的是微信服务号给关注用户发送微信红包的相关内容:主要使用的业务场景有:1.业务员匆匆销员的奖励:2.现场会议互动抽奖:3.微信推广转发奖励:4.其他等等等,大开脑洞想 ...

  8. 微信红包高级接口JAVA实现

    看评论有网友说资源不全,因为是公司的代码,所以最近又独立个小项目独立出来,大家可以去 这里 下载代码,一起学习. 应用场景:        网站某一类型注册类型会员通过微信公众账号进入其账号中心时,可 ...

  9. java 开发微信红包

    1.接口文档 https://pay.weixin.qq.com/wiki/doc/api/cash_coupon.php?chapter=13_5 2.证书下载及证书安装 首先,商户调用微信红包接口 ...

最新文章

  1. Serverless Kubernetes:理想,现实与未来
  2. weblogic线程阻塞性能调优(图解)转
  3. oracle with 查询,oracle with 语句实现递归查询
  4. 大家都在说的分布式系统到底是什么
  5. 与访问您网站(或Blog)的朋友即时交流
  6. java arraylist 添加对象_如何在Java中将对象添加到ArrayList
  7. after、append和appendTo三个函数的区别
  8. 官网为啥这么喜欢IE和Flash?
  9. Babylongjs-纹理
  10. GWT RPC 开发
  11. 一般家用路由器买多大的合适_家用路由器选多少M(兆)的合适
  12. Translatium for Mac(Google在线翻译工具)
  13. mkv封装格式+ebml语法
  14. C语言中的移位运算乘法,C语言中 移位操作运算
  15. 最新UPX3.91-支持win64/PE-加/脱壳
  16. Android悬浮窗使用及窗口设置相关
  17. (学习收藏)招标过程中如何讲标?
  18. iTOL美化进化树实战:标签、枝修饰,分组着色
  19. Fundamentals of Power Electronics 中文版译文
  20. 再获品牌价值榜宴会家具类第一,DESON德尚持续赋能酒店

热门文章

  1. java poi2007_Java使用POI读取2007+版本PPT
  2. 在线期刊和论文投稿与评审系统
  3. Web前端面试题目及答案汇总
  4. NoteExpress与word 2016不能关联问题的解决
  5. 盒子滚动到底部有偏差 js_杭州连廊支座厂家销售,滚动铰支座_衡水安通
  6. void和int函数的区别
  7. 刘德华 -《声音》224Kbps VBR[MP3!]
  8. java 计算两个时间之间的间隔
  9. 中国彩瞳市场消费需求显著增长 天猫引领行业新趋势
  10. 【Git 教程系列第 27 篇】ssh: connect to host github.com port 22: Connection refused 的解决方案