java 调用微信红包接口
之前写的一个微信红包接口,用于公众号自动发送红包给用户,调用微信接口思路都是相同的,其他接口也可以使用这个方法。
-
jar包
方法涉及的java包过多,需要自行查询下载
-
方法
public final static int SEND_FAILED = 0; // 发放失败
public final static int SEND_SENDING = 1; // 发放中
public final static int SEND_SENT = 2; // 已发放
public final static int SEND_RECEIVED = 3; // 已领取
@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);//数据库获取商户平台配置,根据项目更改
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());
// 拼接请求参数
Map<String, String> paramap = new HashMap<String, String>();
// 随机字符串
String nonce_str = create_nonce_str();
paramap.put("nonce_str", nonce_str);
// 商户订单号
String orderid = createOrderId();
paramap.put("mch_billno", orderid);
// 商户号
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));
// 红包发放总人数
paramap.put("total_num", String.valueOf(1));
// 红包祝福语
paramap.put("wishing", "恭喜中奖");
// ip地址
paramap.put("client_ip", ip);
// 活动名称
paramap.put("act_name", act_name);
// 备注
paramap.put("remark", "红包");
// 场景id
paramap.put("scene_id", "PRODUCT_5");//查看微信开发者文档自行修改
// 签名
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);
// 向微信接口发起请求
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";
}
// 解析返回数据
try {
logger.info("ActivityWechatPay::xml response:" + xmlresponse);
Map<String, String> responsemap = doXMLParse(xmlresponse);
// 通信标识
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";
}
// 业务结果
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;
}
// 生成订单号
private String createOrderId() {
int machineId = 1;// 最大支持1-9个集群机器部署
int hashCodeV = UUID.randomUUID().toString().hashCode();
if (hashCodeV < 0) {
hashCodeV = -hashCodeV;
}
return machineId + String.format("%027d", hashCodeV);
}
// 将拼接的字符串转化为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
* 参数
* @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");
// 读取本机存放的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();
// 设置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严格是对内容和长度相匹配的。用法和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设置要解析的xml数据
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无法解析多层标签,单独加保护(红包查询时需要)
/*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;
}
以上是红包发放方法,由于发送可能被微信驳回等失败因素,建议根据各自需求写一个红包是否发送成功的查询的方法。
网友评论