java 調(diào)用微信紅包接口
之前寫的一個(gè)微信紅包接口狐胎,用于公眾號(hào)自動(dòng)發(fā)送紅包給用戶,調(diào)用微信接口思路都是相同的歌馍,其他接口也可以使用這個(gè)方法。
-
jar包
方法涉及的java包過多晕鹊,需要自行查詢下載
-
方法
public final static int SEND_FAILED = 0; // 發(fā)放失敗
public final static int SEND_SENDING = 1; // 發(fā)放中
public final static int SEND_SENT = 2; // 已發(fā)放
public final static int SEND_RECEIVED = 3; // 已領(lǐng)取
@Autowired
private ConfigMgrService configMgrService;
@Autowired
private WXpayorderService wXpayorderService;
// 紅包接口
public String do_pay(String openid, int price ,String act_name) {
logger.info("WechatPay::do_pay called");
if (openid == null) {
logger.error("WechatPay::openid is null");
return "fail";
}
Map wx_pay_config = configMgrService.queryWxConfigByGameid(1);//數(shù)據(jù)庫獲取商戶平臺(tái)配置松却,根據(jù)項(xiàng)目更改
if (wx_pay_config == null) {
logger.error("WechatPay::wx_pay_config is null");
return "fail";
}
String ip = wx_pay_config.get("client_ip").toString();
int game_id = Integer.parseInt(wx_pay_config.get("game_id").toString());
// 拼接請求參數(shù)
Map<String, String> paramap = new HashMap<String, String>();
// 隨機(jī)字符串
String nonce_str = create_nonce_str();
paramap.put("nonce_str", nonce_str);
// 商戶訂單號(hào)
String orderid = createOrderId();
paramap.put("mch_billno", orderid);
// 商戶號(hào)
paramap.put("mch_id", wx_pay_config.get("mch_id").toString());
// appid
paramap.put("wxappid", wx_pay_config.get("app_id").toString());
// 商戶名稱
paramap.put("send_name", wx_pay_config.get("send_name").toString());
// 用戶openid
paramap.put("re_openid", openid);
// 付款金額
paramap.put("total_amount", String.valueOf(price));
// 紅包發(fā)放總?cè)藬?shù)
paramap.put("total_num", String.valueOf(1));
// 紅包祝福語
paramap.put("wishing", "恭喜中獎(jiǎng)");
// ip地址
paramap.put("client_ip", ip);
// 活動(dòng)名稱
paramap.put("act_name", act_name);
// 備注
paramap.put("remark", "紅包");
// 場景id
paramap.put("scene_id", "PRODUCT_5");//查看微信開發(fā)者文檔自行修改
// 簽名
try {
String paysign = getPayCustomSign(paramap, wx_pay_config.get("key")
.toString()); // todo get sign
// key
paramap.put("sign", paysign);
} catch (Exception e) {
logger.error(e.toString());
return "fail";
}
String xml = ArrayToXml(paramap);
// 向微信接口發(fā)起請求
String url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack";
String xmlresponse = "";
try {
xmlresponse = sendRedEnvelope(url, xml);
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
logger.error("WechatPay::" + e1);
}
// String xmlresponse = dopost(url, xml);
if (xmlresponse.isEmpty()) {
logger.error("ActivityWechatPay::dopost failed");
return "fail";
}
// 解析返回?cái)?shù)據(jù)
try {
logger.info("ActivityWechatPay::xml response:" + xmlresponse);
Map<String, String> responsemap = doXMLParse(xmlresponse);
// 通信標(biāo)識(shí)
String returncode = responsemap.get("return_code");
if (!returncode.equals("SUCCESS")) {
logger.error("WechatPay::wechat return err:" + returncode
+ ",return_msg:" + responsemap.get("return_msg"));
return "fail";
}
// 業(yè)務(wù)結(jié)果
returncode = responsemap.get("result_code");
if (!returncode.equals("SUCCESS")) {
logger.error("WechatPay::wechat return err:"
+ responsemap.get("err_code") + ",err_code_des:"
+ responsemap.get("err_code_des"));
return "fail";
}
} catch (XmlPullParserException e) {
logger.error(e.toString());
} catch (IOException ioe) {
logger.error(ioe.toString());
}
return "success";
}
// 生成簽名
private String getPayCustomSign(Map<String, String> bizObj, String key)
throws Exception {
String bizString = FormatBizQueryParaMap(bizObj, false);
// logger.info(bizString);
return sign(bizString, key);
}
private String FormatBizQueryParaMap(Map<String, String> paraMap,
boolean urlencode) throws Exception {
String buff = "";
try {
List<Map.Entry<String, String>> infoIds = new ArrayList<Entry<String, String>>(
paraMap.entrySet());
Collections.sort(infoIds,
new Comparator<Map.Entry<String, String>>() {
public int compare(Map.Entry<String, String> o1,
Map.Entry<String, String> o2) {
return (o1.getKey()).toString().compareTo(
o2.getKey());
}
});
for (int i = 0; i < infoIds.size(); i++) {
Map.Entry<String, String> item = infoIds.get(i);
// System.out.println(item.getKey());
if (item.getKey() != "") {
String key = item.getKey();
String val = item.getValue();
if (urlencode) {
val = URLEncoder.encode(val, "utf-8");
}
buff += key + "=" + val + "&";
}
}
if (buff.isEmpty() == false) {
buff = buff.substring(0, buff.length() - 1);
}
} catch (Exception e) {
throw new Exception(e.getMessage());
}
return buff;
}
// 生成訂單號(hào)
private String createOrderId() {
int machineId = 1;// 最大支持1-9個(gè)集群機(jī)器部署
int hashCodeV = UUID.randomUUID().toString().hashCode();
if (hashCodeV < 0) {
hashCodeV = -hashCodeV;
}
return machineId + String.format("%027d", hashCodeV);
}
// 將拼接的字符串轉(zhuǎn)化為xml文件
public String ArrayToXml(Map<String, String> arr) {
String xml = "<xml>";
Iterator<Entry<String, String>> iter = arr.entrySet().iterator();
while (iter.hasNext()) {
Entry<String, String> entry = iter.next();
String key = entry.getKey();
String val = entry.getValue();
xml += "<" + key + ">" + val + "</" + key + ">";
}
xml += "</xml>";
return xml;
}
/**
* 帶證書httpPost請求
*
* @param url
* 接口地址
* @param param
* 參數(shù)
* @return
* @throws Exception
*/
public static String sendRedEnvelope(String url, String param)
throws Exception {
// PKCS12的密碼
String PKCS12 = "";
// 指定讀取證書格式為PKCS12
KeyStore keyStore = KeyStore.getInstance("PKCS12");
InputStream instream = WechatPayMgr.class
.getResourceAsStream("apiclient_cert.p12");
// 讀取本機(jī)存放的PKCS12證書文件
if (instream == null) {
instream = WechatPayMgr.class.getClassLoader().getResourceAsStream(
"apiclient_cert.p12");
}
if (instream == null) {
instream = WechatPayMgr.class.getClassLoader()
.getSystemResourceAsStream("apiclient_cert.p12");
}
try {
// 指定PKCS12的密碼
keyStore.load(instream, PKCS12.toCharArray());
} finally {
instream.close();
}
// 指定TLS版本
SSLContext sslcontext = SSLContexts.custom()
.loadKeyMaterial(keyStore, PKCS12.toCharArray()).build();
// 設(shè)置httpclient的SSLSocketFactory
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
sslcontext, new String[] { "TLSv1" }, null,
SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
CloseableHttpClient httpclient = HttpClients.custom()
.setSSLSocketFactory(sslsf).build();
StringBuffer stringBuffer = new StringBuffer();
try {
HttpPost httpPost = new HttpPost(url);
InputStream is = new ByteArrayInputStream(param.getBytes("UTF-8"));
// InputStreamEntity嚴(yán)格是對內(nèi)容和長度相匹配的暴浦。用法和BasicHttpEntity類似
InputStreamEntity inputStreamEntity = new InputStreamEntity(is,
is.available());
httpPost.setEntity(inputStreamEntity);
CloseableHttpResponse response = httpclient.execute(httpPost);
try {
HttpEntity entity = response.getEntity();
BufferedReader reader = new BufferedReader(
new InputStreamReader(entity.getContent(), "UTF-8"));
String inputLine;
while ((inputLine = reader.readLine()) != null) {
stringBuffer.append(inputLine);
}
} finally {
response.close();
}
} finally {
httpclient.close();
}
return stringBuffer.toString();
}
// 解析xml
private Map<String, String> doXMLParse(String xml)
throws XmlPullParserException, IOException {
InputStream inputStream = new ByteArrayInputStream(xml.getBytes());
Map<String, String> map = null;
XmlPullParserFactory dbf = XmlPullParserFactory.newInstance();
String FEATURE = null;
FEATURE = "http://xml.org/sax/features/external-general-entities";
dbf.setFeature(FEATURE, false);
FEATURE = "http://xml.org/sax/features/external-parameter-entities";
dbf.setFeature(FEATURE, false);
FEATURE = "http://apache.org/xml/features/nonvalidating/load-external-dtd";
dbf.setFeature(FEATURE, false);
XmlPullParser pullParser = dbf.newPullParser();
pullParser.setInput(inputStream, "UTF-8"); // 為xml設(shè)置要解析的xml數(shù)據(jù)
int eventType = pullParser.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
switch (eventType) {
case XmlPullParser.START_DOCUMENT:
map = new HashMap<String, String>();
break;
case XmlPullParser.START_TAG:
String key = pullParser.getName();
if (key.equals("xml"))
break;
// xml無法解析多層標(biāo)簽,單獨(dú)加保護(hù)(紅包查詢時(shí)需要)
/*if (key.equals("hblist")) {
pullParser.next();
pullParser.next();
key = pullParser.getName();
}*/
String value = pullParser.nextText();
map.put(key, value);
break;
case XmlPullParser.END_TAG:
break;
}
eventType = pullParser.next();
}
return map;
}
以上是紅包發(fā)放方法晓锻,由于發(fā)送可能被微信駁回等失敗因素歌焦,建議根據(jù)各自需求寫一個(gè)紅包是否發(fā)送成功的查詢的方法。