微信支付 JAVA实现

来源:互联网 发布:免费刷svip永久软件 编辑:程序博客网 时间:2024/05/19 16:36


微信支付接口文档2.7里的demo实在是看不下去了,错误百出,到网上搜了半天,全部都是把官方文档下下来让你下载,还扣你积分,操蛋。。。

 

微信支付JAVA 接口

首先下载官方demo,虽然很多有问题,但是很多工具类是可以用的

附上地址:https://mp.weixin.qq.com/paymch/readtemplate?t=mp/business/course2_tmpl(别上人家那下还费积分)

 

1.请求前的拼包

// api支付拼包------------------------------------------------------------------------------RequestHandler reqHandler = new RequestHandler(request, response);// TenpayHttpClient httpClient = new TenpayHttpClient();// TreeMap<String, String> outParams = new TreeMap<String,String>();// 初始化reqHandler.init();reqHandler.init(APP_ID,APP_SECRET, APP_KEY,PARTNER_KEY);// 当前时间 yyyyMMddHHmmssString currTime = TenpayUtil.getCurrTime();// 8位日期String strTime = currTime.substring(8, currTime.length());// 四位随机数String strRandom = TenpayUtil.buildRandom(4) + "";// 10位序列号,可以自行调整。String strReq = strTime + strRandom;// 订单号,此处用时间加随机数生成,商户根据自己情况调整,只要保持全局唯一就行String out_trade_no = strReq;// 设置package订单参数SortedMap<String, String> packageParams = new TreeMap<String, String>();packageParams.put("bank_type", "WX"); // 支付类型packageParams.put("body", "商品名称"); // 商品描述packageParams.put("fee_type", "1"); // 银行币种packageParams.put("input_charset", "UTF-8"); // 字符集packageParams.put("notify_url", "通知地址,接收交易结果,并进行业务处理,例如:http://abc.com/buy/buy.do"); // 通知地址packageParams.put("out_trade_no", out_trade_no); // 商户订单号packageParams.put("partner", PARTNER_ID); // 设置商户号packageParams.put("total_fee", "交易金额"); // 商品总金额,以分为单位packageParams.put("spbill_create_ip", request.getRemoteAddr()); // 订单生成的机器IP,指用户浏览器端IP// 获取package包String packageValue = reqHandler.genPackage(packageParams);String noncestr = Sha1Util.getNonceStr();String timestamp = Sha1Util.getTimeStamp();// 设置支付参数SortedMap<String, String> signParams = new TreeMap<String, String>();signParams.put("appid", appid);signParams.put("noncestr", noncestr);signParams.put("package", packageValue);signParams.put("timestamp", timestamp);signParams.put("appkey", appkey);// 生成支付签名,要采用URLENCODER的原始值进行SHA1算法!String sign = Sha1Util.createSHA1Sign(signParams);// 增加非参与签名的额外参数signParams.put("paySign", sign);signParams.put("signType", "SHA1");// ------------------------------------微信js// api支付拼包结束------------------------------------// --------------------------------本地系统生成订单-------------------------------------//// --------------------------------生成完成---------------------------------------------request.setAttribute("appid", appid);request.setAttribute("timestamp", timestamp);request.setAttribute("noncestr", noncestr);request.setAttribute("package", packageValue);request.setAttribute("paysign", sign);request.setAttribute("czje", czje);


 英文全大写带下划线的,各位申请微信支付的时候都会给你的。

注意:微信demo里面RequestHandler 在设置商户key和appkey有点问题,ResponseHandler连postData都没获取到,下面把我修正后的贴出来做参考(注:其它java类没什么问题)

 RequestHandler:

package com.zk.common.wxpay;import java.io.UnsupportedEncodingException;import java.net.URLEncoder;import java.util.Iterator;import java.util.Map;import java.util.Set;import java.util.SortedMap;import java.util.TreeMap;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import com.zk.common.wxpay.util.MD5Util;import com.zk.common.wxpay.util.TenpayUtil;/* '微信支付服务器签名支付请求请求类 '============================================================================ 'api说明: 'init(app_id, app_secret, partner_key, app_key); '初始化函数,默认给一些参数赋值,如cmdno,date等。 'setKey(key_)'设置商户密钥 'getLasterrCode(),获取最后错误号 'GetToken();获取Token 'getTokenReal();Token过期后实时获取Token 'createMd5Sign(signParams);生成Md5签名 'genPackage(packageParams);获取package包 'createSHA1Sign(signParams);创建签名SHA1 'sendPrepay(packageParams);提交预支付 'getDebugInfo(),获取debug信息 '============================================================================ '*/public class RequestHandler {/** Token获取网关地址地址 */private String tokenUrl;/** 预支付网关url地址 */private String gateUrl;/** 查询支付通知网关URL */private String notifyUrl;/** 商户参数 */private String appid;private String appkey;private String partnerkey;private String appsecret;private String key;/** 请求的参数 */private SortedMap parameters;/** Token */private String Token;private String charset;/** debug信息 */private String debugInfo;private String last_errcode;private HttpServletRequest request;private HttpServletResponse response;/** * 初始构造函数。 *  * @return */public RequestHandler(HttpServletRequest request,HttpServletResponse response) {this.last_errcode = "0";this.request = request;this.response = response;this.charset = "GBK";this.parameters = new TreeMap();// 验证notify支付订单网关notifyUrl = "https://gw.tenpay.com/gateway/simpleverifynotifyid.xml";}/** * 初始化函数。 */public void init(String app_id, String app_secret, String app_key,String partner_key) {this.last_errcode = "0";this.Token = "token_";this.debugInfo = "";this.appkey = app_key;this.appid = app_id;this.partnerkey = partner_key;this.key = partner_key;//原demo没有,手动加上this.appsecret = app_secret;}public void init() {}/** * 获取最后错误号 */public String getLasterrCode() {return last_errcode;}/** *获取入口地址,不包含参数值 */public String getGateUrl() {return gateUrl;}/** * 获取参数值 *  * @param parameter *            参数名称 * @return String */public String getParameter(String parameter) {String s = (String) this.parameters.get(parameter);return (null == s) ? "" : s;} //设置密钥public void setKey(String key) {this.partnerkey = key;}//设置微信密钥public void  setAppKey(String key){this.appkey = key;}// 特殊字符处理public String UrlEncode(String src) throws UnsupportedEncodingException {return URLEncoder.encode(src, this.charset).replace("+", "%20");}// 获取package的签名包public String genPackage(SortedMap<String, String> packageParams)throws UnsupportedEncodingException {String sign = createSign(packageParams);StringBuffer sb = new StringBuffer();Set es = packageParams.entrySet();Iterator it = es.iterator();while (it.hasNext()) {Map.Entry entry = (Map.Entry) it.next();String k = (String) entry.getKey();String v = (String) entry.getValue();sb.append(k + "=" + UrlEncode(v) + "&");}// 去掉最后一个&String packageValue = sb.append("sign=" + sign).toString();System.out.println("packageValue=" + packageValue);return packageValue;}/** * 创建md5摘要,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。 */public String createSign(SortedMap<String, String> packageParams) {StringBuffer sb = new StringBuffer();Set es = packageParams.entrySet();Iterator it = es.iterator();while (it.hasNext()) {Map.Entry entry = (Map.Entry) it.next();String k = (String) entry.getKey();String v = (String) entry.getValue();if (null != v && !"".equals(v) && !"sign".equals(k)&& !"key".equals(k)) {sb.append(k + "=" + v + "&");}}sb.append("key=" + this.getKey());System.out.println("md5 sb:" + sb);String sign = MD5Util.MD5Encode(sb.toString(), this.charset).toUpperCase();return sign;}/** * 创建package签名 */public boolean createMd5Sign(String signParams) {StringBuffer sb = new StringBuffer();Set es = this.parameters.entrySet();Iterator it = es.iterator();while (it.hasNext()) {Map.Entry entry = (Map.Entry) it.next();String k = (String) entry.getKey();String v = (String) entry.getValue();if (!"sign".equals(k) && null != v && !"".equals(v)) {sb.append(k + "=" + v + "&");}}// 算出摘要String enc = TenpayUtil.getCharacterEncoding(this.request,this.response);String sign = MD5Util.MD5Encode(sb.toString(), enc).toLowerCase();String tenpaySign = this.getParameter("sign").toLowerCase();// debug信息this.setDebugInfo(sb.toString() + " => sign:" + sign + " tenpaySign:"+ tenpaySign);return tenpaySign.equals(sign);}    //输出XML   public String parseXML() {   StringBuffer sb = new StringBuffer();       sb.append("<xml>");       Set es = this.parameters.entrySet();       Iterator it = es.iterator();       while(it.hasNext()) {Map.Entry entry = (Map.Entry)it.next();String k = (String)entry.getKey();String v = (String)entry.getValue();if(null != v && !"".equals(v) && !"appkey".equals(k)) {sb.append("<" + k +">" + getParameter(k) + "</" + k + ">\n");}}       sb.append("</xml>");return sb.toString();}/** * 设置debug信息 */protected void setDebugInfo(String debugInfo) {this.debugInfo = debugInfo;}public void setPartnerkey(String partnerkey) {this.partnerkey = partnerkey;}public String getDebugInfo() {return debugInfo;}public String getKey() {return key;}}

 

ResponseHandler:

package com.zk.common.wxpay;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;import java.io.Reader;import java.io.UnsupportedEncodingException;import java.util.ArrayList;import java.util.Iterator;import java.util.Map;import java.util.Set;import java.util.SortedMap;import java.util.TreeMap;import com.zk.common.Parameters;import com.zk.common.wxpay.util.Sha1Util;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.dom4j.Document;import org.dom4j.DocumentHelper;import org.dom4j.Element;import org.jdom.JDOMException;import com.sun.org.apache.xalan.internal.xsltc.runtime.Hashtable;import com.zk.common.wxpay.util.MD5Util;import com.zk.common.wxpay.util.TenpayUtil;import com.zk.common.wxpay.util.XMLUtil;/** * 微信支付服务器签名支付请求应答类 api说明: getKey()/setKey(),获取/设置密钥 * getParameter()/setParameter(),获取/设置参数值 getAllParameters(),获取所有参数 * isTenpaySign(),是否财付通签名,true:是 false:否 getDebugInfo(),获取debug信息 */public class ResponseHandler {private static final String appkey = APP_KEY;/** 密钥 */private String key;/** 应答的参数 */private SortedMap parameters;/** debug信息 */private String debugInfo;private HttpServletRequest request;private HttpServletResponse response;private String uriEncoding;private Hashtable xmlMap;private SortedMap smap;public SortedMap getSmap() {return smap;}private String k;/** * 构造函数 *  * @param request * @param response */public ResponseHandler(HttpServletRequest request,HttpServletResponse response) {this.request = request;this.response = response;this.smap = new TreeMap<String, String>();this.key = "";this.parameters = new TreeMap();this.debugInfo = "";this.uriEncoding = "";Map m = this.request.getParameterMap();Iterator it = m.keySet().iterator();while (it.hasNext()) {String k = (String) it.next();String v = ((String[]) m.get(k))[0];this.setParameter(k, v);}BufferedReader reader  =null;try{reader = new BufferedReader(new InputStreamReader(request.getInputStream()));            StringBuilder sb = new StringBuilder();            String line = null;            while ((line = reader.readLine()) != null) {                sb.append(line);            }        Document doc = DocumentHelper.parseText(sb.toString());        Element root = doc.getRootElement();         for (Iterator iterator = root.elementIterator(); iterator.hasNext();) {        Element e = (Element) iterator.next();          smap.put(e.getName(), e.getText());}}catch (Exception e) {// TODO: handle exceptione.printStackTrace();}        }/** * 获取密钥 */public String getKey() {return key;}/** * 设置密钥 */public void setKey(String key) {this.key = key;}/** * 获取参数值 *  * @param parameter *            参数名称 * @return String */public String getParameter(String parameter) {String s = (String) this.parameters.get(parameter);return (null == s) ? "" : s;}/** * 设置参数值 *  * @param parameter *            参数名称 * @param parameterValue *            参数值 */public void setParameter(String parameter, String parameterValue) {String v = "";if (null != parameterValue) {v = parameterValue.trim();}this.parameters.put(parameter, v);}/** * 返回所有的参数 *  * @return SortedMap */public SortedMap getAllParameters() {return this.parameters;}public void doParse(String xmlContent) throws JDOMException, IOException {this.parameters.clear();// 解析xml,得到mapMap m = XMLUtil.doXMLParse(xmlContent);// 设置参数Iterator it = m.keySet().iterator();while (it.hasNext()) {String k = (String) it.next();String v = (String) m.get(k);this.setParameter(k, v);}}/** * 是否财付通签名,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。 *  * @return boolean */public boolean isValidSign() {StringBuffer sb = new StringBuffer();Set es = this.parameters.entrySet();Iterator it = es.iterator();while (it.hasNext()) {Map.Entry entry = (Map.Entry) it.next();String k = (String) entry.getKey();String v = (String) entry.getValue();if (!"sign".equals(k) && null != v && !"".equals(v)) {sb.append(k + "=" + v + "&");}}sb.append("key=" + this.getKey());// 算出摘要String enc = TenpayUtil.getCharacterEncoding(this.request,this.response);String sign = MD5Util.MD5Encode(sb.toString(), enc).toLowerCase();String ValidSign = this.getParameter("sign").toLowerCase();// debug信息this.setDebugInfo(sb.toString() + " => sign:" + sign + " ValidSign:"+ ValidSign);System.out.println("财付通签名:"+this.getDebugInfo());return ValidSign.equals(sign);}/** * 判断微信签名 */public boolean isWXsign() {StringBuffer sb = new StringBuffer();String keys = "";SortedMap<String, String> signParams = new TreeMap<String, String>();Set es = this.smap.entrySet();Iterator it = es.iterator();while (it.hasNext()) {Map.Entry entry = (Map.Entry) it.next();String k = (String) entry.getKey();String v = (String) entry.getValue();if (k != "SignMethod" && k != "AppSignature") {signParams.put(k.toLowerCase(), v);}}signParams.put("appkey", this.appkey);Set set = signParams.entrySet();Iterator pit = set.iterator();while (pit.hasNext()) {Map.Entry entry = (Map.Entry) pit.next();String k = (String) entry.getKey();String v = (String) entry.getValue();if (sb.length() == 0) {sb.append(k + "=" + v);} else {sb.append("&" + k + "=" + v);}}String sign = Sha1Util.getSha1(sb.toString()).toString().toLowerCase();this.setDebugInfo(sb.toString() + " => SHA1 sign:" + sign);return sign.equals(this.smap.get("AppSignature"));}// 判断微信维权签名public boolean isWXsignfeedback() {StringBuffer sb = new StringBuffer();Hashtable signMap = new Hashtable();Set es = this.parameters.entrySet();Iterator it = es.iterator();while (it.hasNext()) {Map.Entry entry = (Map.Entry) it.next();String k = (String) entry.getKey();String v = (String) entry.getValue();if (k != "SignMethod" && k != "AppSignature") {sb.append(k + "=" + v + "&");}}signMap.put("appkey", this.appkey);// ArrayList akeys = new ArrayList();// akeys.Sort();while (it.hasNext()) {String v = k;if (sb.length() == 0) {sb.append(k + "=" + v);} else {sb.append("&" + k + "=" + v);}}String sign = Sha1Util.getSha1(sb.toString()).toString().toLowerCase();this.setDebugInfo(sb.toString() + " => SHA1 sign:" + sign);return sign.equals(this.smap.get("AppSignature"));}/** * 返回处理结果给财付通服务器。 *  * @param msg *            Success or fail * @throws IOException */public void sendToCFT(String msg) throws IOException {String strHtml = msg;PrintWriter out = this.getHttpServletResponse().getWriter();out.println(strHtml);out.flush();out.close();}/** * 获取uri编码 *  * @return String */public String getUriEncoding() {return uriEncoding;}/** * 设置uri编码 *  * @param uriEncoding * @throws UnsupportedEncodingException */public void setUriEncoding(String uriEncoding)throws UnsupportedEncodingException {if (!"".equals(uriEncoding.trim())) {this.uriEncoding = uriEncoding;// 编码转换String enc = TenpayUtil.getCharacterEncoding(request, response);Iterator it = this.parameters.keySet().iterator();while (it.hasNext()) {String k = (String) it.next();String v = this.getParameter(k);v = new String(v.getBytes(uriEncoding.trim()), enc);this.setParameter(k, v);}}}/** * 获取debug信息 */public String getDebugInfo() {return debugInfo;}/** * 设置debug信息 */protected void setDebugInfo(String debugInfo) {this.debugInfo = debugInfo;}protected HttpServletRequest getHttpServletRequest() {return this.request;}protected HttpServletResponse getHttpServletResponse() {return this.response;}}

 

2.Jsapi调用

在第一步中已拼好包放入request中了,第二部js调用微信api,看代码:

<script type="text/javascript">function callpay(){ WeixinJSBridge.invoke('getBrandWCPayRequest',{ "appId" : "${appid}","timeStamp" : "${timestamp}", "nonceStr" : "${noncestr}", "package" : "${package}","signType" : "SHA1", "paySign" : "${paysign}" },function(res){WeixinJSBridge.log(res.err_msg);if(res.err_msg == "get_brand_wcpay_request:ok"){alert("微信支付成功");}else if(res.err_msg == "get_brand_wcpay_request:cancel"){alert("用户取消支付");}else{alert("支付失败");}});}</script>


点击支付按钮,调用callpay 即可。

 

3.微信支付后的通知接口

支付成功了,微信根据你提供的notify_url,来通知你支付成功与否,虽然js里知道了结果,但这里需要正式通知,并处理业务,下面是我的代码片段:

System.out.println("-----------------微信支付来消息啦--------------------------");ResponseHandler resHandler = new ResponseHandler(request,response);resHandler.setKey(PARTNER_KEY);if (resHandler.isValidSign() == true) {if (resHandler.isWXsign() == true) {// 商户订单号String out_trade_no = resHandler.getParameter("out_trade_no");// 财付通订单号String transaction_id = resHandler.getParameter("transaction_id");// 金额,以分为单位String total_fee = resHandler.getParameter("total_fee");// 如果有使用折扣券,discount有值,total_fee+discount=原请求的total_feeString discount = resHandler.getParameter("discount");// 支付结果String trade_state = resHandler.getParameter("trade_state");System.out.println("支付的订单号:" + out_trade_no);// 判断签名及结果if ("0".equals(trade_state)) {System.out.println("哈哈,微信支付成功了");// ------------------------------// 即时到账处理业务开始// ------------------------------// 处理数据库逻辑// 注意交易单不要重复处理// 注意判断返回金额// ------------------------------// 即时到账处理业务完毕// ------------------------------System.out.println("success 后台通知成功");// 给财付通系统发送成功信息,财付通系统收到此结果后不再进行后续通知resHandler.sendToCFT("success");} else {// sha1签名失败System.out.println("fail -SHA1 failed");resHandler.sendToCFT("fail");}} else {// MD5签名失败System.out.println("fail -Md5 failed");}}


到这里OK了,支付接口完成了。

 

别忘了,还有维权接口,维权接口很简单,接收维权的数据,然后通过api告知微信处理结果就ok了。

 

看完了记得顶一下哦。。。 

 

6 0
原创粉丝点击