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(MaprequestMap,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支付
SortedMappackageParams=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("__","_"));
MapresponseMap=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="dsfsdf sdfsd dfsd sdfsdfsdfdsf JSAPI sdfsdf ";
//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集合
SortedMappackageParams=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解析
publicstaticSortedMapdoXMLParseWithSorted(Stringstrxml)throwsException{
strxml=strxml.replaceFirst("encoding=\".*\"","encoding=\"UTF-8\"");
if(null==strxml||"".equals(strxml)){
returnnull;
}
SortedMapm=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
*/
publicstaticMapxmlToMap(StringstrXML)throwsException{
try{
Mapdata=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;idxdata)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(finalMapdata,Stringkey)throwsException{
returngenerateSignedXml(data,key,SignType.MD5);
}
/**
*生成带有sign的XML格式字符串
*
*@paramdataMap类型数据
*@paramkeyAPI密钥
*@paramsignType签名类型
*@return含有sign字段的XML
*/
publicstaticStringgenerateSignedXml(finalMapdata,Stringkey,SignTypesignType)throwsException{
Stringsign=generateSignature(data,key,signType);
data.put(WXPayConstants.FIELD_SIGN,sign);
returnmapToXml(data);
}
/**
*判断签名是否正确
*
*@paramxmlStrXML格式数据
*@paramkeyAPI密钥
*@return签名是否正确
*@throwsException
*/
publicstaticbooleanisSignatureValid(StringxmlStr,Stringkey)throwsException{
Mapdata=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(Mapdata,Stringkey)throwsException{
returnisSignatureValid(data,key,SignType.MD5);
}
/**
*判断签名是否正确,必须包含sign字段,否则返回false。
*
*@paramdataMap类型数据
*@paramkeyAPI密钥
*@paramsignType签名方式
*@return签名是否正确
*@throwsException
*/
publicstaticbooleanisSignatureValid(Mapdata,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(finalMapdata,Stringkey)throwsException{
returngenerateSignature(data,key,SignType.MD5);
}
/**
*生成签名.注意,若含有sign_type字段,必须和signType参数保持一致。
*
*@paramdata待签名数据
*@paramkeyAPI密钥
*@paramsignType签名方式
*@return签名
*/
publicstaticStringgenerateSignature(finalMapdata,Stringkey,SignTypesignType)throwsException{
SetkeySet=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(Mapparam){
StringBuffersb=newStringBuffer();
sb.append("");
for(Map.Entryentry:param.entrySet()){
sb.append("<"+entry.getKey()+">");
sb.append(entry.getValue());
sb.append(""+entry.getKey()+">");
}
sb.append(" ");
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){
Mapparas=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,ClassvalueType){
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){
Mapmap=newHashMap<>();
//订单号目前生产的随机数后面放入指定系统唯一的单号
//判断单号是否存在
Stringnoncestr=WXPayUtil.generateNonceStr();
MaprequestMap=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","散客下单账单支付");
MaprequestInfo=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);
SortedMappackageParams=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());//接受微信的回调的通知参数
Mapreturn_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;
}
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。