title: 微信红包发送关键代码
date: 2019-09-21 17:30:13
tags: 微信
微信红包发送主要涉及服务号获取用户openid、发送红包请求两块内容,本文展示这两部分的关键代码。
获取用户openid
1、服务号设置内容链接
笔者维护的服务号使用自定义菜单跳转网页的方式,网页链接格式按照微信公众号开发文档中归档的格式即可,如果只需要获得openid的则按照snsapi_base的格式即可。
2、获取网页授权access_token与openid
获取网页授权access_token部分代码:
// 拼接请求地址
String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
url = url.replace("APPID", appId);
url = url.replace("SECRET", appSecret);
url = url.replace("CODE", code);
Map<String, Object> map = new HashMap<String, Object>();
ObjectMapper mapper = new ObjectMapper();
// 获取网页授权凭证
String result = new WxUtil().getSendResult(url);//该方法发送get请求
try {
result = new String(result.getBytes("GBK"), "UTF-8");
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
}
System.out.println("result=" + result);
正常获取的json数据格式如下,其中openid 便是用户在这个服务号下的唯一编号,之后便可以与数据库中的用户进行绑定:
{
"access_token":"ACCESS_TOKEN",
"expires_in":7200,
"refresh_token":"REFRESH_TOKEN",
"openid":"OPENID",
"scope":"SCOPE"
}
发送红包
1、获得签名
发送红包请求中需要包含签名,具体生成方法请参考微信商户签名生成方法文档。这个步骤很容易出现错误,比如数值为空的参数也参与了签名算法、key值为空等情况,可参考签名校验工具进行验证。以下为笔者生成签名的部分代码:
//String param = "act_name=ACT_NAME&client_ip=CLIENT_IP&mch_billno=MCH_BILLNO&mch_id=MCH_ID&nonce_str=NONCE_STR&re_openid=RE_OPENID&remark=REMARK&scene_id=SCENE_ID&send_name=SEND_NAME&total_amount=TOTAL_AMOUNT&total_num=TOTAL_NUM&wishing=WISHING&wxappid=WXAPPID&key=KEY";
//不添加场景参数
String param = "act_name=ACT_NAME&client_ip=CLIENT_IP&mch_billno=MCH_BILLNO&mch_id=MCH_ID&nonce_str=NONCE_STR&re_openid=RE_OPENID&remark=REMARK&send_name=SEND_NAME&total_amount=TOTAL_AMOUNT&total_num=TOTAL_NUM&wishing=WISHING&wxappid=WXAPPID&key=KEY";
String act_name = str.get(map, "act_name");//str为笔者系统里的一个工具类
String client_ip = str.get(map, "client_ip");
String mch_billno = str.get(map, "mch_billno");
String mch_id = str.get(map, "mch_id");
String nonce_str = str.get(map, "nonce_str");
String re_openid = str.get(map, "re_openid");
String remark = str.get(map, "remark");
String scene_id = str.get(map, "scene_id");
String send_name = str.get(map, "send_name");
String sign = str.get(map, "sign");
String total_amount = str.get(map, "total_amount");
String total_num = str.get(map, "total_num");
String wishing = str.get(map, "wishing");
String wxappid = str.get(map, "wxappid");
param = param.replace("ACT_NAME", act_name)
.replace("CLIENT_IP", client_ip)
.replace("MCH_BILLNO", mch_billno)
.replace("MCH_ID", mch_id)
.replace("NONCE_STR", nonce_str)
.replace("RE_OPENID", re_openid)
.replace("REMARK", remark)
.replace("SCENE_ID", scene_id)
.replace("SEND_NAME", send_name)
.replace("SIGN", sign)
.replace("TOTAL_AMOUNT", total_amount)
.replace("TOTAL_NUM", total_num)
.replace("WISHING", wishing)
.replace("WXAPPID", wxappid)
.replace("KEY", key);
//System.out.println(param);
return new MD5().MD5Encode(param).toUpperCase();
2、发送红包请求
发送请求请按照微信红包发送文档的规定进行发送,请求方式为post,必须得携带api证书进行发送,以下为部分发送代码:
public String sendRedPack(Map<String, Object> packInfo) throws Exception {
String result = "";
String url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack";
String urlparams = sendRedPackParams();
Set<String> set = packInfo.keySet(); //取出所有的key值
for (String key:set) {
String value = (String)packInfo.get(key);
urlparams = urlparams.replace(key.toUpperCase(), value);
//log.debug("key="+key+" value="+value);
}
log.debug("urlparams=" + urlparams);
KeyStore keyStore = KeyStore.getInstance("PKCS12");
FileInputStream instream = new FileInputStream(new File("apiclient_cert.p12"));
try {
keyStore.load(instream, SzdjjhConst.getMch_id().toCharArray());
} finally {
instream.close();
}
// Trust own CA and all self-signed certs
SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, SzdjjhConst.getMch_id().toCharArray()).build();
// Allow TLSv1 protocol only
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1" }, null,
SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
try {
HttpPost httpPost = new HttpPost(url);
log.debug("executing request" + httpPost.getRequestLine());
//中文不成功是因为没加编码
StringEntity myEntity = new StringEntity(urlparams, "utf-8");
httpPost.setEntity(myEntity);
CloseableHttpResponse response = httpclient.execute(httpPost);
try {
HttpEntity entity1 = response.getEntity();
log.debug("----------------------------------------");
log.debug(response.getStatusLine());
if (entity1 != null) {
log.debug("Response content length: " + entity1.getContentLength());
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(entity1.getContent()));
String text;
while ((text = bufferedReader.readLine()) != null) {
result += text;
/*result += new String(text.getBytes("gbk"), "utf-8");
log.debug(new String(text.getBytes("gbk"), "utf-8"));*/
}
}
EntityUtils.consume(entity1);
} catch (Exception e) {
e.printStackTrace();
} finally {
response.close();
}
} finally {
httpclient.close();
}
return result;
}
public static String sendRedPackParams(){
String xmlParams = " <xml>"
+ "<sign>SIGN</sign>"
+ "<mch_billno>MCH_BILLNO</mch_billno>"
+ "<mch_id>MCH_ID</mch_id>"
+ "<wxappid>WXAPPID</wxappid>"
+ "<send_name>SEND_NAME</send_name>"
+ "<re_openid>RE_OPENID</re_openid>"
+ "<total_amount>TOTAL_AMOUNT</total_amount>"
+ "<total_num>TOTAL_NUM</total_num>"
+ "<wishing>WISHING</wishing>"
+ "<client_ip>CLIENT_IP</client_ip>"
+ "<act_name>ACT_NAME</act_name>"
+ "<remark>REMARK</remark>"
//+ "<scene_id>SCENE_ID</scene_id>"
+ "<nonce_str>NONCE_STR</nonce_str>"
+ "</xml>";
return xmlParams;
}
附上红包发送成功的示例: