现金红包,是微信支付商户平台提供的营销工具之一,上线以来深受广大商户与用户的喜爱。商户可以通过公众号或者服务通知向用户发放现金红包。用户领取红包后,资金到达用户微信支付零钱账户,和零钱包的其他资金有一样的使用出口;若用户未领取,资金将会在24小时后退回商户的微信支付账户中。
代码示例
/**
* 微信现金红包
*
* @return 微信接口响应
* @throws Exception 异常
*/
public String red() throws Exception {
Map<String, Object> map = new HashMap<>();
// 随机字符串
map.put("nonce_str", System.currentTimeMillis() + String.valueOf(new java.util.Random().nextInt(900) + 100));
// 商户订单
map.put("mch_billno", getOrderNo());
// 商户号
map.put("mch_id", "商户号");
// 公众号appid
map.put("wxappid", "公众号appid");
// 商户名称
map.put("send_name", "商户名称");
// 用户openid
map.put("re_openid", "用户openid");
// 付款金额 单位分
map.put("total_amount", 100);
// 红包发送总人数
map.put("total_num", 1);
// 红包祝福语
map.put("wishing", "红包祝福语");
// 发送端ip地址
map.put("client_ip", "发送端ip地址");
// 活动名称
map.put("act_name", "活动名称");
// 备注
map.put("remark", "备注");
/*
发放红包使用场景,红包金额大于200或者小于1元时必传
PRODUCT_1:商品促销
PRODUCT_2:抽奖
PRODUCT_3:虚拟物品兑奖
PRODUCT_4:企业内部福利
PRODUCT_5:渠道分润
PRODUCT_6:保险回馈
PRODUCT_7:彩票派奖
PRODUCT_8:税务刮奖
*/
map.put("scene_id", "PRODUCT_2");
// 签名
map.put("sign", createSign(map));
return doSendMoney(createXML(map));
}
/**
* 发送红包
*
* @param data 请求参数
* @return 微信接口响应
* @throws Exception 异常
*/
String doSendMoney(String data) throws Exception {
KeyStore keyStore = KeyStore.getInstance("PKCS12");
// p12文件路径
try (FileInputStream instream = new FileInputStream(new File("D:\\apiclient_cert.p12"))) {
// 默认密码为微信支付商户号
keyStore.load(instream, "密码".toCharArray());
}
// Trust own CA and all self-signed certs
SSLContext sslcontext = SSLContexts.custom()
.loadKeyMaterial(keyStore, "商户号".toCharArray())
.build();
// Allow TLSv1 protocol only
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[]{"TLSv1"}, null,
SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
try (CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build()) {
HttpPost httpost = new HttpPost("https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack");
httpost.addHeader("Connection", "keep-alive");
httpost.addHeader("Accept", "*/*");
httpost.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
httpost.addHeader("Host", "api.mch.weixin.qq.com");
httpost.addHeader("X-Requested-With", "XMLHttpRequest");
httpost.addHeader("Cache-Control", "max-age=0");
httpost.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");
httpost.setEntity(new StringEntity(data, "UTF-8"));
try (CloseableHttpResponse response = httpclient.execute(httpost)) {
HttpEntity entity = response.getEntity();
String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");
EntityUtils.consume(entity);
return jsonStr;
}
}
}
/**
* 创建签名所需要的参数xml格式
*
* @param map Map
* @return xml
*/
public String createXML(Map<String, Object> map) {
StringBuilder xml = new StringBuilder("<xml>");
Set<String> set = map.keySet();
for (String str : set) {
xml.append("<").append(str).append(">").append("<![CDATA[").append(map.get(str)).append("]]>").append("</").append(str).append(">");
}
xml.append("</xml>");
return xml.toString();
}
/**
* 创建签名
*
* @param map 参数Map
* @return 签名
*/
String createSign(Map<String, Object> map) {
SortedMap<String, String> packageParams = new TreeMap<>();
for (Map.Entry<String, Object> m : map.entrySet()) {
packageParams.put(m.getKey(), m.getValue().toString());
}
StringBuilder sb = new StringBuilder();
Set<?> es = packageParams.entrySet();
for (Object e : es) {
Map.Entry entry = (Map.Entry) e;
String k = (String) entry.getKey();
String v = (String) entry.getValue();
if (!StringUtils.isEmpty(v) && !"sign".equals(k) && !"key".equals(k))
sb.append(k).append("=").append(v).append("&");
}
// API密钥
sb.append("key=").append("API密钥");
return md5(sb.toString()).toUpperCase();
}
/**
* md5加密
*
* @param string 被加密数据
* @return 加密数据
*/
String md5(String string) {
try {
byte[] digest = MessageDigest.getInstance("MD5").digest(string.getBytes(StandardCharsets.UTF_8));
StringBuilder buf = new StringBuilder(digest.length * 2);
for (byte b : digest) {
if ((b & 0xFF) < 16) buf.append("0");
buf.append(Long.toString((b & 0xFF), 16));
}
return buf.toString();
} catch (NoSuchAlgorithmException e) {
return null;
}
}
/**
* 生成商户流水订单号
*
* @return 订单号
*/
public static String getOrderNo() {
StringBuilder order = new StringBuilder("商户号" + new SimpleDateFormat("yyyyMMdd").format(new Date()));
Random r = new Random();
for (int i = 0; i < 10; i++) {
order.append(r.nextInt(9));
}
return order.toString();
}
成功响应示例
<xml>
<return_code>
<![CDATA[SUCCESS]]>
</return_code>
<return_msg>
<![CDATA[发放成功]]>
</return_msg>
<result_code>
<![CDATA[SUCCESS]]>
</result_code>
<err_code>
<![CDATA[SUCCESS]]>
</err_code>
<err_code_des>
<![CDATA[发放成功]]>
</err_code_des>
</xml>
常见问题
微信接口返回ip没有权限之类的话 是因为添加ip请求接口权限,添加步骤和上一篇文章的类似