微信支付java版本之Native付款
程序员文章站
2024-03-13 16:22:27
最近工作中接触到一些关于微信支付方面的东西,看到给的demo都是php版本的,再加上微信支付文档写的确实不敢恭维,趟过不少坑之后闲下来做个总结。
一、前期准备&nbs...
最近工作中接触到一些关于微信支付方面的东西,看到给的demo都是php版本的,再加上微信支付文档写的确实不敢恭维,趟过不少坑之后闲下来做个总结。
一、前期准备
做微信开发首先要申请一个公共账号,申请成功后会以邮件形式发给你一些必要信息,公共账号中有开发文档以及开发中必要信息,以及测试的数据查询。
二、工具类
1.md5加密工具类
package com.pay.utils.weixin; import java.security.messagedigest; public class md5util { public final static string md5(string s) { char hexdigits[]={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}; try { byte[] btinput = s.getbytes(); // 获得md5摘要算法的 messagedigest 对象 messagedigest mdinst = messagedigest.getinstance("md5"); // 使用指定的字节更新摘要 mdinst.update(btinput); // 获得密文 byte[] md = mdinst.digest(); // 把密文转换成十六进制的字符串形式 int j = md.length; char str[] = new char[j * 2]; int k = 0; for (int i = 0; i < j; i++) { byte byte0 = md[i]; str[k++] = hexdigits[byte0 >>> 4 & 0xf]; str[k++] = hexdigits[byte0 & 0xf]; } return new string(str); } catch (exception e) { e.printstacktrace(); return null; } } }
2.commonutil工具类,用于装换成微信所需xml。以下return new string(xml.tostring().getbytes(),"iso8859-1");将工具类中的utf-8改成iso8859-1,否则微信订单中的中文会出现乱码,改后可以正确显示。
package com.pay.utils.weixin; import java.io.unsupportedencodingexception; import java.net.urlencoder; import java.util.*; import java.util.map.entry; public class commonutil { public static string createnoncestr(int length) { string chars = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz0123456789"; string res = ""; for (int i = 0; i < length; i++) { random rd = new random(); res += chars.indexof(rd.nextint(chars.length() - 1)); } return res; } public static string createnoncestr() { string chars = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz0123456789"; string res = ""; for (int i = 0; i < 16; i++) { random rd = new random(); res += chars.charat(rd.nextint(chars.length() - 1)); } return res; } public static string formatqueryparamap(hashmap<string, string> parameters) throws sdkruntimeexception { string buff = ""; try { list<map.entry<string, string>> infoids = new arraylist<map.entry<string, string>>( parameters.entryset()); collections.sort(infoids, new comparator<map.entry<string, string>>() { public int compare(map.entry<string, string> o1, map.entry<string, string> o2) { return (o1.getkey()).tostring().compareto( o2.getkey()); } }); for (int i = 0; i < infoids.size(); i++) { map.entry<string, string> item = infoids.get(i); if (item.getkey() != "") { buff += item.getkey() + "=" + urlencoder.encode(item.getvalue(), "utf-8") + "&"; } } if (buff.isempty() == false) { buff = buff.substring(0, buff.length() - 1); } } catch (exception e) { throw new sdkruntimeexception(e.getmessage()); } return buff; } public static string formatbizqueryparamap(hashmap<string, string> paramap, boolean urlencode) throws sdkruntimeexception { string buff = ""; try { list<map.entry<string, string>> infoids = new arraylist<map.entry<string, string>>( paramap.entryset()); collections.sort(infoids, new comparator<map.entry<string, string>>() { public int compare(map.entry<string, string> o1, map.entry<string, string> o2) { return (o1.getkey()).tostring().compareto( o2.getkey()); } }); for (int i = 0; i < infoids.size(); i++) { map.entry<string, string> item = infoids.get(i); //system.out.println(item.getkey()); if (item.getkey() != "") { string key = item.getkey(); string val = item.getvalue(); if (urlencode) { val = urlencoder.encode(val, "utf-8"); } buff += key.tolowercase() + "=" + val + "&"; } } if (buff.isempty() == false) { buff = buff.substring(0, buff.length() - 1); } } catch (exception e) { throw new sdkruntimeexception(e.getmessage()); } return buff; } public static boolean isnumeric(string str) { if (str.matches("\\d *")) { return true; } else { return false; } } public static string arraytoxml(hashmap<string, string> arr) { string xml = "<xml>"; iterator<entry<string, string>> iter = arr.entryset().iterator(); while (iter.hasnext()) { entry<string, string> entry = iter.next(); string key = entry.getkey(); string val = entry.getvalue(); if (isnumeric(val)) { xml += "<" + key + ">" + val + "</" + key + ">"; } else xml += "<" + key + "><![cdata[" + val + "]]></" + key + ">"; } xml += "</xml>"; try { return new string(xml.tostring().getbytes(),"iso8859-1"); } catch (unsupportedencodingexception e) { // todo auto-generated catch block e.printstacktrace(); } return ""; } }
3.clientcustomssl工具类,用于生成sign以及创建微信订单package com.pay.utils.weixin;
import java.util.arraylist; import java.util.collections; import java.util.comparator; import java.util.hashmap; import java.util.list; import java.util.map; import org.springframework.util.stringutils; /** * this example demonstrates how to create secure connections with a custom ssl * context. */ public class clientcustomssl { public static string getbizsign(hashmap<string, string> bizobj) throws sdkruntimeexception { hashmap<string, string> bizparameters = new hashmap<string, string>(); list<map.entry<string, string>> infoids = new arraylist<map.entry<string, string>>( bizobj.entryset()); system.out.println(infoids); collections.sort(infoids, new comparator<map.entry<string, string>>() { public int compare(map.entry<string, string> o1, map.entry<string, string> o2) { return (o1.getkey()).tostring().compareto(o2.getkey()); } }); system.out.println("--------------------"); system.out.println(infoids); for (int i = 0; i < infoids.size(); i++) { map.entry<string, string> item = infoids.get(i); if (item.getkey() != "") { bizparameters.put(item.getkey().tolowercase(), item.getvalue()); } } //bizparameters.put("key", "12345678123456781234567812345671"); string bizstring = commonutil.formatbizqueryparamap(bizparameters, false); bizstring += "&key=12345678123456781234567812345671"; system.out.println("***************"); system.out.println(bizstring); // return sha1util.sha1(bizstring); return md5util.md5(bizstring); } /** * 微信创建订单 * @param noncestr * @param orderdescribe * @param orderno * @param price * @param timestart * @param timeexpire * @return * @throws sdkruntimeexception */ public static string createnativepackage(string noncestr,string orderdescribe,string orderno,string price,string timestart,string timeexpire) throws sdkruntimeexception { hashmap<string, string> nativeobj = new hashmap<string, string>(); nativeobj.put("appid", "见公众账号"); //公众账号id nativeobj.put("mch_id", "见邮件"); //商户号 nativeobj.put("nonce_str", noncestr); //随机字符串 nativeobj.put("body", orderdescribe); //商品描述 nativeobj.put("attach", "tradeno"); //附加数据 nativeobj.put("out_trade_no", orderno); //商户订单号(全局唯一) nativeobj.put("total_fee", price); //总金额(单位为分,不能带小数点) nativeobj.put("spbill_create_ip","192.168.0.144"); //终端ip nativeobj.put("time_start", timestart); //交易起始时间 nativeobj.put("time_expire", timeexpire); //交易结束时间 nativeobj.put("notify_url", customizedpropertyplaceholderconfigurer.getcontextproperty("wxurl")+"/weixin_callback/weixincallback/init.action"); //回调通知地址 nativeobj.put("trade_type", "native"); //交易类型 string sign = getbizsign(nativeobj); nativeobj.put("sign", sign.touppercase()); return commonutil.arraytoxml(nativeobj); } /** * 微信订单支付查询 * @param noncestr * @param orderdescribe * @param orderno * @param price * @param timestart * @param timeexpire * @return * @throws sdkruntimeexception */ public static string searchnativepackage(string transactionid,string outtradeno,string noncestr) throws sdkruntimeexception { hashmap<string, string> nativeobj = new hashmap<string, string>(); nativeobj.put("appid", "见公众共账号"); //公众账号id nativeobj.put("mch_id", "见邮件");//商户号 nativeobj.put("nonce_str", noncestr);//随机字符串 if(!stringutils.isempty(transactionid)){ nativeobj.put("transaction_id", transactionid); } if(!stringutils.isempty(outtradeno)){ nativeobj.put("out_trade_no", outtradeno);//随机字符串 } string sign = getbizsign(nativeobj); nativeobj.put("sign", sign.touppercase()); return commonutil.arraytoxml(nativeobj); /** * 微信退款 * @param outtradeno * @param outrefundno * @param totalfee * @param refundfee * @return * @throws sdkruntimeexception */ public static string refundnativepackage(string outtradeno,string outrefundno,string totalfee,string refundfee,string noncestr) throws sdkruntimeexception { hashmap<string, string> nativeobj = new hashmap<string, string>(); nativeobj.put("appid", "见公众账号");//公众账号id nativeobj.put("mch_id", "见邮件");//商户号 nativeobj.put("nonce_str", noncestr);//随机字符串 nativeobj.put("out_trade_no", outtradeno);//商户订单号(全局唯一) nativeobj.put("out_refund_no", outrefundno);//商户退款单号(全局唯一) nativeobj.put("total_fee", totalfee);//总金额(单位为分,不能带小数点) nativeobj.put("refund_fee", refundfee);//退款金额(单位为分,不能带小数点) nativeobj.put("op_user_id", "邮件"); string sign = getbizsign(nativeobj); nativeobj.put("sign", sign.touppercase()); return commonutil.arraytoxml(nativeobj); } /** * 微信待支付 * @param noncestr * @param orderdescribe * @param orderno * @param price * @param timestart * @param timeexpire * @return * @throws sdkruntimeexception */ public static string createjsapipackage(string noncestr,string orderdescribe,string orderno,string price,string timestart,string timeexpire,string openid) throws sdkruntimeexception { hashmap<string, string> nativeobj = new hashmap<string, string>(); nativeobj.put("appid", "见公众账号");//公众账号id nativeobj.put("openid", openid);//公众账号id nativeobj.put("mch_id", "见邮件")//商户号 nativeobj.put("nonce_str", noncestr);//随机字符串 nativeobj.put("body", orderdescribe);//商品描述 nativeobj.put("attach", "tradeno");//附加数据 nativeobj.put("out_trade_no", orderno);//商户订单号(全局唯一) nativeobj.put("total_fee", price);//总金额(单位为分,不能带小数点) nativeobj.put("spbill_create_ip","192.168.0.144");//终端ip nativeobj.put("time_start", timestart);//交易起始时间 nativeobj.put("time_expire", timeexpire)//交易结束时间 nativeobj.put("notify_url",customizedpropertyplaceholderconfigurer.getcontextproperty("wxurl")+"/weixin_callback/weixincallback/init.action");//通知地址 nativeobj.put("trade_type", "jsapi");//交易类型 string sign = getbizsign(nativeobj); nativeobj.put("sign", sign.touppercase()); return commonutil.arraytoxml(nativeobj); } /** * 微信关闭订单 * @param noncestr * @param orderdescribe * @param orderno * @param price * @param timestart * @param timeexpire * @param openid * @return * @throws sdkruntimeexception */ public static string createcloseorder(string outtradeno,string noncestr) throws sdkruntimeexception { hashmap<string, string> nativeobj = new hashmap<string, string>(); nativeobj.put("appid", "见公众账号");//公众账号id nativeobj.put("mch_id", "见邮件");//商户号 nativeobj.put("out_trade_no", outtradeno);//商户订单号(全局唯一) nativeobj.put("nonce_str", noncestr);//随机字符串 string sign = getbizsign(nativeobj); nativeobj.put("sign", sign.touppercase()); return commonutil.arraytoxml(nativeobj); } }
4.调用微信支付接口
package com.pay.controller.weixin; import java.io.file; import java.io.fileinputstream; import java.security.keystore; import java.text.simpledateformat; import java.util.date; import java.util.list; import javax.net.ssl.sslcontext; import javax.servlet.http.httpservletrequest; import javax.servlet.http.httpservletresponse; import net.sf.json.jsonarray; import net.sf.json.jsonobject; import org.apache.http.httpentity; import org.apache.http.client.methods.closeablehttpresponse; import org.apache.http.client.methods.httppost; import org.apache.http.conn.ssl.sslconnectionsocketfactory; import org.apache.http.conn.ssl.sslcontexts; import org.apache.http.entity.stringentity; import org.apache.http.impl.client.closeablehttpclient; import org.apache.http.impl.client.httpclients; import org.apache.http.util.entityutils; import org.dom4j.document; import org.dom4j.documenthelper; import org.dom4j.element; import org.dom4j.io.saxreader; import org.springframework.beans.factory.annotation.autowired; import org.springframework.http.httpstatus; import org.springframework.web.bind.annotation.requestbody; import org.springframework.web.bind.annotation.requestmapping; import org.springframework.web.bind.annotation.requestmethod; import org.springframework.web.bind.annotation.responsestatus; import org.springframework.web.bind.annotation.restcontroller; import com.pay.bo.payhist; import com.pay.constants.payhistorypaystatus; import com.pay.constants.payhistorypaytype; import com.pay.service.weixinpayservice; import com.pay.utils.weixin.clientcustomssl; import com.pay.utils.weixin.closeweixinorderutils; import com.pay.utils.weixin.customizedpropertyplaceholderconfigurer; @restcontroller @requestmapping("/pay") public class weixinpaycontroller { @autowired weixinpayservice weixinpayservice; private static long standardtime = 1662652800000l; /** * 返回生成二维码的url * @param request * @param response * @return */ @requestmapping(value="/geturl",method=requestmethod.post) @responsestatus(httpstatus.ok) public object geturl(httpservletresponse response,@requestbody string body){ try{ jsonobject jsono = jsonobject.fromobject(body); payhist ph = null; // list<map<string,object>> td = weixinpayservice.gettrade(orderno); date dt = new date(); simpledateformat sdf = new simpledateformat("yyyymmddhhmmss"); string noncestr = sdf.format(dt).tostring(); date now = new date(); string tradepayno = jsono.get("orderno").tostring()+string.format("%10d",standardtime - now.gettime()).substring(0, 10); system.out.println("订单标号orderno======="+jsono.get("orderno").tostring()); system.out.println("10位随机数======="+string.format("%10d",standardtime - now.gettime()).substring(0, 10)); string price = math.round(float.valueof(jsono.get("price").tostring())*100)+""; long timeexpirestrold = dt.gettime(); long timenew = long.parselong(customizedpropertyplaceholderconfigurer.getcontextproperty("weixin.send2finish.overtime").tostring()); long timeexpirenew = timeexpirestrold+timenew; date dttimeexpire = new date(timeexpirenew); simpledateformat dtsdf = new simpledateformat("yyyymmddhhmmss"); string timeexpire = dtsdf.format(dttimeexpire).tostring(); system.out.println("noncestr=="+noncestr); system.out.println("orderno=="+jsono.get("orderno").tostring()); system.out.println("price=="+price); system.out.println("timestart=="+noncestr); system.out.println("timeexpire=="+timeexpire); jsonobject result = (jsonobject) seturl(noncestr,"订单",tradepayno,price,noncestr,timeexpire); if(result.get("status").tostring().equals("success")){ ph = new payhist(); ph.settradepayurl(result.getstring("weixinpayurl"));//此字段为支付链接,可以此链接生成二维码扫码支付 ph.setpaytradeno(jsono.get("orderno").tostring()); ph.settradepayno(tradepayno); ph.setpaystatus(payhistorypaystatus.wechat_pay_status_wait); ph.setpaytype(payhistorypaytype.wechat); ph.setappkey(jsono.getstring("appkey").tostring()); ph.setpayamount(price); result.put("paytradeno", ph.getpaytradeno()); result.put("tradepayno", ph.gettradepayno()); result.put("paystatus", ph.getpaystatus()); result.put("paytype", ph.getpaytype()); } return result; }catch(exception e){ e.printstacktrace(); jsonobject result = new jsonobject(); result.put("status","error"); result.put("msg",e.getmessage()); // return result.tostring(); } return null; } public object seturl(string noncestr,string orderdescribe,string orderno,string price,string timestart,string timeexpire) { try{ keystore keystore = keystore.getinstance("pkcs12"); fileinputstream instream = new fileinputstream(new file(微信证书绝对路径)); try { keystore.load(instream, "商户id".tochararray()); }finally { instream.close(); } // trust own ca and all self-signed certs sslcontext sslcontext = sslcontexts.custom().loadkeymaterial(keystore,<span style="font-family: arial, helvetica, sans-serif;">商户id</span>.tochararray()).build(); // allow tlsv1 protocol only sslconnectionsocketfactory sslsf = new sslconnectionsocketfactory( sslcontext, new string[] { "tlsv1" }, null, sslconnectionsocketfactory.allow_all_hostname_verifier); closeablehttpclient httpclient = httpclients.custom() .setsslsocketfactory(sslsf).build(); // httpget httpget = new // httpget("https://api.mch.weixin.qq.com/secapi/pay/refund"); httppost httppost = new httppost( "https://api.mch.weixin.qq.com/pay/unifiedorder"); string xml = clientcustomssl.createnativepackage(noncestr,orderdescribe,orderno,price,timestart,timeexpire); try { stringentity se = new stringentity(xml); httppost.setentity(se); system.out.println("executing request" + httppost.getrequestline()); closeablehttpresponse responseentry = httpclient.execute(httppost); try { httpentity entity = responseentry.getentity(); system.out.println("----------------------------------------"); system.out.println(responseentry.getstatusline()); if (entity != null) { system.out.println("response content length: " + entity.getcontentlength()); /* bufferedreader bufferedreader = new bufferedreader( new inputstreamreader(entity.getcontent())); string text; while ((text = bufferedreader.readline()) != null) { system.out.println("======="+text); }*/ saxreader saxreader = new saxreader(); document document = saxreader.read(entity.getcontent()); element rootelt = document.getrootelement(); system.out.println("根节点:" + rootelt.getname()); system.out.println("==="+rootelt.elementtext("result_code")); system.out.println("==="+rootelt.elementtext("return_msg")); string resultcode = rootelt.elementtext("result_code"); jsonobject result = new jsonobject(); document documentxml =documenthelper.parsetext(xml); element rooteltxml = documentxml.getrootelement(); if(resultcode.equals("success")){ system.out.println("=================prepay_id===================="+ rootelt.elementtext("prepay_id")); system.out.println("=================sign===================="+ rooteltxml.elementtext("sign")); result.put("weixinpayurl", rootelt.elementtext("code_url")); result.put("prepayid", rootelt.elementtext("prepay_id")); result.put("status","success"); result.put("msg","success"); }else{ result.put("status","false"); result.put("msg",rootelt.elementtext("err_code_des")); } return result; } entityutils.consume(entity); } finally { responseentry.close(); } } finally { httpclient.close(); } return null; }catch(exception e){ e.printstacktrace(); jsonobject result = new jsonobject(); result.put("status","error"); result.put("msg",e.getmessage()); return result; } } }
httpclient jar包和json jar包:下载地址。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: State
下一篇: Java抽奖算法第二例