当前位置: 移动技术网 > IT编程>开发语言>Java > 微信公众号支付(二)实现统一下单接口

微信公众号支付(二)实现统一下单接口

2019年07月22日  | 移动技术网IT编程  | 我要评论
已经获取到了用户的openid 这篇主要是调用微信公众支付的统一下单api api地址: 看文档,主要流程就是把20个左右的参数封装为xml格式发送到微信给的接口地址

已经获取到了用户的openid

这篇主要是调用微信公众支付的统一下单api

api地址:

看文档,主要流程就是把20个左右的参数封装为xml格式发送到微信给的接口地址,然后就可以获取到返回的内容了,如果成功里面就有支付所需要的预支付id

请求参数就不解释了。

其中,随机字符串:我用的是uuid去中划线

 public static string create_nonce_str() {
 return uuid.randomuuid().tostring().replace("-","");
 }

商户订单号:每个订单号只能使用一次,所以用的是系统的订单号加的时间戳。

总金额:不能为

通知地址:微信支付成功或失败回调给系统的地址

签名:

import java.io.serializable;
 public class payinfo implements serializable{
 private static final long serialversionuid = l;
 private string appid;
 private string mch_id;
 private string device_info;
 private string nonce_str;
 private string sign;
 private string body;
 private string attach;
 private string out_trade_no;
 private int total_fee;
 private string spbill_create_ip;
 private string notify_url;
 private string trade_type;
 private string openid;
 //下面是get,set方法 
 }


 /**
 * 创建统一下单的xml的java对象
 * @param bizorder 系统中的业务单号
 * @param ip 用户的ip地址
 * @param openid 用户的openid
 * @return
 */
 public payinfo createpayinfo(bizorder bizorder,string ip,string openid) {
  payinfo payinfo = new payinfo();
  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(new date(), "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);
  return payinfo;
 }

获取签名:

/**
 * 获取签名
 * @param payinfo
 * @return
 * @throws exception
 */
 public string getsign(payinfo payinfo) throws exception {
  string signtemp = "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注意
 messagedigest md = messagedigest.getinstance("md");
 md.reset();
 md.update(signtemp.getbytes("utf-"));
 string sign = commonutil.bytetostr(md.digest()).touppercase();
 return sign;
 }

注意:上面的constants.key取值在商户号api安全的api密钥中。

一些工具方法:获取ip地址,将字节数组转换为十六进制字符串,将字节转换为十六进制字符串

 /**
 * 将字节数组转换为十六进制字符串
 * 
 * @param bytearray
 * @return
 */
 public static string bytetostr(byte[] bytearray) {
  string strdigest = "";
  for (int i = ; i < bytearray.length; i++) {
  strdigest += bytetohexstr(bytearray[i]);
  }
  return strdigest;
 }
 /**
 * 将字节转换为十六进制字符串
 * 
 * @param btyes
 * @return
 */
 public static string bytetohexstr(byte bytes) {
  char[] digit = { '', '', '', '', '', '', '', '', '', '', 'a', 'b', 'c', 'd', 'e', 'f' };
  char[] temparr = new char[];
  temparr[] = digit[(bytes >>> ) & xf];
  temparr[] = digit[bytes & xf];
  string s = new string(temparr);
  return s;
 }
 /**
 * 获取ip地址
 * @param request
 * @return
 */
 public static string getipaddr(httpservletrequest request) { 
  inetaddress addr = null; 
  try { 
  addr = inetaddress.getlocalhost(); 
  } catch (unknownhostexception e) { 
  return request.getremoteaddr(); 
  } 
  byte[] ipaddr = addr.getaddress(); 
  string ipaddrstr = ""; 
  for (int i = ; i < ipaddr.length; i++) { 
  if (i > ) { 
   ipaddrstr += "."; 
  } 
  ipaddrstr += ipaddr[i] & xff; 
  } 
  return ipaddrstr; 
 } 

这样就获取了签名,把签名与payinfo中的其他数据转成xml格式,当做参数传递给统一下单地址。

 payinfo pi = pu.createpayinfo(bo,"...","");
 string sign = pu.getsign(pi);
 pi.setsign(sign);

对象转xml

 /**
 * 扩展xstream使其支持cdata
 */
 private static xstream xstream = new xstream(new xppdriver() {
  public hierarchicalstreamwriter createwriter(writer out) {
  return new prettyprintwriter(out) {
   //增加cdata标记
   boolean cdata = true;
   @suppresswarnings("rawtypes")
   public void startnode(string name, class clazz) {
   super.startnode(name, clazz);
   }
   protected void writetext(quickwriter writer, string text) {
   if (cdata) {
    writer.write("<![cdata[");
    writer.write(text);
    writer.write("]]>");
   } else {
    writer.write(text);
   }
   }
  };
  }
 });
 public static string payinfotoxml(payinfo pi) {
  xstream.alias("xml", pi.getclass());
  return xstream.toxml(pi);
 }

xml转map

 @suppresswarnings("unchecked")
 public static map<string, string> parsexml(string xml) throws exception {
  map<string, string> map = new hashmap<string, string>();
  document document = documenthelper.parsetext(xml);
  element root = document.getrootelement();
  list<element> elementlist = root.elements();
  for (element e : elementlist)
  map.put(e.getname(), e.gettext());
  return map;
 }

下面就是调用统一下单的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);

 public static map<string, string> httpsrequesttoxml(string requesturl, string requestmethod, string outputstr) {
  map<string, string> result = new hashmap<>();
  try {
  stringbuffer buffer = httpsrequest(requesturl, requestmethod, outputstr);
  result = messageutil.parsexml(buffer.tostring());
  } catch (connectexception ce) {
  log.error("连接超时:"+ce.getmessage());
  } catch (exception e) {
  log.error("https请求异常:"+ece.getmessage());
  }
  return result;
 }

httpsrequest()这个方法在第一篇中

上面获取到的map如果成功的话,里面就会有

string return_code = map.get("return_code");
 if(stringutils.isnotblank(return_code) && return_code.equals("success")){
   string return_msg = map.get("return_msg");
 if(stringutils.isnotblank(return_msg) && !return_msg.equals("ok")) {
   return "统一下单错误!";
 }
 }else{
   return "统一下单错误!";
 }
 string prepay_id = map.get("prepay_id");

这个prepay_id就是预支付的id。后面支付需要它。

如您对本文有疑问或者有任何想说的,请 点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网