公众号微信支付java开发,微信支付签名错误,或者一直请求回调方法问题
本编为原创,如需转载,请注明出处。
微信支付开发过程中,如果没有遇到签名错误这个问题或者一直请求回调方法问题,那么感觉你开发了一个假对接,网上也有许多列子,以及官网也有微信团队demo,但是还是有解决不了的各种签名问题,demo需要手动修改因为他的加密方式会不尽如人意,还有排序问题。好了,话不多说,直接进入步骤中。
注意:如果遇到签名错误,一定要查看参数顺序
比较坑的是,
1:官网商户key填写的时候提示你8位数还是6位数以上的数字加字母组成就可以,但是你必须在设定完之后,再次修改成32位加密字符串!!!
2:回调地址,如果你是http://www.xxx.cn/txxxr/wxpay/wxpay.do的方式,你的地址需要写成http://www.xxx.cn/txxxr/wxpay/ !!!
好了,以上两个问题如果都没问题了,那么我们进入正式代码开发。(具体工具类以及全部代码,会在本文的末尾中。)
在此只介绍重点步骤,开发可以在demo中修改我的路径以及自己的逻辑就可以。
controller方法:
package cn.teacher.wxpay.controller; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.UUID; import javax.servlet.http.HttpServletRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.transaction.annotation.Transactional; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import cn.teacher.weiXin.dao.BasWxUserForStuDao; import cn.teacher.wxpay.sdk.WXPay; import cn.teacher.wxpay.sdk.WXPayUtil; import cn.teacher.wxpay.util.WXPayConfigImpl; @Controller @RequestMapping("wxpay") public class WXPayController { private WXPay wxpay; private WXPayConfigImpl config; private String out_trade_no; @Autowired private BasWxUserForStuDao basWxUserForStuDao; @RequestMapping(value="/wxpay_memberManagement") public String memberManagement(HttpServletRequest request,Model model){ String openid ="ogcMwwuHoHeMG5Mp_cPkmYYdY6CU"; return "memberManagement"; } @RequestMapping(value="/wxpay_packageInfo") public String packageInfo(HttpServletRequest request){ return "packageInfo"; } public WXPayController() throws Exception { config = WXPayConfigImpl.getInstance(); wxpay = new WXPay(config); out_trade_no = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32); } /** * 扫码支付 下单 * @throws Exception */ @RequestMapping(value = "/wxpay_unifiedOrder", produces = "application/json;charset=UTF-8")//这一步必须有!! @Transactional public @ResponseBody String doUnifiedOrder(String bodyname,String fee) throws Exception {//bodyname例如:腾讯支付中心,fee为价格 JSONObject result = new JSONObject(); Map<String, String> resdata = new HashMap<String, String>(); //获取到用户的openid String openid ="ogcMwwuHoHeMG5Mp_cPkmYYdY6CU"; Map<String, String> data = new HashMap<String, String>(); data.put("body", bodyname); data.put("out_trade_no", out_trade_no);//生成的订单编号 data.put("fee_type", "CNY"); data.put("total_fee", fee); data.put("spbill_create_ip", "58.87.76.30");//请求ip地址 data.put("notify_url", "http://xxx.mmath.cn/teacher/uploadwx/paytest");//请求成功返回路径 data.put("trade_type", "JSAPI");//公众号支付类型 data.put("openid", openid); try { //统一下单,得到prepay_id Map<String, String> r = wxpay.unifiedOrder(data); //得到带预支付prepay_id String prepay_id= r.get("prepay_id"); //拼接组成新的sign并加密 String timestamp = String.valueOf(new Date().getTime()/1000); String stringA =""+"appId="+config.getAppID()+"&nonceStr="+r.get("nonce_str") +"&package=prepay_id="+prepay_id+"&signType=MD5"+"&timeStamp=" + timestamp + "&key="+config.getKey(); String sign=WXPayUtil.MD5(stringA).toUpperCase(); //返回页面数据供调用H5使用 result.put("appId", config.getAppID());//appid result.put("timeStamp", timestamp);//时间戳精确到秒 result.put("nonceStr", r.get("nonce_str"));//订单编号 result.put("paySign", sign);//sign result.put("signType", "MD5");//加密方式 result.put("packageStr", "prepay_id=" + prepay_id); //预支付id result.put("flag", true);//支付方法状态 //可以在此处添加一个临时的订单步骤,状态为支付中,在回调接口中修改支付状态为支付成功或者失败 } catch (Exception e) { e.printStackTrace(); } return JSON.toJSONString(result); } }
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <% String path = request.getContextPath(); %> <!doctype html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> <title>个人中心</title> <script type="text/javascript" src="<%=path %>/js/jquery.js"></script> <script type="text/javascript" src="http://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script> <body> <div> <div style=" width: 100%;"> <ul > <li style="width: 80%;float: left;"><p><strong id="bodyname">99元套餐</strong></p><p>六年级下学期下载</p></li> <li style="width: 20%;float: left;"><p><input type="button" value="结算" onclick="pay();" style="background-color: yellow;"></li> <li style="width: 100%;float: left;" > <input name="tab" type="checkbox" value="" onclick="money();"/>赵小小 <input name="tab" type="checkbox" value="" onclick="money();"/>陈大 <input name="tab" type="checkbox" value="" onclick="money();"/>辰辰 合计¥<strong id="m">0</strong> </li> </ul> </div> </div> <script type="text/javascript"> var prepay_id ,paySign,appId ,timeStamp, nonceStr,packageStr ,signType ; /** * 点击支付按钮进行方法调用 */ function pay(){ var fee="20"; var bodyname="XXX支付界面"; var url = "http://XXX.mmath.cn/teacher/wxpay/wxpay_unifiedOrder"; $.ajax({ type:"post", url:url, data: "bodyname="+bodyname+"&fee="+fee, success:function(data) { if(data.flag){ appId = data.appId; paySign = data.paySign; timeStamp = data.timeStamp; nonceStr = data.nonceStr; packageStr = data.packageStr; signType = data.signType; callpay(); }else{ alert("统一下单失败"); } } }); } /* * 调用支付h5页面 */ function onBridgeReady(){ WeixinJSBridge.invoke( "getBrandWCPayRequest", { "appId":appId, //公众号名称,由商户传入 "timeStamp":timeStamp, //时间戳,自1970年以来的秒数 "nonceStr":nonceStr , //随机串 "package":packageStr, //预支付交易会话标识 "signType":signType, //微信签名方式 "paySign":paySign //微信签名 }, function(res){ if(res.err_msg == "get_brand_wcpay_request:ok" ) { alert("支付成功"); }else if(res.err_msg == "get_brand_wcpay_request:cancel"){ alert("支付取消"); }else if(res.err_msg == "get_brand_wcpay_request:fail" ){ alert("支付失败"); } //使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回 ok,但并不保证它绝对可靠。 } ); } /** * 判断是否进入支付步骤 */ function callpay(){ 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> </body> </html>
其余的文件以及工具类
由于上次上传的文件没有声明以下内容,导致码农下载完资源后看到个官方demo基本一致,直接弃置不用,所以在此特别声明。如果介意,不要下载。
(本文项目是在微信官方demo的基础上进行修改开发的,所以类名方法名和框架结构和官方demo基本一致,但是部分内容会进行修改,请下载前仔细阅读)
http://download.csdn.net/download/qq_37581708/10198124
好吧,我不知道怎么弄成免费的,你们可以联系我,我私发给你们,或者留下你的QQ~
下面是最后一步处理:回调接口
/** * 支付成功后,接收微信返回的回调方法 */ @RequestMapping(value="/order", produces = "application/json;charset=UTF-8") @ResponseBody public void order(HttpServletRequest request, HttpServletResponse response) throws Exception{ String msg = "success"; response.setContentType("text/xml"); String resXml = ""; BufferedReader reader = null; reader = request.getReader(); String line = ""; String xmlString = null; StringBuffer inputString = new StringBuffer(); while ((line = reader.readLine()) != null) { inputString.append(line); } xmlString = inputString.toString(); request.getReader().close(); Document doc = null; try { // 下面的是通过解析xml字符串的 doc = DocumentHelper.parseText(xmlString); // 将字符串转为XML Element rootElt = doc.getRootElement(); // 获取根节点 Element recordEle = (Element)rootElt; String result_code = recordEle.elementTextTrim("result_code"); String return_code = recordEle.elementTextTrim("return_code"); String out_trade_no = recordEle.elementTextTrim("out_trade_no"); String stuNo =out_trade_no.split("_ms_")[1]; //在此处开始进行数据库订单记录状态插入与修改 if(return_code.indexOf("SUCCESS")!=-1){ if(result_code.indexOf("SUCCESS")!=-1){ //支付成功 wXPayService.updateOrder(out_trade_no, "1",stuNo); }else{ //支付失败 wXPayService.updateOrder(out_trade_no, "2","1"); } //这一步非常重要:返回给微信成功通知,否则会一直回调。 resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>" + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> "; BufferedOutputStream out = new BufferedOutputStream( response.getOutputStream()); out.write(resXml.getBytes()); out.flush(); out.close(); response.getWriter().println(msg); } } catch (DocumentException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } }
声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。