前言
用戶邀請朋友購買公衆號產品,購買成功之後工會總好將給邀請人指定百分比的佣金,通過公衆號紅包的形式下發的邀請人;
此處整理將相關代碼都集中在了一起,真正開發中建議此寫法;
代碼中的相關參數如有不明白可參閱官方文檔
公衆號發送紅包
此功能實現需公衆號開通微信支付功能;
並採集微信商戶平臺信息,商戶號,支付祕鑰及證書申請下載
public class TextJkx {
private static final Logger LOGGER = LoggerFactory.getLogger(WinxinUtil.class);
// 發放紅包接口URL
private static final String REDENVELOPE_URL = "https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack";
// 證書路徑
private static final String CERTIFICATE_URL = "C:\\tuikuan\\cert\\apiclient_cert.p12";
// 商戶號
private static final String MCH_ID = "mch_id";
// 公衆號appid
private static final String APPID = "appid";
// 支付祕鑰
private static final String PAY_KEY = "pay_key";
public static void main(String[] args) throws Exception {
PayUtil payUtil = new PayUtil();
String uuid = UUIDUtil.getUUID();
String orderIdByTime = WinxinUtil.getOrderIdByTime();
// 活動標題
String sTitle = "";
payUtil.setMch_id(MCH_ID);
payUtil.setPayKey(PAY_KEY);
payUtil.setAppid(APPID);
payUtil.setNonce_str(uuid);
payUtil.setMch_billno(orderIdByTime);
// 公衆號名稱
payUtil.setSend_name("send_name");
// 紅包接收人openid
payUtil.setRe_openid("re_openid");
// 金額爲分,福利紅包爲分享信息金額的10%
BigDecimal bignum1 = new BigDecimal(String.valueOf(100));
BigDecimal bignum2 = new BigDecimal("100");
BigDecimal bignum3 = bignum1.multiply(bignum2); //乘法運算
int total_amount = bignum3.intValue() / 10;
payUtil.setTotal_amount(total_amount);
payUtil.setTotal_num(1);
payUtil.setWishing("感謝您參加XXX活動" + sTitle);
payUtil.setAct_name(sTitle);
payUtil.setRemark(Constants.RED_ENVELOPE_REMARK);
// 服務器ip
payUtil.setSpbill_create_ip("127.0.0.1");
// 給用戶發現金紅包
Map map = redEnvelope(payUtil);
if (StringUtils.equals(WXPayConstants.SUCCESS, map.get("result_code").toString()) && StringUtils.equals(WXPayConstants.SUCCESS, map.get("return_code").toString())) {
// 紅包派發成功,業務處理邏輯 TODO
} else {
// 紅包派發失敗
}
}
/**
* @Description: 給用戶發現金紅包
* @Author: Mr.Jkx
* @date: 2019/11/12 11:06
* 參考鏈接:https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_4&index=3
*/
public static Map redEnvelope(PayUtil payUtil) throws Exception {
//生成的隨機字符串
String stringA = "act_name=" + payUtil.getAct_name()
+ "&client_ip=" + payUtil.getSpbill_create_ip()
+ "&mch_billno=" + payUtil.getMch_billno()
+ "&mch_id=" + payUtil.getMch_id()
+ "&nonce_str=" + payUtil.getNonce_str()
+ "&re_openid=" + payUtil.getRe_openid()
+ "&remark=" + payUtil.getRemark()
+ "&send_name=" + payUtil.getSend_name()
+ "&total_amount=" + payUtil.getTotal_amount()
+ "&total_num=" + payUtil.getTotal_num()
+ "&wishing=" + payUtil.getWishing()
+ "&wxappid=" + payUtil.getAppid()
+ "&key=" + payUtil.getPayKey();
String sign = Md5Util.md5(stringA).toUpperCase();
String xml = "<xml>" +
" <act_name>" + payUtil.getAct_name() + "</act_name>" +
" <client_ip>" + payUtil.getSpbill_create_ip() + "</client_ip>" +
" <mch_billno>" + payUtil.getMch_billno() + "</mch_billno>" +
" <mch_id>" + payUtil.getMch_id() + "</mch_id>" +
" <nonce_str>" + payUtil.getNonce_str() + "</nonce_str>" +
" <re_openid>" + payUtil.getRe_openid() + "</re_openid>" +
" <remark>" + payUtil.getRemark() + "</remark>" +
" <send_name>" + payUtil.getSend_name() + "</send_name>" +
" <total_amount>" + payUtil.getTotal_amount() + "</total_amount>" +
" <total_num>" + payUtil.getTotal_num() + "</total_num>" +
" <wishing>" + payUtil.getWishing() + "</wishing>" +
" <wxappid>" + payUtil.getAppid() + "</wxappid>" +
" <sign>" + sign + "</sign>" +
"</xml> ";
LOGGER.info("----現金紅包-----請求XML數據:{}", xml);
String result = payOfCertificate(REDENVELOPE_URL, xml);
// 將解析結果存儲在HashMap中
Map map = doXMLParse(result);
LOGGER.info("----現金紅包-----回執數據:{}", map);
return map;
}
/**
* @Description: 加載證書 發送請求
* @Author: Mr.Jkx
* @Date: 2019/4/10 10:06
*/
public static String payOfCertificate(String url, String data) throws Exception {
KeyStore keyStore = KeyStore.getInstance("PKCS12");
FileInputStream is = new FileInputStream(new File(CERTIFICATE_URL));
try {
keyStore.load(is, MCH_ID.toCharArray());
} finally {
is.close();
}
SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, MCH_ID.toCharArray()).build();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
sslcontext,
new String[]{"TLSv1"},
null,
SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER
);
CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
try {
HttpPost httpost = new HttpPost(url); // 設置響應頭信息
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"));
CloseableHttpResponse response = httpclient.execute(httpost);
try {
HttpEntity entity = response.getEntity();
String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");
EntityUtils.consume(entity);
return jsonStr;
} finally {
response.close();
}
} finally {
httpclient.close();
}
}
/**
* 解析xml,返回第一級元素鍵值對。如果第一級元素有子節點,則此節點的值是子節點的xml數據。
*
* @param strxml
* @return
*/
public static Map doXMLParse(String strxml) throws Exception {
if (null == strxml || "".equals(strxml)) {
return null;
}
Map m = new HashMap();
InputStream in = String2Inputstream(strxml);
SAXBuilder builder = new SAXBuilder();
Document doc = builder.build(in);
Element root = doc.getRootElement();
List list = root.getChildren();
Iterator it = list.iterator();
while (it.hasNext()) {
Element e = (Element) it.next();
String k = e.getName();
String v = "";
List children = e.getChildren();
if (children.isEmpty()) {
v = e.getTextNormalize();
} else {
v = getChildrenText(children);
}
m.put(k, v);
}
//關閉流
in.close();
return m;
}
/**
* 獲取子結點的xml
*
* @param children
* @return String
*/
public static String getChildrenText(List children) {
StringBuffer sb = new StringBuffer();
if (!children.isEmpty()) {
Iterator it = children.iterator();
while (it.hasNext()) {
Element e = (Element) it.next();
String name = e.getName();
String value = e.getTextNormalize();
List list = e.getChildren();
sb.append("<" + name + ">");
if (!list.isEmpty()) {
sb.append(getChildrenText(list));
}
sb.append(value);
sb.append("</" + name + ">");
}
}
return sb.toString();
}
public static InputStream String2Inputstream(String str) {
return new ByteArrayInputStream(str.getBytes());
}
}