java微信公众号支付示例详解
本文实例为大家分享了java微信公众号支付示例代码,供大家参考,具体内容如下
开始之前,先准备好:appid、商家号、商户密匙。
工具类:
MD5Util.java
packagecom.yiexpress.core.utils.wechat; importjava.security.MessageDigest; /** *MD5工具类 */ publicclassMD5Util{ publicfinalstaticStringMD5(Strings){ charhexDigits[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; try{ byte[]btInput=s.getBytes(); MessageDigestmdInst=MessageDigest.getInstance("MD5"); mdInst.update(btInput); byte[]md=mdInst.digest(); intj=md.length; charstr[]=newchar[j*2]; intk=0; for(inti=0;i>>4&0xf]; str[k++]=hexDigits[byte0&0xf]; } Stringmd5Str=newString(str); returnmd5Str; }catch(Exceptione){ e.printStackTrace(); returnnull; } } }
SapUtils.java
packagecom.yiexpress.core.utils; importjava.lang.reflect.*; importjava.util.List; importjava.io.IOException; importjava.io.StringWriter; importorg.dom4j.Document; importorg.dom4j.DocumentHelper; importorg.dom4j.Element; importorg.dom4j.io.OutputFormat; importorg.dom4j.io.XMLWriter; importorg.slf4j.Logger; importorg.slf4j.LoggerFactory; importorg.springframework.util.StringUtils; publicclassSapUtils{ privatestaticfinalLoggerlogger=LoggerFactory.getLogger(SapUtils.class); /**根据反射对javabean转成xml文件的格式 *以类名为第一标签,所有属性作为第二节点,并放入对应的值,如果属性为空就不放入该熟悉 *@paramdto传入的对象 *@paramoperationName操作名称 *@return */ publicstaticStringformatToXml(Objectdto,StringoperationName){ logger.info("解析当前类{}为指定的xml文档格式的数据",dto.getClass().getName()); logger.info("当前的同步方法是,{}",operationName); Stringresult=null; Fieldfields[]=dto.getClass().getDeclaredFields();//dto是实体类名称 //DocumentHelper提供了创建Document对象的方法 Documentdocument=DocumentHelper.createDocument(); //添加节点信息 StringclassName=dto.getClass().getName(); //操作的名称 ElementrootElement=document.addElement(operationName); try{ Field.setAccessible(fields,true); for(inti=0;itype=fields[i].getType(); //如果是list if(type==List.class){ StringlistName=fields[i].getName(); createElement(rootElement,fields[i].get(dto),listName); } else{ Elementelement=rootElement.addElement(fields[i].getName()); element.setText((String)fields[i].get(dto)); } } } //设置XML文档格式 OutputFormatoutputFormat=OutputFormat.createPrettyPrint(); //设置XML编码方式,即是用指定的编码方式保存XML文档到字符串(String),这里也可以指定为GBK或是ISO8859-1 outputFormat.setEncoding("UTF-8"); //outputFormat.setSuppressDeclaration(true);//是否生产xml头 outputFormat.setIndent(true);//设置是否缩进 outputFormat.setIndent("");//以四个空格方式实现缩进 outputFormat.setNewlines(true);//设置是否换行 StringWriterstringWriter=null; //WriterfileWriter=null; //xmlWriter是用来把XML文档写入字符串的(工具) XMLWriterxmlWriter=null; try{ //stringWriter字符串是用来保存XML文档的 stringWriter=newStringWriter(); //fileWriter=newFileWriter("D:\\modu11le.xml"); //xmlWriter是用来把XML文档写入字符串的(工具) xmlWriter=newXMLWriter(stringWriter,outputFormat); //把创建好的XML文档写入字符串 xmlWriter.write(document); //fileWriter.write(stringWriter.toString()); result=stringWriter.toString(); }catch(IOExceptione){ logger.error("写入数据失败"); thrownewRuntimeException("写入数据失败"+e); }finally{ try{ if(xmlWriter!=null){ xmlWriter.flush(); xmlWriter.close(); } /*if(fileWriter!=null){ fileWriter.flush(); fileWriter.close(); }*/ }catch(IOExceptione){ logger.error("关闭输出流出错"); thrownewRuntimeException("关闭输出流出错"+e); } } }catch(Exceptione){ logger.error("添加xml的节点失败"+e); } logger.error("转换xml结束"); returnresult; } /** *添加类中的list *@paramelement *@paramobject *@paramname *@return *@throwsIllegalArgumentException *@throwsIllegalAccessException */ publicstaticElementcreateElement(Elementelement,Objectobject,Stringname)throwsIllegalArgumentException,IllegalAccessException{ ElementnameElement=element.addElement(name); Listinfo=(List)object; for(intj=0;j UnifiedOrderRequest.java
packagecom.yiexpress.core.utils.wechat; publicclassUnifiedOrderRequest{ privateStringappid;//公众账号ID privateStringmch_id;//商户号 privateStringdevice_info;//设备号否 privateStringnonce_str;//随机字符串 privateStringsign;//签名 privateStringsign_type;//签名类型 privateStringbody;//商品描述 privateStringdetail;//商品详情 privateStringattach;//附加数据 privateStringout_trade_no;//商户订单号 privateStringfee_type;//标价币种 privateStringtotal_fee;//标价金额 privateStringspbill_create_ip;//终端IP privateStringtime_start;//交易起始时间 privateStringtime_expire;//交易结束时间 privateStringgoods_tag;//订单优惠标记 privateStringnotify_url;//通知地址 privateStringtrade_type;//交易类型 privateStringproduct_id;//商品ID privateStringlimit_pay;//指定支付方式 privateStringopenid;//用户标识 publicStringgetAppid(){ returnappid; } publicvoidsetAppid(Stringappid){ this.appid=appid; } publicStringgetMch_id(){ returnmch_id; } publicvoidsetMch_id(Stringmch_id){ this.mch_id=mch_id; } publicStringgetDevice_info(){ returndevice_info; } publicvoidsetDevice_info(Stringdevice_info){ this.device_info=device_info; } publicStringgetNonce_str(){ returnnonce_str; } publicvoidsetNonce_str(Stringnonce_str){ this.nonce_str=nonce_str; } publicStringgetSign(){ returnsign; } publicvoidsetSign(Stringsign){ this.sign=sign; } publicStringgetSign_type(){ returnsign_type; } publicvoidsetSign_type(Stringsign_type){ this.sign_type=sign_type; } publicStringgetBody(){ returnbody; } publicvoidsetBody(Stringbody){ this.body=body; } publicStringgetDetail(){ returndetail; } publicvoidsetDetail(Stringdetail){ this.detail=detail; } publicStringgetAttach(){ returnattach; } publicvoidsetAttach(Stringattach){ this.attach=attach; } publicStringgetOut_trade_no(){ returnout_trade_no; } publicvoidsetOut_trade_no(Stringout_trade_no){ this.out_trade_no=out_trade_no; } publicStringgetFee_type(){ returnfee_type; } publicvoidsetFee_type(Stringfee_type){ this.fee_type=fee_type; } publicStringgetTotal_fee(){ returntotal_fee; } publicvoidsetTotal_fee(Stringtotal_fee){ this.total_fee=total_fee; } publicStringgetSpbill_create_ip(){ returnspbill_create_ip; } publicvoidsetSpbill_create_ip(Stringspbill_create_ip){ this.spbill_create_ip=spbill_create_ip; } publicStringgetTime_start(){ returntime_start; } publicvoidsetTime_start(Stringtime_start){ this.time_start=time_start; } publicStringgetTime_expire(){ returntime_expire; } publicvoidsetTime_expire(Stringtime_expire){ this.time_expire=time_expire; } publicStringgetGoods_tag(){ returngoods_tag; } publicvoidsetGoods_tag(Stringgoods_tag){ this.goods_tag=goods_tag; } publicStringgetNotify_url(){ returnnotify_url; } publicvoidsetNotify_url(Stringnotify_url){ this.notify_url=notify_url; } publicStringgetTrade_type(){ returntrade_type; } publicvoidsetTrade_type(Stringtrade_type){ this.trade_type=trade_type; } publicStringgetProduct_id(){ returnproduct_id; } publicvoidsetProduct_id(Stringproduct_id){ this.product_id=product_id; } publicStringgetLimit_pay(){ returnlimit_pay; } publicvoidsetLimit_pay(Stringlimit_pay){ this.limit_pay=limit_pay; } publicStringgetOpenid(){ returnopenid; } publicvoidsetOpenid(Stringopenid){ this.openid=openid; } }UnifiedOrderRespose.java
packagecom.yiexpress.core.utils.wechat; publicclassUnifiedOrderRespose{ privateStringreturn_code;//返回状态码 privateStringreturn_msg;//返回信息 privateStringappid;//公众账号ID privateStringmch_id;//商户号 privateStringdevice_info;//设备号 privateStringnonce_str;//随机字符串 privateStringsign;//签名 privateStringresult_code;//业务结果 privateStringerr_code;//错误代码 privateStringerr_code_des;//错误代码描述 privateStringtrade_type;//交易类型 privateStringprepay_id;//预支付交易会话标识 privateStringcode_url;//二维码链接 publicStringgetReturn_code(){ returnreturn_code; } publicvoidsetReturn_code(Stringreturn_code){ this.return_code=return_code; } publicStringgetReturn_msg(){ returnreturn_msg; } publicvoidsetReturn_msg(Stringreturn_msg){ this.return_msg=return_msg; } publicStringgetAppid(){ returnappid; } publicvoidsetAppid(Stringappid){ this.appid=appid; } publicStringgetMch_id(){ returnmch_id; } publicvoidsetMch_id(Stringmch_id){ this.mch_id=mch_id; } publicStringgetDevice_info(){ returndevice_info; } publicvoidsetDevice_info(Stringdevice_info){ this.device_info=device_info; } publicStringgetNonce_str(){ returnnonce_str; } publicvoidsetNonce_str(Stringnonce_str){ this.nonce_str=nonce_str; } publicStringgetSign(){ returnsign; } publicvoidsetSign(Stringsign){ this.sign=sign; } publicStringgetResult_code(){ returnresult_code; } publicvoidsetResult_code(Stringresult_code){ this.result_code=result_code; } publicStringgetErr_code(){ returnerr_code; } publicvoidsetErr_code(Stringerr_code){ this.err_code=err_code; } publicStringgetErr_code_des(){ returnerr_code_des; } publicvoidsetErr_code_des(Stringerr_code_des){ this.err_code_des=err_code_des; } publicStringgetTrade_type(){ returntrade_type; } publicvoidsetTrade_type(Stringtrade_type){ this.trade_type=trade_type; } publicStringgetPrepay_id(){ returnprepay_id; } publicvoidsetPrepay_id(Stringprepay_id){ this.prepay_id=prepay_id; } publicStringgetCode_url(){ returncode_url; } publicvoidsetCode_url(Stringcode_url){ this.code_url=code_url; } }WXPayConstants.java
packagecom.yiexpress.core.utils.wechat; publicclassWXPayConstants{ publicenumSignType{ MD5,HMACSHA256 } publicstaticfinalStringFAIL="FAIL"; publicstaticfinalStringSUCCESS="SUCCESS"; publicstaticfinalStringHMACSHA256="HMAC-SHA256"; publicstaticfinalStringMD5="MD5"; publicstaticfinalStringFIELD_SIGN="sign"; publicstaticfinalStringFIELD_SIGN_TYPE="sign_type"; }WXPayUtil.java
packagecom.yiexpress.core.utils.wechat; importjava.io.BufferedOutputStream; importjava.io.BufferedReader; importjava.io.ByteArrayInputStream; importjava.io.InputStream; importjava.io.InputStreamReader; importjava.io.StringWriter; importjava.io.Writer; importjava.net.HttpURLConnection; importjava.net.URL; importjava.util.*; importjava.security.MessageDigest; importorg.w3c.dom.Node; importorg.w3c.dom.NodeList; importcom.yiexpress.core.utils.SapUtils; importcom.yiexpress.core.utils.XmlUtil; importcom.yiexpress.core.utils.wechat.WXPayConstants.SignType; importjavax.crypto.Mac; importjavax.crypto.spec.SecretKeySpec; importjavax.xml.parsers.DocumentBuilder; importjavax.xml.parsers.DocumentBuilderFactory; importjavax.xml.transform.OutputKeys; importjavax.xml.transform.Transformer; importjavax.xml.transform.TransformerFactory; importjavax.xml.transform.dom.DOMSource; importjavax.xml.transform.stream.StreamResult; importorg.jdom2.Document; importorg.jdom2.Element; importorg.jdom2.input.SAXBuilder; importorg.slf4j.Logger; importorg.slf4j.LoggerFactory; /** *支付工具类 */ publicclassWXPayUtil{ privatestaticLoggerlog=LoggerFactory.getLogger(WXPayUtil.class); /** *生成订单对象信息 *@paramorderId订单号 *@paramappId微信appId *@parammch_id微信分配的商户ID *@parambody支付介绍主体 *@paramprice支付价格(放大100倍) *@paramspbill_create_ip终端IP *@paramnotify_url异步直接结果通知接口地址 *@paramnoncestr *@return */ publicstaticMapcreateOrderInfo(Map requestMap,StringshopKey){ //生成订单对象 UnifiedOrderRequestunifiedOrderRequest=newUnifiedOrderRequest(); unifiedOrderRequest.setAppid(requestMap.get("appId"));//公众账号ID unifiedOrderRequest.setBody(requestMap.get("body"));//商品描述 unifiedOrderRequest.setMch_id(requestMap.get("mch_id"));//商户号 unifiedOrderRequest.setNonce_str(requestMap.get("noncestr"));//随机字符串 unifiedOrderRequest.setNotify_url(requestMap.get("notify_url"));//通知地址 unifiedOrderRequest.setOpenid(requestMap.get("userWeixinOpenId")); unifiedOrderRequest.setDetail(requestMap.get("detail"));//详情 unifiedOrderRequest.setOut_trade_no(requestMap.get("out_trade_no"));//商户订单号 unifiedOrderRequest.setSpbill_create_ip(requestMap.get("spbill_create_ip"));//终端IP unifiedOrderRequest.setTotal_fee(requestMap.get("payMoney"));//金额需要扩大100倍:1代表支付时是0.01 unifiedOrderRequest.setTrade_type("JSAPI");//JSAPI--公众号支付、NATIVE--原生扫码支付、APP--app支付 SortedMap packageParams=newTreeMap (); packageParams.put("appid",unifiedOrderRequest.getAppid()); packageParams.put("body",unifiedOrderRequest.getBody()); packageParams.put("mch_id",unifiedOrderRequest.getMch_id()); packageParams.put("nonce_str",unifiedOrderRequest.getNonce_str()); packageParams.put("notify_url",unifiedOrderRequest.getNotify_url()); packageParams.put("openid",unifiedOrderRequest.getOpenid()); packageParams.put("detail",unifiedOrderRequest.getDetail()); packageParams.put("out_trade_no",unifiedOrderRequest.getOut_trade_no()); packageParams.put("spbill_create_ip",unifiedOrderRequest.getSpbill_create_ip()); packageParams.put("total_fee",unifiedOrderRequest.getTotal_fee()); packageParams.put("trade_type",unifiedOrderRequest.getTrade_type()); try{ unifiedOrderRequest.setSign(generateSignature(packageParams,shopKey));//签名 }catch(Exceptione){ e.printStackTrace(); } //将订单对象转为xml格式 Stringorderstr=SapUtils.formatToXml(unifiedOrderRequest,"xml").replace("",""); log.debug("封装好的统一下单请求数据:"+orderstr.replace("__","_")); Map responseMap=newHashMap (); responseMap.put("orderInfo_toString",orderstr.replace("__","_")); responseMap.put("unifiedOrderRequest",unifiedOrderRequest); returnresponseMap; } publicstaticvoidmain(String[]args){ //UnifiedOrderRequestut=newUnifiedOrderRequest(); //ut.setAppid("wx1234156789"); //ut.setBody("内容body"); //ut.setMch_id("商户号"); //ut.setNonce_str("随机字符串"); //ut.setNotify_url("回调地址"); //ut.setOpenid("openid"); //ut.setDetail("详情"); //ut.setOut_trade_no("订单号"); //ut.setSpbill_create_ip("终端IP"); //ut.setTotal_fee("金额"); //ut.setTrade_type("调用类型JSAPI"); //System.out.println("---"+SapUtils.formatToXml(ut,"xml")+"---"); //UnifiedOrderRequestunifiedOrderRequest=newUnifiedOrderRequest(); //unifiedOrderRequest.setAppid("dsfsdf");//公众账号ID //unifiedOrderRequest.setBody("sdfsdf");//商品描述 //unifiedOrderRequest.setMch_id("sdfsd");//商户号 //unifiedOrderRequest.setNonce_str("dfsd");//随机字符串 //unifiedOrderRequest.setNotify_url("sdfdsf");//通知地址 //unifiedOrderRequest.setOpenid("sdfsdf"); // //unifiedOrderRequest.setTrade_type("JSAPI");//JSAPI--公众号支付、NATIVE--原生扫码支付、APP--app支付 // //System.out.println("---"+SapUtils.formatToXml(unifiedOrderRequest,"xml").replace("","")+"---"); //Stringstr=" "; //UnifiedOrderRequests=SapUtils.getBeanByxml(str,UnifiedOrderRequest.class); //System.out.println(s.getAppid()+"---"+s.getMch_id()+"--"+s.getFee_type()); } /** *生成签名 *@paramappid_value *@parammch_id_value *@paramproductId *@paramnonce_str_value *@paramtrade_type *@paramnotify_url *@paramspbill_create_ip *@paramtotal_fee *@paramout_trade_no *@return */ privatestaticStringcreateSign(UnifiedOrderRequestunifiedOrderRequest,StringshopKey){ //根据规则创建可排序的map集合 SortedMap dsfsdf sdfsd dfsd sdfsdfsdfdsf JSAPI sdfsdf packageParams=newTreeMap (); packageParams.put("appid",unifiedOrderRequest.getAppid()); packageParams.put("body",unifiedOrderRequest.getBody()); packageParams.put("mch_id",unifiedOrderRequest.getMch_id()); packageParams.put("nonce_str",unifiedOrderRequest.getNonce_str()); packageParams.put("notify_url",unifiedOrderRequest.getNotify_url()); packageParams.put("out_trade_no",unifiedOrderRequest.getOut_trade_no()); packageParams.put("spbill_create_ip",unifiedOrderRequest.getSpbill_create_ip()); packageParams.put("trade_type",unifiedOrderRequest.getTrade_type()); packageParams.put("total_fee",unifiedOrderRequest.getTotal_fee()); StringBuffersb=newStringBuffer(); Setes=packageParams.entrySet();//字典序 Iteratorit=es.iterator(); while(it.hasNext()){ Map.Entryentry=(Map.Entry)it.next(); Stringk=(String)entry.getKey(); Stringv=(String)entry.getValue(); //为空不参与签名、参数名区分大小写 if(null!=v&&!"".equals(v)&&!"sign".equals(k)&&!"key".equals(k)){ sb.append(k+"="+v+"&"); } } //第二步拼接key,key设置路径:微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置 sb.append("key="+shopKey); Stringsign=MD5Util.MD5(sb.toString()).toUpperCase();//MD5加密 log.error("方式一生成的签名="+sign); returnsign; } //xml解析 publicstaticSortedMap doXMLParseWithSorted(Stringstrxml)throwsException{ strxml=strxml.replaceFirst("encoding=\".*\"","encoding=\"UTF-8\""); if(null==strxml||"".equals(strxml)){ returnnull; } SortedMap m=newTreeMap (); InputStreamin=newByteArrayInputStream(strxml.getBytes("UTF-8")); SAXBuilderbuilder=newSAXBuilder(); Documentdoc=builder.build(in); Elementroot=doc.getRootElement(); Listlist=root.getChildren(); Iteratorit=list.iterator(); while(it.hasNext()){ Elemente=(Element)it.next(); Stringk=e.getName(); Stringv=""; Listchildren=e.getChildren(); if(children.isEmpty()){ v=e.getTextNormalize(); }else{ v=getChildrenText(children); } m.put(k,v); } //关闭流 in.close(); returnm; } publicstaticStringgetChildrenText(Listchildren){ StringBuffersb=newStringBuffer(); if(!children.isEmpty()){ Iteratorit=children.iterator(); while(it.hasNext()){ Elemente=(Element)it.next(); Stringname=e.getName(); Stringvalue=e.getTextNormalize(); Listlist=e.getChildren(); sb.append("<"+name+">"); if(!list.isEmpty()){ sb.append(getChildrenText(list)); } sb.append(value); sb.append(""+name+">"); } } returnsb.toString(); } /** *调统一下单API *@paramorderInfo *@return */ publicstaticUnifiedOrderResposehttpOrder(StringorderInfo,intindex){ //统一下单接口地址自动适应1中国境内2东南亚3其他 String[]urlList={"https://api.mch.weixin.qq.com/pay/unifiedorder","https://apihk.mch.weixin.qq.com/pay/unifiedorder" ,"https://apius.mch.weixin.qq.com/pay/unifiedorder"}; //Stringurl="https://api.mch.weixin.qq.com/pay/unifiedorder"; try{ HttpURLConnectionconn=(HttpURLConnection)newURL(urlList[index]).openConnection(); //加入数据 conn.setRequestMethod("POST"); conn.setDoOutput(true); BufferedOutputStreambuffOutStr=newBufferedOutputStream(conn.getOutputStream()); buffOutStr.write(orderInfo.getBytes("UTF-8")); buffOutStr.flush(); buffOutStr.close(); //获取输入流 BufferedReaderreader=newBufferedReader(newInputStreamReader(conn.getInputStream(),"UTF-8")); Stringline=null; StringBuffersb=newStringBuffer(); while((line=reader.readLine())!=null){ sb.append(line); } //xml转对象 UnifiedOrderResposeunifiedOrderRespose=XmlUtil.getBeanByxml(sb.toString(),UnifiedOrderRespose.class); returnunifiedOrderRespose; }catch(Exceptione){ e.printStackTrace(); } returnnull; } /** *XML格式字符串转换为Map * *@paramstrXMLXML字符串 *@returnXML数据转换后的Map *@throwsException */ publicstaticMap xmlToMap(StringstrXML)throwsException{ try{ Map data=newHashMap (); DocumentBuilderFactorydocumentBuilderFactory=DocumentBuilderFactory.newInstance(); DocumentBuilderdocumentBuilder=documentBuilderFactory.newDocumentBuilder(); InputStreamstream=newByteArrayInputStream(strXML.getBytes("UTF-8")); org.w3c.dom.Documentdoc=documentBuilder.parse(stream); doc.getDocumentElement().normalize(); NodeListnodeList=doc.getDocumentElement().getChildNodes(); for(intidx=0;idx data)throwsException{ DocumentBuilderFactorydocumentBuilderFactory=DocumentBuilderFactory.newInstance(); DocumentBuilderdocumentBuilder=documentBuilderFactory.newDocumentBuilder(); org.w3c.dom.Documentdocument=documentBuilder.newDocument(); org.w3c.dom.Elementroot=document.createElement("xml"); document.appendChild(root); for(Stringkey:data.keySet()){ Stringvalue=data.get(key); if(value==null){ value=""; } value=value.trim(); org.w3c.dom.Elementfiled=document.createElement(key); filed.appendChild(document.createTextNode(value)); root.appendChild(filed); } TransformerFactorytf=TransformerFactory.newInstance(); Transformertransformer=tf.newTransformer(); DOMSourcesource=newDOMSource(document); transformer.setOutputProperty(OutputKeys.ENCODING,"UTF-8"); transformer.setOutputProperty(OutputKeys.INDENT,"yes"); StringWriterwriter=newStringWriter(); StreamResultresult=newStreamResult(writer); transformer.transform(source,result); Stringoutput=writer.getBuffer().toString();//.replaceAll("\n|\r",""); try{ writer.close(); } catch(Exceptionex){ } returnoutput; } /** *生成带有sign的XML格式字符串 * *@paramdataMap类型数据 *@paramkeyAPI密钥 *@return含有sign字段的XML */ publicstaticStringgenerateSignedXml(finalMap data,Stringkey)throwsException{ returngenerateSignedXml(data,key,SignType.MD5); } /** *生成带有sign的XML格式字符串 * *@paramdataMap类型数据 *@paramkeyAPI密钥 *@paramsignType签名类型 *@return含有sign字段的XML */ publicstaticStringgenerateSignedXml(finalMap data,Stringkey,SignTypesignType)throwsException{ Stringsign=generateSignature(data,key,signType); data.put(WXPayConstants.FIELD_SIGN,sign); returnmapToXml(data); } /** *判断签名是否正确 * *@paramxmlStrXML格式数据 *@paramkeyAPI密钥 *@return签名是否正确 *@throwsException */ publicstaticbooleanisSignatureValid(StringxmlStr,Stringkey)throwsException{ Map data=xmlToMap(xmlStr); if(!data.containsKey(WXPayConstants.FIELD_SIGN)){ returnfalse; } Stringsign=data.get(WXPayConstants.FIELD_SIGN); returngenerateSignature(data,key).equals(sign); } /** *判断签名是否正确,必须包含sign字段,否则返回false。使用MD5签名。 * *@paramdataMap类型数据 *@paramkeyAPI密钥 *@return签名是否正确 *@throwsException */ publicstaticbooleanisSignatureValid(Map data,Stringkey)throwsException{ returnisSignatureValid(data,key,SignType.MD5); } /** *判断签名是否正确,必须包含sign字段,否则返回false。 * *@paramdataMap类型数据 *@paramkeyAPI密钥 *@paramsignType签名方式 *@return签名是否正确 *@throwsException */ publicstaticbooleanisSignatureValid(Map data,Stringkey,SignTypesignType)throwsException{ if(!data.containsKey(WXPayConstants.FIELD_SIGN)){ returnfalse; } Stringsign=data.get(WXPayConstants.FIELD_SIGN); returngenerateSignature(data,key,signType).equals(sign); } /** *生成签名 * *@paramdata待签名数据 *@paramkeyAPI密钥 *@return签名 */ publicstaticStringgenerateSignature(finalMap data,Stringkey)throwsException{ returngenerateSignature(data,key,SignType.MD5); } /** *生成签名.注意,若含有sign_type字段,必须和signType参数保持一致。 * *@paramdata待签名数据 *@paramkeyAPI密钥 *@paramsignType签名方式 *@return签名 */ publicstaticStringgenerateSignature(finalMap data,Stringkey,SignTypesignType)throwsException{ Set keySet=data.keySet(); String[]keyArray=keySet.toArray(newString[keySet.size()]); Arrays.sort(keyArray); StringBuildersb=newStringBuilder(); for(Stringk:keyArray){ if(k.equals(WXPayConstants.FIELD_SIGN)){ continue; } if(data.get(k).trim().length()>0)//参数值为空,则不参与签名 sb.append(k).append("=").append(data.get(k).trim()).append("&"); } sb.append("key=").append(key); if(SignType.MD5.equals(signType)){ returnMD5(sb.toString()).toUpperCase(); } elseif(SignType.HMACSHA256.equals(signType)){ returnHMACSHA256(sb.toString(),key); } else{ log.error("获取签名失败,失败原因:"+String.format("Invalidsign_type:%s",signType)); thrownewException(String.format("Invalidsign_type:%s",signType)); } } /** *获取随机字符串NonceStr *@returnString随机字符串 */ publicstaticStringgenerateNonceStr(){ returnUUID.randomUUID().toString().replaceAll("-","").substring(0,32); } /** *Map转xml数据 */ publicstaticStringGetMapToXML(Map param){ StringBuffersb=newStringBuffer(); sb.append(" "); for(Map.Entry "); returnsb.toString(); } /** *生成MD5 *@paramdata待处理数据 *@returnMD5结果 */ publicstaticStringMD5(Stringdata)throwsException{ java.security.MessageDigestmd=MessageDigest.getInstance("MD5"); byte[]array=md.digest(data.getBytes("UTF-8")); StringBuildersb=newStringBuilder(); for(byteitem:array){ sb.append(Integer.toHexString((item&0xFF)|0x100).substring(1,3)); } returnsb.toString().toUpperCase(); } /** *生成HMACSHA256 *@paramdata待处理数据 *@paramkey密钥 *@return加密结果 *@throwsException */ publicstaticStringHMACSHA256(Stringdata,Stringkey)throwsException{ Macsha256_HMAC=Mac.getInstance("HmacSHA256"); SecretKeySpecsecret_key=newSecretKeySpec(key.getBytes("UTF-8"),"HmacSHA256"); sha256_HMAC.init(secret_key); byte[]array=sha256_HMAC.doFinal(data.getBytes("UTF-8")); StringBuildersb=newStringBuilder(); for(byteitem:array){ sb.append(Integer.toHexString((item&0xFF)|0x100).substring(1,3)); } returnsb.toString().toUpperCase(); } /** *日志 *@return */ publicstaticLoggergetLogger(){ Loggerlogger=LoggerFactory.getLogger("wxpayjavasdk"); returnlogger; } /** *获取当前时间戳,单位秒 *@return */ publicstaticlonggetCurrentTimestamp(){ returnSystem.currentTimeMillis()/1000; } /** *获取当前时间戳,单位毫秒 *@return */ publicstaticlonggetCurrentTimestampMs(){ returnSystem.currentTimeMillis(); } /** *生成uuid,即用来标识一笔单,也用做nonce_str *@return */ publicstaticStringgenerateUUID(){ returnUUID.randomUUID().toString().replaceAll("-","").substring(0,32); } /** *支付签名 *@paramtimestamp *@paramnoncestr *@parampackages *@return *@throwsUnsupportedEncodingException */ publicstaticStringpaySign(Stringtimestamp,Stringnoncestr,Stringpackages,StringappId){ Mapentry:param.entrySet()){ sb.append("<"+entry.getKey()+">"); sb.append(entry.getValue()); sb.append(""+entry.getKey()+">"); } sb.append(" paras=newHashMap (); paras.put("appid",appId); paras.put("timestamp",timestamp); paras.put("noncestr",noncestr); paras.put("package",packages); paras.put("signType","MD5"); StringBuffersb=newStringBuffer(); Setes=paras.entrySet();//字典序 Iteratorit=es.iterator(); while(it.hasNext()){ Map.Entryentry=(Map.Entry)it.next(); Stringk=(String)entry.getKey(); Stringv=(String)entry.getValue(); //为空不参与签名、参数名区分大小写 if(null!=v&&!"".equals(v)&&!"sign".equals(k)&&!"key".equals(k)){ sb.append(k+"="+v+"&"); } } Stringsign=MD5Util.MD5(sb.toString()).toUpperCase();//MD5加密 returnsign; } } XmlUtil.java
packagecom.yiexpress.core.utils; importjava.io.StringReader; importjava.lang.reflect.Field; importjava.util.Date; importorg.dom4j.Document; importorg.dom4j.Element; importorg.dom4j.io.SAXReader; importorg.xml.sax.InputSource; publicclassXmlUtil{ /** *json数据转换对象 * *@paramElement *要转换的Element数据 *@parampojo *要转换的目标对象类型 *@return转换的目标对象 *@throwsException *转换失败 */ @SuppressWarnings("rawtypes") publicstaticObjectfromXmlToBean(ElementrootElt,Classpojo)throwsException{ //首先得到pojo所定义的字段 Field[]fields=pojo.getDeclaredFields(); //根据传入的Class动态生成pojo对象 Objectobj=pojo.newInstance(); for(Fieldfield:fields) { //设置字段可访问(必须,否则报错) field.setAccessible(true); //得到字段的属性名 Stringname=field.getName(); //这一段的作用是如果字段在Element中不存在会抛出异常,如果出异常,则跳过。 try { rootElt.elementTextTrim(name); } catch(Exceptionex) { continue; } if(rootElt.elementTextTrim(name)!=null&&!"".equals(rootElt.elementTextTrim(name))) { //根据字段的类型将值转化为相应的类型,并设置到生成的对象中。 if(field.getType().equals(Long.class)||field.getType().equals(long.class)) { field.set(obj,Long.parseLong(rootElt.elementTextTrim(name))); } elseif(field.getType().equals(String.class)) { field.set(obj,rootElt.elementTextTrim(name)); } elseif(field.getType().equals(Double.class)||field.getType().equals(double.class)) { field.set(obj,Double.parseDouble(rootElt.elementTextTrim(name))); } elseif(field.getType().equals(Integer.class)||field.getType().equals(int.class)) { field.set(obj,Integer.parseInt(rootElt.elementTextTrim(name))); } elseif(field.getType().equals(java.util.Date.class)) { field.set(obj,Date.parse(rootElt.elementTextTrim(name))); } else { continue; } } } returnobj; } /** *把xml格式转化为指定对象 * *@paramxml *@return */ @SuppressWarnings("unchecked") publicstaticTgetBeanByxml(Stringxml,Class valueType){ Tperson=null; InputSourcein=newInputSource(newStringReader(xml)); in.setEncoding("UTF-8"); SAXReaderreader=newSAXReader(); Documentdocument; try{ document=reader.read(in); Elementroot=document.getRootElement(); person=(T)XmlUtil.fromXmlToBean(root,valueType); }catch(Exceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); System.out.println("数据解析错误"); } returnperson; } } 获取预支付ID和签名的controller
packagecom.yiexpress.jerry.controller.ewe.wechat; importjava.util.HashMap; importjava.util.Map; importjava.util.SortedMap; importjava.util.TreeMap; importjavax.servlet.http.HttpServletRequest; importorg.slf4j.Logger; importorg.slf4j.LoggerFactory; importorg.springframework.stereotype.Controller; importorg.springframework.web.bind.annotation.RequestMapping; importorg.springframework.web.bind.annotation.RequestParam; importorg.springframework.web.bind.annotation.ResponseBody; importcom.yiexpress.core.utils.wechat.UnifiedOrderRequest; importcom.yiexpress.core.utils.wechat.UnifiedOrderRespose; importcom.yiexpress.core.utils.wechat.WXPayUtil; /** *微信支付controller */ @Controller @RequestMapping(value="/wxpay") publicclassWXPayController{ privatestaticfinalLoggerLOGGER=LoggerFactory.getLogger(WXPayController.class); privateStringappId="公总号appid";//公总号appid privateStringmchId="商家号";//商家号 privateStringapiKey="商户密匙";//商户密匙 /** *获取终端IP *@paramrequest *@return */ publicstaticStringgetIpAddr(HttpServletRequestrequest){ Stringip=request.getHeader("x-forwarded-for"); if(ip==null||ip.length()==0||"unknown".equalsIgnoreCase(ip)){ ip=request.getHeader("Proxy-Client-IP"); } if(ip==null||ip.length()==0||"unknown".equalsIgnoreCase(ip)){ ip=request.getHeader("WL-Proxy-Client-IP"); } if(ip==null||ip.length()==0||"unknown".equalsIgnoreCase(ip)){ ip=request.getRemoteAddr(); } returnip; } /** *支付初始化返回预支付ID、签名等信息 *@parampayMoney *@returnmap *result-1 */ @RequestMapping("/toPayInit") @ResponseBody publicMaptoPay(HttpServletRequestrequest,@RequestParam(value="payMoney",required=true)floatpayMoney,@RequestParam(value="openId",required=true)StringopenId,@RequestParam(value="orderId",required=true)StringorderId){ Map map=newHashMap<>(); //订单号目前生产的随机数后面放入指定系统唯一的单号 //判断单号是否存在 Stringnoncestr=WXPayUtil.generateNonceStr(); Map requestMap=newHashMap (); requestMap.put("appId",appId); requestMap.put("userWeixinOpenId",openId); //之前使用ETCA单号作为商户订单号,现在改为自动生成的账单号2018-10-25Peter //requestMap.put("out_trade_no",auShipmentBrief.getShipmentReference()); requestMap.put("out_trade_no","订单号"); requestMap.put("mch_id",mchId); //计算金额微信支付的金额的单位是分,例如:实际支付1.23元,传入参数就是123 intmoney=0; try{ money=(int)(payMoney*100); }catch(Exceptione){ map.put("result",-1); map.put("msg","金额格式不正确"); returnmap; } requestMap.put("payMoney",money+""); requestMap.put("spbill_create_ip",getIpAddr(request)); requestMap.put("notify_url","回调地址"); requestMap.put("noncestr",noncestr); requestMap.put("body","微信下单账单支付"); requestMap.put("detail","散客下单账单支付"); Map requestInfo=WXPayUtil.createOrderInfo(requestMap,apiKey); StringorderInfo_toString=(String)requestInfo.get("orderInfo_toString"); LOGGER.debug("request请求字符串:"+orderInfo_toString); //判断返回码 UnifiedOrderResposeorderResponse=WXPayUtil.httpOrder(orderInfo_toString,0);//调用统一下单接口 //判断超时的情况 if(orderResponse==null||orderResponse.getReturn_code()==null||("SUCCESS".equals(orderResponse.getReturn_code())&&(orderResponse.getErr_code()==null||"SYSTEMERROR".equals(orderResponse.getErr_code())))){ orderResponse=WXPayUtil.httpOrder(orderInfo_toString,1); if(orderResponse==null||orderResponse.getReturn_code()==null||("SUCCESS".equals(orderResponse.getReturn_code())&&(orderResponse.getErr_code()==null||"SYSTEMERROR".equals(orderResponse.getErr_code())))){ orderResponse=WXPayUtil.httpOrder(orderInfo_toString,2); } } LOGGER.debug("response返回字段:==》{}",orderResponse); //根据微信文档return_code和result_code都为SUCCESS的时候才会返回code_url if(null!=orderResponse&&"SUCCESS".equals(orderResponse.getReturn_code())&&"SUCCESS".equals(orderResponse.getResult_code())){ Stringtimestamp=String.valueOf(WXPayUtil.getCurrentTimestamp()); map.put("timestamp",timestamp); map.put("noncestr",noncestr); UnifiedOrderRequestunifiedOrderRequest=(UnifiedOrderRequest)requestInfo.get("unifiedOrderRequest"); map.put("unifiedOrderRequest",unifiedOrderRequest); SortedMap packageParams=newTreeMap (); packageParams.put("appId",appId); packageParams.put("signType","MD5"); packageParams.put("nonceStr",noncestr); packageParams.put("timeStamp",timestamp); Stringpackages="prepay_id="+orderResponse.getPrepay_id(); packageParams.put("package",packages); Stringsign=null; try{ //生成签名 sign=WXPayUtil.generateSignature(packageParams,apiKey); }catch(Exceptione){ map.put("result",-1); map.put("msg","支付签名信息异常"); e.printStackTrace(); } if(sign!=null&&!"".equals(sign)){ LOGGER.debug("------------支付签名:"+sign+"-------------------"); map.put("paySign",sign); map.put("result",1); map.put("appId",appId); }else{ map.put("result",-1); map.put("msg","支付签名信息异常"); } map.put("prepay_id",orderResponse.getPrepay_id()); returnmap; }else{//不成功 if(orderResponse!=null){ Stringtext="调用微信支付出错,返回状态码:"+orderResponse.getReturn_code()+",返回信息:"+orderResponse.getReturn_msg(); if(orderResponse.getErr_code()!=null&&!"".equals(orderResponse.getErr_code())){ text=text+",错误码:"+orderResponse.getErr_code()+",错误描述:"+orderResponse.getErr_code_des(); } LOGGER.error(text); }else{ LOGGER.error("返回值orderResponse对象为空"); } map.put("result",-1); map.put("msg","支付环境异常,请稍后再试"); returnmap; } } } jsp代码
//点击支付按钮开始支付 functiontoPay(){ //初步判断数据 varopenId=$("#openId").val(); varpayMoney=$("#payMoney").val(); $.ajax({ url:"${pageContext.request.contextPath}/toPayInit", type:"POST", dataType:'json', data:{ payMoney:payMoney, openId:openId, orderId:"订单号" }, success:function(result){ if(result.result==1){ varpaySign=result.paySign; varprepay_id=result.prepay_id; varnonceStr=result.noncestr; vartimestamp=result.timestamp; varunifiedOrderRequest=result.unifiedOrderRequest; varspbill_create_ip=unifiedOrderRequest.spbill_create_ip; vardetail=unifiedOrderRequest.detail; varout_trade_no=unifiedOrderRequest.out_trade_no; varappId=result.appId; onBridgeReady(paySign,prepay_id,nonceStr,timestamp,appId); }else{ alert("失败"); } }, error:function(data,status,e){//服务器响应失败时的处理函数 alert("数据异常,支付失败",'error'); } }); } //调起公众号支付 functiononBridgeReady(paySign,prepay_id,nonceStr,timestamp,appId){ WeixinJSBridge.invoke( 'getBrandWCPayRequest',{ "appId":appId,//appid "timeStamp":timestamp, "nonceStr":nonceStr,//随机串 "package":"prepay_id="+prepay_id, "signType":"MD5", "paySign":paySign//微信签名 }, function(res){ //使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。 if(res.err_msg=="get_brand_wcpay_request:ok"){ alert("支付完成",'success'); }elseif(res.err_msg=="get_brand_wcpay_request:cancel"){ alert("取消支付",'success'); }elseif(res.err_msg=="get_brand_wcpay_request:fail"){ alert("支付失败",'success'); } } ); } 定义微信支付成功回调接口APIAupostController.java
packagecom.yiexpress.api.controller.ewe.aupost; importjava.util.HashMap; importjava.util.Map; importjavax.annotation.Resource; importjavax.servlet.ServletInputStream; importjavax.servlet.http.HttpServletRequest; importjavax.servlet.http.HttpServletResponse; importorg.apache.commons.collections.MapUtils; importorg.slf4j.Logger; importorg.slf4j.LoggerFactory; importorg.springframework.beans.factory.annotation.Value; importorg.springframework.http.converter.json.MappingJackson2HttpMessageConverter; importorg.springframework.stereotype.Controller; importorg.springframework.web.bind.annotation.RequestMapping; importorg.springframework.web.bind.annotation.ResponseBody; importcom.yiexpress.core.utils.wechat.WXPayUtil; @Controller @RequestMapping("/api") publicclassAPIAupostController{ privatestaticfinalLoggerLOGGER=LoggerFactory.getLogger(APIAupostController.class); @Resource(name="jacksonBean") privateMappingJackson2HttpMessageConverterjackson; privateStringapiKey="商户密匙";//商户密匙 /** *异步回调接口 *@paramrequest *@paramresponse *@throwsException */ @RequestMapping(value="/paymentNotice",produces="text/html;charset=utf-8") @ResponseBody publicStringWeixinParentNotifyPage(HttpServletRequestrequest,HttpServletResponseresponse)throwsException{ ServletInputStreaminstream=request.getInputStream(); StringBuffersb=newStringBuffer(); intlen=-1; byte[]buffer=newbyte[1024]; while((len=instream.read(buffer))!=-1){ sb.append(newString(buffer,0,len)); } instream.close(); Mapmap=WXPayUtil.xmlToMap(sb.toString());//接受微信的回调的通知参数 Map return_data=newHashMap (); //判断签名是否正确 if(WXPayUtil.isSignatureValid(map,apiKey)){ if(map.get("return_code").toString().equals("FAIL")){ return_data.put("return_code","FAIL"); return_data.put("return_msg",map.get("return_msg")); }else{ Stringreturn_code=MapUtils.getString(map,"return_code"); Stringresult_code=MapUtils.getString(map,"result_code"); if(return_code!=null&&"SUCCESS".equals(return_code)&&result_code!=null&&"SUCCESS".equals(result_code)){ Stringout_trade_no=MapUtils.getString(map,"out_trade_no");//系统订单号 //支付成功,可以自定义新逻辑 } } }else{ return_data.put("return_code","FAIL"); return_data.put("return_msg","签名错误"); } Stringxml=WXPayUtil.GetMapToXML(return_data); LOGGER.error("支付通知回调结果:"+xml); returnxml; } } 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。