現(xiàn)金紅包堂飞,是微信支付商戶平臺提供的營銷工具之一圃泡,上線以來深受廣大商戶與用戶的喜愛。商戶可以通過公眾號或者服務通知向用戶發(fā)放現(xiàn)金紅包蛙讥。用戶領取紅包后薪丁,資金到達用戶微信支付零錢賬戶遇西,和零錢包的其他資金有一樣的使用出口;若用戶未領取严嗜,資金將會在24小時后退回商戶的微信支付賬戶中粱檀。
代碼示例
/**
* 微信現(xiàn)金紅包
*
* @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);
// 紅包發(fā)送總?cè)藬?shù)
map.put("total_num", 1);
// 紅包祝福語
map.put("wishing", "紅包祝福語");
// 發(fā)送端ip地址
map.put("client_ip", "發(fā)送端ip地址");
// 活動名稱
map.put("act_name", "活動名稱");
// 備注
map.put("remark", "備注");
/*
發(fā)放紅包使用場景,紅包金額大于200或者小于1元時必傳
PRODUCT_1:商品促銷
PRODUCT_2:抽獎
PRODUCT_3:虛擬物品兌獎
PRODUCT_4:企業(yè)內(nèi)部福利
PRODUCT_5:渠道分潤
PRODUCT_6:保險回饋
PRODUCT_7:彩票派獎
PRODUCT_8:稅務刮獎
*/
map.put("scene_id", "PRODUCT_2");
// 簽名
map.put("sign", createSign(map));
return doSendMoney(createXML(map));
}
/**
* 發(fā)送紅包
*
* @param data 請求參數(shù)
* @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;
}
}
}
/**
* 創(chuàng)建簽名所需要的參數(shù)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();
}
/**
* 創(chuàng)建簽名
*
* @param map 參數(shù)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 被加密數(shù)據(jù)
* @return 加密數(shù)據(jù)
*/
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[發(fā)放成功]]>
</return_msg>
<result_code>
<![CDATA[SUCCESS]]>
</result_code>
<err_code>
<![CDATA[SUCCESS]]>
</err_code>
<err_code_des>
<![CDATA[發(fā)放成功]]>
</err_code_des>
</xml>
常見問題
微信接口返回ip沒有權限之類的話 是因為添加ip請求接口權限漫玄,添加步驟和上一篇文章的類似