微信公众号支付怎么实现统一下单接口
发布时间:-03-12 09:44:45
来源:亿速云
阅读:89
作者:小新
这篇文章将为大家详细讲解有关微信公众号支付怎么实现统一下单接口,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。
主要是调用微信公众支付的统一下单API
API地址:https://pay./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
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
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("
writer.write(text);
writer.write("]]>");
}else{
writer.write(text);
}
}
};
}
});
publicstaticStringpayInfoToXML(PayInfopi){
xstream.alias("xml",pi.getClass());
returnxstream.toXML(pi);
}
xml转Map@SuppressWarnings("unchecked")
publicstaticMapparseXml(Stringxml)throwsException{
Mapmap=newHashMap();
Documentdocument=DocumentHelper.parseText(xml);
Elementroot=document.getRootElement();
ListelementList=root.elements();
for(Elemente:elementList)
map.put(e.getName(),e.getText());
returnmap;
}
下面就是调用统一下单的URL了log.info(MessageUtil.payInfoToXML(pi).replace("__","_"));
Mapmap=CommonUtil.httpsRequestToXML("https://api.mch./pay/unifiedorder","POST",MessageUtil.payInfoToXML(pi).replace("__","_").replace("",""));
log.info(map);
publicstaticMaphttpsRequestToXML(StringrequestUrl,StringrequestMethod,StringoutputStr){
Mapresult=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。后面支付需要它。
关于“微信公众号支付怎么实现统一下单接口”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。
如果觉得《php微信统一公众号支付接口 微信公众号支付怎么实现统一下单接口》对你有帮助,请点赞、收藏,并留下你的观点哦!