微信公众号支付怎么实现统一下单接口

这篇文章将为大家详细讲解有关微信公众号支付怎么实现统一下单接口,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

主要是调用微信公众支付的统一下单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-03-13 15:37:59
收藏
分享
海报
0 条评论
169
上一篇:iOS如何实现类似微信和支付宝的密码输入框 下一篇:微信开发之怎么使用地理位置扩展
目录

    0 条评论

    本站已关闭游客评论,请登录或者注册后再评论吧~

    忘记密码?

    图形验证码