微信公众号支付怎么实现统一下单接口
这篇文章将为大家详细讲解有关微信公众号支付怎么实现统一下单接口,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。
主要是调用微信公众支付的统一下单API
API地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
看文档,主要流程就是把20个左右的参数封装为XML格式发送到微信给的接口地址,然后就可以获取到返回的内容了,如果成功里面就有支付所需要的预支付ID
请求参数就不解释了。
其中,随机字符串:我用的是UUID去中划线
publicstaticStringcreate_nonce_str(){ returnUUID.randomUUID().toString().replace("-",""); }
商户订单号:每个订单号只能使用一次,所以用的是系统的订单号加的时间戳。
总金额:不能为
通知地址:微信支付成功或失败回调给系统的地址
签名:
importjava.io.Serializable; publicclassPayInfoimplementsSerializable{ privatestaticfinallongserialVersionUID=L; privateStringappid; privateStringmch_id; privateStringdevice_info; privateStringnonce_str; privateStringsign; privateStringbody; privateStringattach; privateStringout_trade_no; privateinttotal_fee; privateStringspbill_create_ip; privateStringnotify_url; privateStringtrade_type; privateStringopenid; //下面是get,set方法 } /** *创建统一下单的xml的java对象 *@parambizOrder系统中的业务单号 *@paramip用户的ip地址 *@paramopenId用户的openId *@return */ publicPayInfocreatePayInfo(BizOrderbizOrder,Stringip,StringopenId){ PayInfopayInfo=newPayInfo(); payInfo.setAppid(Constants.appid); payInfo.setDevice_info("WEB"); payInfo.setMch_id(Constants.mch_id); payInfo.setNonce_str(CommonUtil.create_nonce_str().replace("-","")); payInfo.setBody("这里是某某白米饭的body"); payInfo.setAttach(bizOrder.getId()); payInfo.setOut_trade_no(bizOrder.getOrderCode().concat("A").concat(DateFormatUtils.format(newDate(),"MMddHHmmss"))); payInfo.setTotal_fee((int)bizOrder.getFeeAmount()); payInfo.setSpbill_create_ip(ip); payInfo.setNotify_url(Constants.notify_url); payInfo.setTrade_type("JSAPI"); payInfo.setOpenid(openId); returnpayInfo; }
获取签名:
/** *获取签名 *@parampayInfo *@return *@throwsException */ publicStringgetSign(PayInfopayInfo)throwsException{ StringsignTemp="appid="+payInfo.getAppid() +"&attach="+payInfo.getAttach() +"&body="+payInfo.getBody() +"&device_info="+payInfo.getDevice_info() +"&mch_id="+payInfo.getMch_id() +"&nonce_str="+payInfo.getNonce_str() +"¬ify_url="+payInfo.getNotify_url() +"&openid="+payInfo.getOpenid() +"&out_trade_no="+payInfo.getOut_trade_no() +"&spbill_create_ip="+payInfo.getSpbill_create_ip() +"&total_fee="+payInfo.getTotal_fee() +"&trade_type="+payInfo.getTrade_type() +"&key="+Constants.key;//这个key注意 MessageDigestmd=MessageDigest.getInstance("MD"); md.reset(); md.update(signTemp.getBytes("UTF-")); Stringsign=CommonUtil.byteToStr(md.digest()).toUpperCase(); returnsign; }
注意:上面的Constants.key取值在商户号API安全的API密钥中。
一些工具方法:获取ip地址,将字节数组转换为十六进制字符串,将字节转换为十六进制字符串
/** *将字节数组转换为十六进制字符串 * *@parambyteArray *@return */ publicstaticStringbyteToStr(byte[]byteArray){ StringstrDigest=""; for(inti=;i<byteArray.length;i++){ strDigest+=byteToHexStr(byteArray[i]); } returnstrDigest; } /** *将字节转换为十六进制字符串 * *@parambtyes *@return */ publicstaticStringbyteToHexStr(bytebytes){ char[]Digit={'','','','','','','','','','','A','B','C','D','E','F'}; char[]tempArr=newchar[]; tempArr[]=Digit[(bytes>>>)&XF]; tempArr[]=Digit[bytes&XF]; Strings=newString(tempArr); returns; } /** *获取ip地址 *@paramrequest *@return */ publicstaticStringgetIpAddr(HttpServletRequestrequest){ InetAddressaddr=null; try{ addr=InetAddress.getLocalHost(); }catch(UnknownHostExceptione){ returnrequest.getRemoteAddr(); } byte[]ipAddr=addr.getAddress(); StringipAddrStr=""; for(inti=;i<ipAddr.length;i++){ if(i>){ ipAddrStr+="."; } ipAddrStr+=ipAddr[i]&xFF; } returnipAddrStr; }
这样就获取了签名,把签名与PayInfo中的其他数据转成XML格式,当做参数传递给统一下单地址。
PayInfopi=pu.createPayInfo(bo,"...",""); Stringsign=pu.getSign(pi); pi.setSign(sign);
对象转XML
/** *扩展xstream使其支持CDATA */ privatestaticXStreamxstream=newXStream(newXppDriver(){ publicHierarchicalStreamWritercreateWriter(Writerout){ returnnewPrettyPrintWriter(out){ //增加CDATA标记 booleancdata=true; @SuppressWarnings("rawtypes") publicvoidstartNode(Stringname,Classclazz){ super.startNode(name,clazz); } protectedvoidwriteText(QuickWriterwriter,Stringtext){ if(cdata){ writer.write("<![CDATA["); writer.write(text); writer.write("]]>"); }else{ writer.write(text); } } }; } }); publicstaticStringpayInfoToXML(PayInfopi){ xstream.alias("xml",pi.getClass()); returnxstream.toXML(pi); }
xml转Map
@SuppressWarnings("unchecked") publicstaticMap<String,String>parseXml(Stringxml)throwsException{ Map<String,String>map=newHashMap<String,String>(); Documentdocument=DocumentHelper.parseText(xml); Elementroot=document.getRootElement(); List<Element>elementList=root.elements(); for(Elemente:elementList) map.put(e.getName(),e.getText()); returnmap; }
下面就是调用统一下单的URL了
log.info(MessageUtil.payInfoToXML(pi).replace("__","_")); Map<String,String>map=CommonUtil.httpsRequestToXML("https://api.mch.weixin.qq.com/pay/unifiedorder","POST",MessageUtil.payInfoToXML(pi).replace("__","_").replace("<![CDATA[","").replace("]]>","")); log.info(map); publicstaticMap<String,String>httpsRequestToXML(StringrequestUrl,StringrequestMethod,StringoutputStr){ Map<String,String>result=newHashMap<>(); try{ StringBufferbuffer=httpsRequest(requestUrl,requestMethod,outputStr); result=MessageUtil.parseXml(buffer.toString()); }catch(ConnectExceptionce){ log.error("连接超时:"+ce.getMessage()); }catch(Exceptione){ log.error("https请求异常:"+ece.getMessage()); } returnresult; }
httpsRequest()这个方法在第一篇中
上面获取到的Map如果成功的话,里面就会有
Stringreturn_code=map.get("return_code"); if(StringUtils.isNotBlank(return_code)&&return_code.equals("SUCCESS")){ Stringreturn_msg=map.get("return_msg"); if(StringUtils.isNotBlank(return_msg)&&!return_msg.equals("OK")){ return"统一下单错误!"; } }else{ return"统一下单错误!"; } Stringprepay_Id=map.get("prepay_id");
这个prepay_id就是预支付的ID。后面支付需要它。
关于“微信公众号支付怎么实现统一下单接口”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。
推荐阅读
-
2021微信公众号借钱排行榜(这几个下款比较快!)
-
微信公众号如何搜索关键词,微信公众号号内搜索关键词排序方法
-
.NET C#使用微信公众号登录网站的案例
-
如何使用.NET微信公众号开发
-
之微信公众号开发php如何实现自定义关键字回复
小编给大家分享一下之微信公众号开发php如何实现自定义关键字回复,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望...
-
微信公众号开发实现点击返回按钮就返回到聊天界面的方法
小编给大家分享一下微信公众号开发实现点击返回按钮就返回到聊天界面的方法,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下...
-
微信公众号之网页授权获取怎么弄
这篇文章主要介绍了微信公众号之网页授权获取怎么弄,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下...
-
微信公众号快速涨粉技巧(日涨1000粉)!