一、获取微信公众号相关信息
微信公众号id、密钥、财付通商户号、商户号对应的密钥、支付成功后跳转地址,放在constants里,方便维护取用
二、获取微信支付页面所需参数的方法
/**
* 微信支付
* @param request
* @param session
* @return
*/
@RequestMapping("/wechat/pay.htm")
@ResponseBody
public String pay(HttpServletRequest request, HttpSession session,HttpServletResponse response) {
try {
String noncestr = Tool.getNonceStr();//32位随机字符串
String timestamp = Long.toString(System.currentTimeMillis() / 1000);//时间戳
PageData param = this.getPageData();
//最好将用户的openid放在session当中,方便取用
User user = this.getUser(request);
String openid = user.getOPENID();
param.put("openid",openid);
int total_fee = (int) (Double.parseDouble(param.get("paymoney").toString()+"")*100);//微信支付金额百进制
String out_trade_no = Tool.isEmpty(param.get("ordercode"));//订单号
SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
parameters.put("appid",Const.APPID);//微信公众号id
parameters.put("body","XX微信支付");
parameters.put("mch_id",SHHID);//财付通商户号
parameters.put("nonce_str", noncestr);
parameters.put("notify_url",Constants.notify_url);//支付成功后的请求通知地址
parameters.put("openid",openid);//用户openid
parameters.put("out_trade_no", out_trade_no);//订单号
parameters.put("spbill_create_ip", request.getRemoteAddr());
parameters.put("total_fee", total_fee);
// parameters.put("total_fee", 1);
parameters.put("trade_type", "JSAPI");
String sign = SignUtil.createSign("UTF-8", parameters);
parameters.put("sign", sign);
String requestXML = StringUtil.getRequesetXml(parameters);
logger.info("=========requestXML"+requestXML);
String strXML = WeixinUtil.httpRequest1(WeixinUtil.UNIFIEDORDER_URL, "POST", requestXML);
Map m = XMLUtil.doXMLoarse(strXML);
logger.info("=========mmmmm"+gson.toJson(m));
//将返回的值传入支付jsp页面
SortedMap<Object, Object> params = new TreeMap<Object, Object>();
params.put("appId",Const.APPID);
params.put("timeStamp", timestamp);
params.put("nonceStr", noncestr);
params.put("package", "prepay_id="+m.get("prepay_id"));
params.put("signType", "MD5");
String paySign=SignUtil.createSign("UTF-8",params);
params.put("packageValue", "prepay_id="+m.get("prepay_id"));
params.put("paySign", paySign);
params.put("sendUrl", Constants.SUCCESS_URL);//支付成功后跳转页面
logger.info("*****************paySign****************:"+paySign);
String userAgent = request.getHeader("user-agent");
char agent = userAgent.charAt(userAgent.indexOf("MicroMessenger")+15);
params.put("agent", new String(new char[]{agent}));//微信版本号,用于判断用户手机微信版本是否是5.0以上版本
JsapiTicket qr=WeixinUtil.getJsapi_ticket(tool.isEmpty(WeixinUtil.getAccessToken(accountid,coreService,openid).get("access_token")));
String path = request.getRequestURI();
String basePath = request.getScheme() + "://xtedu.triones.cc"
+ path + "?"
+ request.getQueryString();
logger.info("*******************basePath*******************:"+basePath);
String signature = SignUtil.sign(qr.getTicket(), timestamp, noncestr, basePath);
logger.info("*****************signature****************:"+signature);
params.put("signature", signature);//初始化微信js签名
String json = gson.toJson(params);
//添加支付记录
/*Map<String,Object> recordparammap = new HashMap<String,Object>();
recordparammap.put("ordercode", out_trade_no);
recordparammap.put("amount", param.get("paymoney"));
recordparammap.put("uid", param.get("uid"));
recordparammap.put("status", 2);
service.addPayrecord(recordparammap);*/
return json;
} catch (Exception e) {
logger.error("**********error*******" + e.getMessage() + "\n", e);
return returnSysErr();
}
}
三、微信支付页面
wepay.jsp
<%@ page language="java" pageEncoding="utf-8"%>
<!DOCTYPE html>
<html
class="um landscape min-width-240px min-width-320px min-width-480px min-width-768px min-width-1024px">
<head>
<title>XXXX</title>
<!-- 我的收藏 -->
<%@ include file="../config/config.jsp"%>
<script type="text/javascript" src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>
<style type="text/css">
.shadow{
-webkit-box-shadow: #999 1px 1px 6px;
-moz-box-shadow: #999 1px 1px 6px;
box-shadow: #999 1px 1px 6px;
background: white;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
}
</style>
</head>
<body class="um-vp bc-bg4">
<input type="hidden" value="${orderObj.PAY_FEE}" id="paymoney">
<input type="hidden" value="${orderObj.ORDERCODE}" id="ordercode">
<div id="page_0" class="up ub ub-ver" tabindex="0">
<!--header开始-->
<div id="header" class="uh bc-text-head ub bc-head">
<div class="nav-btn" id="nav-left" οnclick="goMenber();">
<div class="fa fa-angle-left fa-2x"></div>
</div>
<h1 class="ut ub-f1 ulev-3 ut-s tx-c " >开通会员</h1>
<div class="nav-btn" id="nav-right">
</div>
</div>
<!--header结束-->
<!--content开始-->
<div id="content" class="ub ub-ver ub-f1" style="overflow-y: auto;margin-bottom: 4em;">
<div class="ub ub-ver ub-f1">
<div class="ub ub-ac uinn ub-pc">
付款总金额
</div>
<div class="ub ub-ac uinn3">
<div class="ub ub-f1 ub-pc oc-font ulev2">¥<fmt:formatNumber value="${orderObj.PAY_FEE}" pattern="#,##0.00"/></div>
</div>
</div>
<div class="ub ub-fh ub-f1">
<div class=" uinn ub ub-f1 ub-pc">
<div class="ub uinn2 input-btn-c2 ub-f1 uc-a1 ub-ac ub-pc" style="border: 0;color: black;height: 2em;background-color:#fdbe49;" οnclick="submitPay();">确认付款</div>
</div>
</div>
</div>
</div>
</body>
<script>
$(function(){
});
//付款
function submitPay(){
var paymoney = $("#paymoney").val();//支付金额
var ordercode = $("#ordercode").val();//订单号
var url = "<%=path%>/wechat/pay.htm";
var param = {};
// param.paymoney=paymoney;
param.paymoney=0.01;
param.ordercode=ordercode;
$.post(url,param,function(data,status){
if(data.agent<5){
layer.open({
content:"您的微信版本低于5.0无法使用微信支付",
time:3
});
return false;
}else{
wx.config({
debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: data.appId, // 必填,公众号的唯一标识
timestamp: data.timeStamp, // 必填,生成签名的时间戳
nonceStr: data.nonceStr, // 必填,生成签名的随机串
signature: data.signature,// 必填,签名,见附录1
jsApiList: ['chooseWXPay'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
});
wx.ready(function(){
wx.chooseWXPay({
"timestamp":data.timeStamp, // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
"nonceStr":data.nonceStr, // 支付签名随机串,不长于 32 位
"package":data.packageValue, // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=***)
"signType":data.signType, // 签名方式,默认为'SHA1',使用新版支付需传入'MD5'
"paySign":data.paySign, // 支付签名
success: function (res) {
// 支付成功后的回调函数
//0成功1失败
var cgtourl = "<%=path%>/wechat/paysucces.htm";//支付成功通知
window.location.href = cgtourl;
}
});
});
wx.error(function(res){
var tourl = "<%=path%>/wechat/payfail.htm";//支付失败通知(简单的页面)
window.location.href = tourl;
// payrecord('1',tourl);
return false;
});
}
},'json');
}
</script>
</html>
四、支付成功后的回调函数
/**
* 支付成功的通知请求
* @param request
* @param session
*/
@RequestMapping("/weixinNotify")
public void notify(HttpServletRequest request,HttpServletResponse response) {
try {
ServletInputStream inStream = request.getInputStream();
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while((len=inStream.read(buffer))!=-1){
outStream.write(buffer, 0, len);
}
outStream.close();
inStream.close();
String result = new String(outStream.toByteArray(),"utf-8");
Map<Object,Object> map = XMLUtil.doXMLoarse(result);
Map<String, Object> uumap = new HashMap<String, Object>();
uumap.put("ordercode", map.get("out_trade_no"));
String out_trade_no = tool.isEmpty(map.get("out_trade_no"));
logger.info("************result********"+map);
if(map.get("result_code").toString().equalsIgnoreCase("SUCCESS")){
//支付成功的业务逻辑
}else{
uumap.put("status", 1);
}
//通知微信.异步确认成功.必写.不然微信会一直通知后台.八次之后就认为交易失败了.
response.getWriter().write(RequestHandler.setXML("SUCCESS", ""));
} catch (Exception e) {
logger.error("**********error*******" + e.getMessage() + "\n", e);
}
}