微信公众号统一下单接口对接代码
1.工具类utils
TrustManager.java
package com.weixin.common.util;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.X509TrustManager;
/**
*
* @ClassName: TrustManager
* @Description: 证书信任管理器(用于https请求)
* @author Administrator
* @date 2015-7-8 上午11:42:27
*
*/
public class TrustManager implements X509TrustManager {
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
WeChatErrorCode.java
package com.weixin.common.util;
import java.util.HashMap;
import java.util.Map;
/**
*
* @ClassName: WeChatErrorCode
* @Description:封装错误类型集合
* @author Administrator
* @date 2015-7-8 上午11:44:05
*
*/
@SuppressWarnings("unchecked")
public class WeChatErrorCode {
public static final Map ERRORCODE=new HashMap<Integer,String>();
static{
ERRORCODE.put(-1,"系统繁忙");
ERRORCODE.put(0,"请求成功");
ERRORCODE.put(40001,"获取access_token时AppSecret错误,或者access_token无效");
ERRORCODE.put(40002,"不合法的凭证类型");
ERRORCODE.put(40003,"不合法的OpenID");
ERRORCODE.put(40004,"不合法的媒体文件类型");
ERRORCODE.put(40005,"不合法的文件类型");
ERRORCODE.put(40006,"不合法的文件大小");
ERRORCODE.put(40007,"不合法的媒体文件id");
ERRORCODE.put(40008,"不合法的消息类型");
ERRORCODE.put(40009,"不合法的图片文件大小");
ERRORCODE.put(40010,"不合法的语音文件大小");
ERRORCODE.put(40011,"不合法的视频文件大小");
ERRORCODE.put(40012,"不合法的缩略图文件大小");
ERRORCODE.put(40013,"不合法的APPID");
ERRORCODE.put(40014,"不合法的access_token");
ERRORCODE.put(40015,"不合法的菜单类型");
ERRORCODE.put(40016,"不合法的按钮个数");
ERRORCODE.put(40017,"不合法的按钮个数");
ERRORCODE.put(40018,"不合法的按钮名字长度");
ERRORCODE.put(40019,"不合法的按钮KEY长度");
ERRORCODE.put(40020,"不合法的按钮URL长度");
ERRORCODE.put(40021,"不合法的菜单版本号");
ERRORCODE.put(40022,"不合法的子菜单级数");
ERRORCODE.put(40023,"不合法的子菜单按钮个数");
ERRORCODE.put(40024,"不合法的子菜单按钮类型");
ERRORCODE.put(40025,"不合法的子菜单按钮名字长度");
ERRORCODE.put(40026,"不合法的子菜单按钮KEY长度");
ERRORCODE.put(40027,"不合法的子菜单按钮URL长度");
ERRORCODE.put(40028,"不合法的自定义菜单使用用户");
ERRORCODE.put(40029,"不合法的oauth_code");
ERRORCODE.put(40030,"不合法的refresh_token");
ERRORCODE.put(40031,"不合法的openid列表");
ERRORCODE.put(40032,"不合法的openid列表长度");
ERRORCODE.put(40033,"不合法的请求字符,不能包含\\uxxxx格式的字符");
ERRORCODE.put(40035,"不合法的参数");
ERRORCODE.put(40038,"不合法的请求格式");
ERRORCODE.put(40039,"不合法的URL长度");
ERRORCODE.put(40050,"不合法的分组id");
ERRORCODE.put(40051,"分组名字不合法");
ERRORCODE.put(41001,"缺少access_token参数");
ERRORCODE.put(41002,"缺少appid参数");
ERRORCODE.put(41003,"缺少refresh_token参数");
ERRORCODE.put(41004,"缺少secret参数");
ERRORCODE.put(41005,"缺少多媒体文件数据");
ERRORCODE.put(41006,"缺少media_id参数");
ERRORCODE.put(41007,"缺少子菜单数据");
ERRORCODE.put(41008,"缺少oauth code");
ERRORCODE.put(41009,"缺少openid");
ERRORCODE.put(42001,"access_token超时");
ERRORCODE.put(42002,"refresh_token超时");
ERRORCODE.put(42003,"oauth_code超时");
ERRORCODE.put(43001,"需要GET请求");
ERRORCODE.put(43002,"需要POST请求");
ERRORCODE.put(43003,"需要HTTPS请求");
ERRORCODE.put(43004,"需要接收者关注");
ERRORCODE.put(43005,"需要好友关系");
ERRORCODE.put(44001,"多媒体文件为空");
ERRORCODE.put(44002,"POST的数据包为空");
ERRORCODE.put(44003,"图文消息内容为空");
ERRORCODE.put(44004,"文本消息内容为空");
ERRORCODE.put(45001,"多媒体文件大小超过限制");
ERRORCODE.put(45002,"消息内容超过限制");
ERRORCODE.put(45003,"标题字段超过限制");
ERRORCODE.put(45004,"描述字段超过限制");
ERRORCODE.put(45005,"链接字段超过限制");
ERRORCODE.put(45006,"图片链接字段超过限制");
ERRORCODE.put(45007,"语音播放时间超过限制");
ERRORCODE.put(45008,"图文消息超过限制");
ERRORCODE.put(45009,"接口调用超过限制");
ERRORCODE.put(45010,"创建菜单个数超过限制");
ERRORCODE.put(45015,"回复时间超过限制");
ERRORCODE.put(45016,"系统分组,不允许修改");
ERRORCODE.put(45017,"分组名字过长");
ERRORCODE.put(45018,"分组数量超过上限");
ERRORCODE.put(46001,"不存在媒体数据");
ERRORCODE.put(46002,"不存在的菜单版本");
ERRORCODE.put(46003,"不存在的菜单数据");
ERRORCODE.put(46004,"不存在的用户");
ERRORCODE.put(47001,"解析JSON/XML内容错误");
ERRORCODE.put(48001,"api功能未授权");
ERRORCODE.put(50001,"用户未授权该api");
}
}
WeChatUtil.java
package com.weixin.common.util;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.URL;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.servlet.http.HttpServletRequest;
import org.apache.http.entity.StringEntity;
import net.sf.json.JSONObject;
import com.weixin.common.wxpojo.AccessToken;
import com.weixin.common.wxpojo.WebAccessToken;
import com.weixin.pojo.WxUser;
/**
*
* @ClassName: WeChatUtil
* @Description: 微信开发工具类
* @author Administrator
* @date 2015-7-8 上午11:50:24
*
*/
public class WeChatUtil {
/**
*
* @Title: httpRequest
* @Description: 访问微信接口
* @author Administrator
* @date 2015-7-8 下午03:34:12
* @param requestUrl 访问路径
* @param requestMethod 访问类型 POST OR GET
* @param outputStr 要提交的数据,没有设置为null
* @return 返回数据 json格式
*/
public static JSONObject httpRequest(String requestUrl,String requestMethod, String outputStr) {
JSONObject jsonObject = null;
StringBuffer buffer = new StringBuffer();
try {
// 创建SSLContext对象,并使用我们指定的信任管理器初始化
TrustManager[] tm = { new TrustManager() };
SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
sslContext.init(null, tm, new java.security.SecureRandom());
// 从上述SSLContext对象中得到SSLSocketFactory对象
SSLSocketFactory ssf = sslContext.getSocketFactory();
URL url = new URL(requestUrl);
HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
httpUrlConn.setSSLSocketFactory(ssf);
httpUrlConn.setDoOutput(true);
httpUrlConn.setDoInput(true);
httpUrlConn.setUseCaches(false);
// 设置请求方式(GET/POST)
httpUrlConn.setRequestMethod(requestMethod);
if ("GET".equalsIgnoreCase(requestMethod))
httpUrlConn.connect();
// 当有数据需要提交时
if (null != outputStr) {
OutputStream outputStream = httpUrlConn.getOutputStream();
// 注意编码格式,防止中文乱码
outputStream.write(outputStr.getBytes("UTF-8"));
outputStream.close();
}
// 将返回的输入流转换成字符串
InputStream inputStream = httpUrlConn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(
inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(
inputStreamReader);
String str = null;
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
bufferedReader.close();
inputStreamReader.close();
// 释放资源
inputStream.close();
inputStream = null;
httpUrlConn.disconnect();
jsonObject = JSONObject.fromObject(buffer.toString());
} catch (ConnectException ce) {
System.out.println("微信服务器连接超时!");
} catch (Exception e) {
System.out.println("HTTPS请求错误,错误信息:\n" + e.getMessage());
}
return jsonObject;
}
//刷新网页授权access_token的接口地址(GET)
public final static String refresh_access_token_url="https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN";
/**
*
* @Title: getRefreshAccessToken
* @Description: 刷新网页授权access_token
* @author Administrator
* @date 2015-7-12 上午09:55:46
* @param appid
* @param refresh_token
* @return
*/
public static WebAccessToken getRefreshAccessToken(String appid,String refresh_token){
WebAccessToken accessToken=null;
String requestUrl=refresh_access_token_url.replace("APPID", appid).replace("REFRESH_TOKEN", refresh_token);
JSONObject jsonObject=httpRequest(requestUrl, "GET", null);
if (null != jsonObject) {
try {
accessToken = new WebAccessToken();
accessToken.setToken(jsonObject.getString("access_token"));
accessToken.setExpiresIn(jsonObject.getInt("expires_in"));
accessToken.setRefreshToken(jsonObject.getString("refresh_token"));
accessToken.setOpenid(jsonObject.getString("openid"));
accessToken.setScope(jsonObject.getString("scope"));
//accessToken.setUnionid(jsonObject.getString("unionid"));
} catch (Exception e) {
accessToken = null;
// 获取token失败
System.out.println("获取TOKEN失败("+jsonObject.getInt("errcode")+"):"+WeChatErrorCode.ERRORCODE.get(jsonObject.getInt("errcode")));
}
}
return accessToken;
}
//获取 网页授权access_token的接口地址(GET)
public final static String web_access_token_url="https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
/**
*
* @Title: getWebAccessToken
* @Description: 获取网页授权access_token
* @author Administrator
* @date 2015-7-12 上午09:47:47
* @param appid 应用id
* @param secret
* @param code
* @return
*/
public static WebAccessToken getWebAccessToken(String appid,String secret,String code){
WebAccessToken accessToken=null;
String requestUrl=web_access_token_url.replace("APPID", appid).replace("SECRET", secret).replace("CODE", code);
JSONObject jsonObject=httpRequest(requestUrl, "GET", null);
// 如果请求成功
if (null != jsonObject) {
try {
accessToken = new WebAccessToken();
accessToken.setToken(jsonObject.getString("access_token"));
accessToken.setExpiresIn(jsonObject.getInt("expires_in"));
accessToken.setRefreshToken(jsonObject.getString("refresh_token"));
accessToken.setOpenid(jsonObject.getString("openid"));
accessToken.setScope(jsonObject.getString("scope"));
//accessToken.setUnionid(jsonObject.getString("unionid"));
} catch (Exception e) {
accessToken = null;
// 获取token失败
System.out.println("获取TOKEN失败("+jsonObject.getInt("errcode")+"):"+WeChatErrorCode.ERRORCODE.get(jsonObject.getInt("errcode")));
}
}
return accessToken;
}
// 获取access_token的接口地址(GET) 限200(次/天)
public final static String access_token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
/**
*
* @Title: getAccessToken
* @Description: 获取access_token
* @author Administrator
* @date 2015-7-8 下午12:08:00
* @param appid 凭证
* @param appsecret 秘钥
* @return
*/
public static AccessToken getAccessToken(String appid, String appsecret) {
AccessToken accessToken = null;
String requestUrl = access_token_url.replace("APPID", appid).replace("APPSECRET", appsecret);
JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
// 如果请求成功
if (null != jsonObject) {
try {
accessToken = new AccessToken();
accessToken.setToken(jsonObject.getString("access_token"));
accessToken.setExpiresIn(jsonObject.getInt("expires_in"));
} catch (Exception e) {
accessToken = null;
// 获取token失败
System.out.println("获取TOKEN失败("+jsonObject.getInt("errcode")+"):"+WeChatErrorCode.ERRORCODE.get(jsonObject.getInt("errcode")));
}
}
return accessToken;
}
// 菜单创建(POST) 限100(次/天)
public static String menu_create_url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN";
/**
*
* @Title: createMenu
* @Description: 创建菜单
* @author Administrator
* @date 2015-7-8 下午12:20:02
* @param jsonMenu 菜单实例(json格式)
* @param accessToken
* @return
*/
public static int createMenu(String jsonMenu, String accessToken) {
int result = 0;
// 拼装创建菜单的url
String url = menu_create_url.replace("ACCESS_TOKEN", accessToken);
// 调用接口创建菜单
JSONObject jsonObject = httpRequest(url, "POST", jsonMenu);
if (null != jsonObject) {
if (0 != jsonObject.getInt("errcode")) {
result = jsonObject.getInt("errcode");
System.out.println("创建菜单失败("+result+"):"+WeChatErrorCode.ERRORCODE.get(result));
}
}
return result;
}
//检验授权凭证access_token是否有效的接口地址(GET)
public final static String check_webaccess_token_url="https://api.weixin.qq.com/sns/auth?access_token=ACCESS_TOKEN&openid=OPENID";
/**
*
* @Title: checkWebAccessToken
* @Description: 检验授权凭证(access_token)是否有效
* @author Administrator
* @date 2015-7-12 上午10:58:58
* @param accessToken
* @param openid
* @return
*/
public static int checkWebAccessToken(String accessToken,String openid){
int result = 0;
// 拼装创建菜单的url
String url = check_webaccess_token_url.replace("ACCESS_TOKEN", accessToken).replace("OPENID", openid);
// 调用接口创建菜单
JSONObject jsonObject = httpRequest(url, "GET", null);
if (null != jsonObject) {
if (0 != jsonObject.getInt("errcode")) {
result = jsonObject.getInt("errcode");
System.out.println("创建菜单失败("+result+"):"+WeChatErrorCode.ERRORCODE.get(result));
}
}
return result;
}
//获取微信用户基本信息的接口地址(GET)
public final static String get_user_info_url="https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";
/**
*
* @Title: getWxUserInfo
* @Description:获取微信用户基本信息
* @author Administrator
* @date 2015-7-12 上午10:54:12
* @param accessToken
* @param opendid
* @return
*/
@SuppressWarnings("unchecked")
public static WxUser getWxUserInfo(String accessToken,String opendid){
WxUser wxUserInfo=null;
String requestUrl=get_user_info_url.replace("ACCESS_TOKEN", accessToken).replace("OPENID",opendid);
JSONObject jsonObject=httpRequest(requestUrl, "GET", null);
if (null != jsonObject) {
try {
wxUserInfo = new WxUser();
wxUserInfo.setCity(jsonObject.getString("city"));
wxUserInfo.setOpenid(jsonObject.getString("openid"));
wxUserInfo.setNickname(jsonObject.getString("nickname"));
wxUserInfo.setSex(jsonObject.getInt("sex"));
wxUserInfo.setProvince(jsonObject.getString("province"));
wxUserInfo.setCountry(jsonObject.getString("country"));
wxUserInfo.setHeadimgurl(jsonObject.getString("headimgurl"));
} catch (Exception e) {
accessToken = null;
// 获取token失败
System.out.println("获取用户基本信息失败("+jsonObject.getInt("errcode")+"):"+WeChatErrorCode.ERRORCODE.get(jsonObject.getInt("errcode")));
}
}
return wxUserInfo;
}
/**
* 主动推送信息接口
*/
private final static String sendMsgUrl = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN";
/**
* @desc 推送信息
* @param token
* @param msg
* @return
*/
public static String sendMessage(String token, String msg) {
try {
System.out.println("sendMessage start.token:" + token + ",msg:" + msg);
String requestUrl = sendMsgUrl.replace("ACCESS_TOKEN", token);
JSONObject jsonObject = httpRequest(requestUrl, "POST", msg);
System.out.println("return response=====start======");
System.out.println(jsonObject);
System.out.println("return response=====end======");
return jsonObject.toString();
} catch (Exception e) {
System.out.println("get user info exception:" + e);
return null;
}
}
}
XcxWeChatUtil.java
package com.weixin.common.util;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.URL;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.servlet.http.HttpServletRequest;
import org.apache.http.entity.StringEntity;
import net.sf.json.JSONObject;
import com.weixin.common.wxpojo.AccessToken;
import com.weixin.common.wxpojo.WebAccessToken;
import com.weixin.pojo.WxUser;
/**
*
* @ClassName: WeChatUtil
* @Description: 微信开发工具类
* @author Administrator
* @date 2015-7-8 上午11:50:24
*
*/
public class XcxWeChatUtil {
/**
*
* @Title: httpRequest
* @Description: 访问微信接口
* @author Administrator
* @date 2015-7-8 下午03:34:12
* @param requestUrl 访问路径
* @param requestMethod 访问类型 POST OR GET
* @param outputStr 要提交的数据,没有设置为null
* @return 返回数据 json格式
*/
public static JSONObject httpRequest(String requestUrl,String requestMethod, String outputStr) {
JSONObject jsonObject = null;
StringBuffer buffer = new StringBuffer();
try {
// 创建SSLContext对象,并使用我们指定的信任管理器初始化
TrustManager[] tm = { new TrustManager() };
SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
sslContext.init(null, tm, new java.security.SecureRandom());
// 从上述SSLContext对象中得到SSLSocketFactory对象
SSLSocketFactory ssf = sslContext.getSocketFactory();
URL url = new URL(requestUrl);
HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
httpUrlConn.setSSLSocketFactory(ssf);
httpUrlConn.setDoOutput(true);
httpUrlConn.setDoInput(true);
httpUrlConn.setUseCaches(false);
// 设置请求方式(GET/POST)
httpUrlConn.setRequestMethod(requestMethod);
if ("GET".equalsIgnoreCase(requestMethod))
httpUrlConn.connect();
// 当有数据需要提交时
if (null != outputStr) {
OutputStream outputStream = httpUrlConn.getOutputStream();
// 注意编码格式,防止中文乱码
outputStream.write(outputStr.getBytes("UTF-8"));
outputStream.close();
}
// 将返回的输入流转换成字符串
InputStream inputStream = httpUrlConn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(
inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(
inputStreamReader);
String str = null;
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
bufferedReader.close();
inputStreamReader.close();
// 释放资源
inputStream.close();
inputStream = null;
httpUrlConn.disconnect();
jsonObject = JSONObject.fromObject(buffer.toString());
} catch (ConnectException ce) {
System.out.println("微信服务器连接超时!");
} catch (Exception e) {
System.out.println("HTTPS请求错误,错误信息:\n" + e.getMessage());
}
return jsonObject;
}
//刷新网页授权access_token的接口地址(GET)
public final static String refresh_access_token_url="https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN";
/**
*
* @Title: getRefreshAccessToken
* @Description: 刷新网页授权access_token
* @author Administrator
* @date 2015-7-12 上午09:55:46
* @param appid
* @param refresh_token
* @return
*/
public static WebAccessToken getRefreshAccessToken(String appid,String refresh_token){
WebAccessToken accessToken=null;
String requestUrl=refresh_access_token_url.replace("APPID", appid).replace("REFRESH_TOKEN", refresh_token);
JSONObject jsonObject=httpRequest(requestUrl, "GET", null);
if (null != jsonObject) {
try {
accessToken = new WebAccessToken();
accessToken.setToken(jsonObject.getString("access_token"));
accessToken.setExpiresIn(jsonObject.getInt("expires_in"));
accessToken.setRefreshToken(jsonObject.getString("refresh_token"));
accessToken.setOpenid(jsonObject.getString("openid"));
accessToken.setScope(jsonObject.getString("scope"));
//accessToken.setUnionid(jsonObject.getString("unionid"));
} catch (Exception e) {
accessToken = null;
// 获取token失败
System.out.println("获取TOKEN失败("+jsonObject.getInt("errcode")+"):"+WeChatErrorCode.ERRORCODE.get(jsonObject.getInt("errcode")));
}
}
return accessToken;
}
//获取 网页授权access_token的接口地址(GET)
public final static String web_access_token_url="https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
/**
*
* @Title: getWebAccessToken
* @Description: 获取网页授权access_token
* @author Administrator
* @date 2015-7-12 上午09:47:47
* @param appid 应用id
* @param secret
* @param code
* @return
*/
public static WebAccessToken getWebAccessToken(String appid,String secret,String code){
WebAccessToken accessToken=null;
String requestUrl=web_access_token_url.replace("APPID", appid).replace("SECRET", secret).replace("CODE", code);
JSONObject jsonObject=httpRequest(requestUrl, "GET", null);
// 如果请求成功
if (null != jsonObject) {
try {
accessToken = new WebAccessToken();
accessToken.setToken(jsonObject.getString("access_token"));
accessToken.setExpiresIn(jsonObject.getInt("expires_in"));
accessToken.setRefreshToken(jsonObject.getString("refresh_token"));
accessToken.setOpenid(jsonObject.getString("openid"));
accessToken.setScope(jsonObject.getString("scope"));
//accessToken.setUnionid(jsonObject.getString("unionid"));
} catch (Exception e) {
accessToken = null;
// 获取token失败
System.out.println("获取TOKEN失败("+jsonObject.getInt("errcode")+"):"+WeChatErrorCode.ERRORCODE.get(jsonObject.getInt("errcode")));
}
}
return accessToken;
}
// 获取access_token的接口地址(GET) 限200(次/天)
public final static String access_token_url = "https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code";
/**
*
* @Title: getAccessToken
* @Description: 获取access_token
* @author Administrator
* @date 2015-7-8 下午12:08:00
* @param appid 凭证
* @param appsecret 秘钥
* @return
*/
public static String getOpenid(String appid, String appsecret,String js_code) {
String openid = "";
String requestUrl = access_token_url.replace("APPID", appid).replace("SECRET", appsecret).replace("JSCODE", js_code);
JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
// 如果请求成功
if (null != jsonObject) {
try {
openid=jsonObject.getString("openid");
} catch (Exception e) {
openid="";
// 获取token失败
System.out.println("获取TOKEN失败("+jsonObject.getInt("errcode")+"):"+WeChatErrorCode.ERRORCODE.get(jsonObject.getInt("errcode")));
}
}
return openid;
}
// 菜单创建(POST) 限100(次/天)
public static String menu_create_url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN";
/**
*
* @Title: createMenu
* @Description: 创建菜单
* @author Administrator
* @date 2015-7-8 下午12:20:02
* @param jsonMenu 菜单实例(json格式)
* @param accessToken
* @return
*/
public static int createMenu(String jsonMenu, String accessToken) {
int result = 0;
// 拼装创建菜单的url
String url = menu_create_url.replace("ACCESS_TOKEN", accessToken);
// 调用接口创建菜单
JSONObject jsonObject = httpRequest(url, "POST", jsonMenu);
if (null != jsonObject) {
if (0 != jsonObject.getInt("errcode")) {
result = jsonObject.getInt("errcode");
System.out.println("创建菜单失败("+result+"):"+WeChatErrorCode.ERRORCODE.get(result));
}
}
return result;
}
//检验授权凭证access_token是否有效的接口地址(GET)
public final static String check_webaccess_token_url="https://api.weixin.qq.com/sns/auth?access_token=ACCESS_TOKEN&openid=OPENID";
/**
*
* @Title: checkWebAccessToken
* @Description: 检验授权凭证(access_token)是否有效
* @author Administrator
* @date 2015-7-12 上午10:58:58
* @param accessToken
* @param openid
* @return
*/
public static int checkWebAccessToken(String accessToken,String openid){
int result = 0;
// 拼装创建菜单的url
String url = check_webaccess_token_url.replace("ACCESS_TOKEN", accessToken).replace("OPENID", openid);
// 调用接口创建菜单
JSONObject jsonObject = httpRequest(url, "GET", null);
if (null != jsonObject) {
if (0 != jsonObject.getInt("errcode")) {
result = jsonObject.getInt("errcode");
System.out.println("创建菜单失败("+result+"):"+WeChatErrorCode.ERRORCODE.get(result));
}
}
return result;
}
//获取微信用户基本信息的接口地址(GET)
public final static String get_user_info_url="https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";
/**
*
* @Title: getWxUserInfo
* @Description:获取微信用户基本信息
* @author Administrator
* @date 2015-7-12 上午10:54:12
* @param accessToken
* @param opendid
* @return
*/
@SuppressWarnings("unchecked")
public static WxUser getWxUserInfo(String accessToken,String opendid){
WxUser wxUserInfo=null;
String requestUrl=get_user_info_url.replace("ACCESS_TOKEN", accessToken).replace("OPENID",opendid);
JSONObject jsonObject=httpRequest(requestUrl, "GET", null);
if (null != jsonObject) {
try {
wxUserInfo = new WxUser();
wxUserInfo.setCity(jsonObject.getString("city"));
wxUserInfo.setOpenid(jsonObject.getString("openid"));
wxUserInfo.setNickname(jsonObject.getString("nickname"));
wxUserInfo.setSex(jsonObject.getInt("sex"));
wxUserInfo.setProvince(jsonObject.getString("province"));
wxUserInfo.setCountry(jsonObject.getString("country"));
wxUserInfo.setHeadimgurl(jsonObject.getString("headimgurl"));
} catch (Exception e) {
accessToken = null;
// 获取token失败
System.out.println("获取用户基本信息失败("+jsonObject.getInt("errcode")+"):"+WeChatErrorCode.ERRORCODE.get(jsonObject.getInt("errcode")));
}
}
return wxUserInfo;
}
/**
* 主动推送信息接口
*/
private final static String sendMsgUrl = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN";
/**
* @desc 推送信息
* @param token
* @param msg
* @return
*/
public static String sendMessage(String token, String msg) {
try {
System.out.println("sendMessage start.token:" + token + ",msg:" + msg);
String requestUrl = sendMsgUrl.replace("ACCESS_TOKEN", token);
JSONObject jsonObject = httpRequest(requestUrl, "POST", msg);
System.out.println("return response=====start======");
System.out.println(jsonObject);
System.out.println("return response=====end======");
return jsonObject.toString();
} catch (Exception e) {
System.out.println("get user info exception:" + e);
return null;
}
}
}
2.统一下单接口
public ModelAndView pay(HttpServletRequest request,HttpServletResponse response) throws ParseException{
ModelAndView mav=new ModelAndView();
try {
SysSet set=commonService.findObjectById(1, SysSet.class);//获取支付信息,公众号appid、公众号密钥;商户号、商户号密钥
Record record=commonService.findObjectById(1, Record.class);//查询支付金额,或者订单
String reqId="";
for (int j = 0; j < 1; j++) {//生成订单号,然后查询是否使用过订单号,如果使用过就循环重新生成
reqId=currentTime("yyyyMMddHHmmssSSS", new Date())+user.getId();
List<Ssrecord> slist=mobileService.getSsrecord(" and reqId='"+reqId+"'");
if(slist.size()>0){
j--;
}
}
Ssrecord srecord=new Ssrecord();//新增一条支付记录,核销时使用
mobileService.addSsrecord(srecord);
BigDecimal bd3 = new BigDecimal(record.getFeiyong()); //金额以分为单位
BigDecimal bd4 = new BigDecimal("100");
int intMoney = bd3.multiply(bd4).intValue();//使用BigDecimal进行转换计算
System.out.println(intMoney);
//总金额以分为单位,不带小数点
int total_fee = intMoney;
//商品描述根据情况修改
String body = record.getTitle();
attach=record.getId()+"-"+user.getId()+"-"+srecord.getId();//增加备注,记录订单的id、支付记录的id和用户的id,在核销时使用这个去查询钉钉,完成核销
String appid = set.getAppId();//公众号appid
String appsecret = set.getAppKey();//公众号密钥
String partner = set.getPartner();//商户号
String partnerkey = set.getPartnerkey();//商户号密钥
//获取openId后调用统一支付接https://api.mch.weixin.qq.com/pay/unifiedorder
String currTime = TenpayUtil.getCurrTime();//时间戳
//8位日期
String strTime = currTime.substring(8, currTime.length());
//四位随机数
String strRandom = TenpayUtil.buildRandom(4) + "";
//10位序列号,可以自行调整。
String strReq = strTime + strRandom;
//商户号
String mch_id = partner;
//随机数
String nonce_str = strReq;
String body = "";
//商户订单号
String out_trade_no = reqId;
//订单生成的机器 IP
String spbill_create_ip = request.getRemoteAddr();
//这里notify_url是 支付完成后微信发给该链接信息,可以判断会员是否支付成功,改变订单状态等。
String notify_url ="pay/notifyUrl";//支付成功后,微信把支付结果返回给这个地址,然后在这个方法里面解析并完成核销,再返回给微信一个状态
String trade_type = "JSAPI";//公众号支付
String openid = openId;
SortedMap<String, String> packageParams = new TreeMap<String, String>();//把需要生成签字的内容当中这个数组
packageParams.put("appid",appid );
packageParams.put("mch_id", mch_id);
packageParams.put("nonce_str", nonce_str);
packageParams.put("body", body);
packageParams.put("attach", attach);
packageParams.put("out_trade_no", out_trade_no);
//这里写的金额为1 分到时修改
packageParams.put("total_fee", total_fee+"");
packageParams.put("spbill_create_ip", spbill_create_ip);
packageParams.put("notify_url", notify_url);
packageParams.put("trade_type", trade_type);
packageParams.put("openid", openid);
RequestHandler reqHandler = new RequestHandler(request, response);
reqHandler.init(appid, appsecret,partnerkey);//api密钥
String sign = reqHandler.createSign(packageParams);//生成签字
//把统一下单的值以XML格式编辑,这个内容要和上面的数据一致,然后多传一个签字
String xml="<xml>"+
"<appid>"+appid+"</appid>"+
"<mch_id>"+mch_id+"</mch_id>"+
"<nonce_str>"+nonce_str+"</nonce_str>"+
"<sign>"+sign+"</sign>"+
"<body><![CDATA["+body+"]]></body>"+
"<attach>"+attach+"</attach>"+
"<out_trade_no>"+out_trade_no+"</out_trade_no>"+
//金额,这里写的1 分到时修改
"<total_fee>"+total_fee+"</total_fee>"+
"<spbill_create_ip>"+spbill_create_ip+"</spbill_create_ip>"+
"<notify_url>"+notify_url+"</notify_url>"+
"<trade_type>"+trade_type+"</trade_type>"+
"<openid>"+openid+"</openid>"+
"</xml>";
String allParameters = "";
try {
allParameters = reqHandler.genPackage(packageParams);
} catch (Exception e) {
e.printStackTrace();
}
String createOrderURL = "https://api.mch.weixin.qq.com/pay/unifiedorder";//访问统一下单接口
String prepay_id="";
try {
prepay_id = new GetWxOrderno().getPayNo(createOrderURL, xml);//访问成功后,解析其中prepay_id的值
if(prepay_id.equals("")){
request.setAttribute("ErrorMsg", "统一支付接口获取预支付订单出错");
response.sendRedirect("error.jsp");
}
} catch (Exception e1) {
e1.printStackTrace();
}
String appid2 = appid;
String timestamp = Sha1Util.getTimeStamp();
String nonceStr2 = nonce_str;
String prepay_id2 = "prepay_id="+prepay_id;
String packages = prepay_id2;
SortedMap<String, String> finalpackage = new TreeMap<String, String>();
finalpackage.put("appId", appid2);
finalpackage.put("timeStamp", timestamp);
finalpackage.put("nonceStr", nonceStr2);
finalpackage.put("package", packages);
finalpackage.put("signType", "MD5");
String finalsign = reqHandler.createSign(finalpackage);
//以下为页面调取微信支付的参数
mav.addObject("timeStamp", timestamp);
mav.addObject("packages", packages);
mav.addObject("paySign", finalsign);
mav.addObject("appId", appid2);
mav.addObject("signType", "MD5");
mav.addObject("nonceStr", nonceStr2);
mav.setViewName("");
} catch (Exception e) {
mav.setViewName("");
}
return mav;
}
3.跳转页面后发起支付
<html>
<body>
</body>
<script type="text/javascript">
var appId = "${appId}";
var timeStamp = "${timeStamp}";
var nonceStr = "${nonceStr}";
var pack = "${packages}";
var paySign = "${paySign}";
var signType = "${signType}";
pay();
function onBridgeReady() {
WeixinJSBridge.invoke(
'getBrandWCPayRequest', {
"appId":appId, //公众号名称,由商户传入
"timeStamp":timeStamp, //时间戳,自1970年以来的秒数
"nonceStr":nonceStr, //随机串
"package":pack,
"signType":signType, //微信签名方式:
"paySign":paySign //微信签名
}, function(res) {
// alert(res.err_code + res.err_desc + res.err_msg);
if (res.err_msg == "get_brand_wcpay_request:ok") {} // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回 ok,但并不保证它绝对可靠。
else if (res.err_msg == "get_brand_wcpay_request:fail") {alert("支付失败"); } // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回 ok,但并不保证它绝对可靠。
else if (res.err_msg == "get_brand_wcpay_request:cancal") {alert("支付取消"); } // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回 ok,但并不保证它绝对可靠。
window.location="";//支付成功、取消或者失败时,跳转的页面地址,这里可以自行编辑
});
}
function pay(){
if (typeof WeixinJSBridge == "undefined") {
if (document.addEventListener) {
document.addEventListener('WeixinJSBridgeReady',onBridgeReady, false);
} else if (document.attachEvent) {
document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
}
} else {
onBridgeReady();
}
}
</script>
</html>
4.核销
public @ResponseBody String notifyUrl(HttpServletRequest request) throws Exception{
String return_code="";
Double total_fee=0.00;
String attach="";
String time_end="";
String out_trade_no="";
String xml="";
BufferedReader br = new BufferedReader(new InputStreamReader((ServletInputStream)request.getInputStream()));//获取微信返回的内容
String line = null;
StringBuilder str = new StringBuilder();
//遍历微信的内容,拼接到字符串str中
while((line = br.readLine())!=null){
str.append(line);
}
System.out.println(str);
Map<String, String> respData=xmlToMap(str.toString());//把str内容转换成Map
//去除支付接口状态和核销需要的参数
if (respData.containsKey("return_code")) {
return_code=respData.get("return_code");
}
else {
throw new Exception(String.format("No `return_code` in XML: %s", str));
}
if (respData.containsKey("total_fee")) {
total_fee=new Double(respData.get("total_fee"))/100;
}
else {
throw new Exception(String.format("No `total_fee` in XML: %s", str));
}
if (respData.containsKey("attach")) {
attach=respData.get("attach");
}
else {
throw new Exception(String.format("No `attach` in XML: %s", str));
}
if (respData.containsKey("time_end")) {
time_end=respData.get("time_end");
}
else {
throw new Exception(String.format("No `time_end` in XML: %s", str));
}
if (respData.containsKey("out_trade_no")) {
out_trade_no=respData.get("out_trade_no");
}
else {
throw new Exception(String.format("No `out_trade_no` in XML: %s", str));
}
System.out.println(return_code);
System.out.println(total_fee);
System.out.println(attach);
System.out.println(time_end);
System.out.println(out_trade_no);
try {
if("SUCCESS".equals(return_code)){
attach=attach.replace(",", "-");//把辅助参数中的','转换成'-'
String[] str = attach.split("-");
WeixinUser user= commonService.findObjectById(new Integer(str[1]), WeixinUser.class);//取出用户信息,把用户的信息放在支付里面(备用)
List<Ssrecord> slist=getSsrecord(" and id in ('"+str[2]+"') and reqId='"+out_trade_no+"'");//根据解析出的id和订单号去查询缴费明细
String paymentDate=currentTime("yyyy-MM-dd HH:mm:ss",conversion("yyyyMMddHHmmss", time_end));//微信传的日期是20221107161526 转换成yyyy-MM-dd HH:mm:ss
//把订单和支付明细的支付状态修改成已支付,把支付金额和支付时间保存到对应字段
}
xml="<xml><return_code>"+return_code+"</return_code></xml>";//按照这个格式把这个值返回,可以参考微信支付文档
System.out.println(xml);
} catch (Exception e) {
e.printStackTrace();
xml="<xml><return_code>FAIL</return_code></xml>";
}
return xml;
}
//工具
public Map<String, String> xmlToMap(String strXML) throws Exception {
try {
Map<String, String> data = new HashMap<String, String>();
DocumentBuilder documentBuilder = WXPayXmlUtil.newDocumentBuilder();
InputStream stream = new ByteArrayInputStream(strXML.getBytes("UTF-8"));
org.w3c.dom.Document doc = documentBuilder.parse(stream);
doc.getDocumentElement().normalize();
NodeList nodeList = doc.getDocumentElement().getChildNodes();
for (int idx = 0; idx < nodeList.getLength(); ++idx) {
Node node = nodeList.item(idx);
if (node.getNodeType() == Node.ELEMENT_NODE) {
org.w3c.dom.Element element = (org.w3c.dom.Element) node;
data.put(element.getNodeName(), element.getTextContent());
}
}
try {
stream.close();
} catch (Exception ex) {
// do nothing
}
return data;
} catch (Exception ex) {
System.out.println("Invalid XML, can not convert to map. Error message: {}. XML content: {}"+ ex.getMessage()+strXML);
throw ex;
}
}
//Date转换String format转换后的日期格式 如 yyyy-MM-dd HH:mm:ss str穿过了的Date类型的值
public static String currentTime(String format,Date date){
SimpleDateFormat dateFormat = new SimpleDateFormat(format);
return dateFormat.format(date);
}
// String转换Date format转换后的日期格式 如 yyyy-MM-dd HH:mm:ss str穿过了的字符串
public static Date conversion(String format,String str) throws ParseException{
SimpleDateFormat dateFormat = new SimpleDateFormat(format);
return dateFormat.parse(str);
}