当前位置: 移动技术网 > IT编程>开发语言>Java > java服务端微信APP支付接口详解

java服务端微信APP支付接口详解

2019年07月22日  | 移动技术网IT编程  | 我要评论

一、微信app支付接入商户服务中心

[申请流程指引] (https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419317780&token=84f23b4e9746c5963128711f225476cfd49ccf8c&lang=zh_cn)

二、开始开发

1、配置相关的配置信息

1.1、配置appid(android)、mch_id(ios)、微信支付后的回调地址

sys.properties配置文件:

  appid=wx***************1
  mch_id=1********2
  notify_url=http://6*.***.***.**/returnmsg.do 

//回调通知的地址,一定是要可以直接访问的地址

2、微信支付–下单

@responsebody
@requestmapping(value = "/weixinpay.do", produces = "text/html;charset=utf-8",method={requestmethod.post})
  public static string weixinpay(string body, //商品描述
      string detail, //商品详情
      string attach, //附加数据,在查询api和支付通知中原样返回,该字段主要用于商户携带订单的自定义数据
      string out_trade_no, //商户系统内部的订单号,32个字符内、可包含字母, 其他说明见商户订单号
      string total_price, //订单总金额,单位为分,详见支付金额
      string spbill_create_ip //用户端实际ip

      ) throws exception { 

    weixinconfigutils config = new weixinconfigutils();
    //参数组
    string appid = config.appid;//微信开放平台审核通过的应用appid
    system.out.println("appid是:"+appid);
    string mch_id = config.mch_id;
    system.out.println("mch_id是:"+mch_id);
    string nonce_str = randcharsutils.getrandomstring(16);
    system.out.println("随机字符串是:"+nonce_str);


    body = body;//"测试微信支付0.01_2";
    detail = detail;//"0.01_元测试开始";
    //attach = attach;//"备用参数,先留着,后面会有用的";
    //string out_trade_no = orderutil.getorderno();//"2015112500001000811017342394";

    double totalfee =0;
    try{
      totalfee=double.parsedouble(total_price);////单位是分,即是0.01元
    }catch (exception e) {
      totalfee=0;
    }
    int total_fee=(int) (totalfee*100);
    spbill_create_ip = spbill_create_ip;//"127.0.0.1";

    string time_start = randcharsutils.timestart();
    system.out.println(time_start);
    string time_expire = randcharsutils.timeexpire();
    system.out.println(time_expire);
    string notify_url = config.notify_url;
    system.out.println("notify_url是:"+notify_url);
    string trade_type = "app";

    //参数:开始生成签名
    sortedmap<object,object> parameters = new treemap<object,object>();
    parameters.put("appid", appid);
    parameters.put("mch_id", mch_id);
    parameters.put("nonce_str", nonce_str);
    parameters.put("body", body);
    //parameters.put("nonce_str", nonce_str);
    parameters.put("detail", detail);
    parameters.put("attach", attach);
    parameters.put("out_trade_no", out_trade_no);
    parameters.put("total_fee", total_fee);
    parameters.put("time_start", time_start);
    parameters.put("time_expire", time_expire);
    parameters.put("notify_url", notify_url);
    parameters.put("trade_type", trade_type);
    parameters.put("spbill_create_ip", spbill_create_ip);

    string sign = wxsignutils.createsign("utf-8", parameters);
    system.out.println("签名是:"+sign);


    unifiedorder unifiedorder = new unifiedorder();
    unifiedorder.setappid(appid);
    unifiedorder.setmch_id(mch_id);
    unifiedorder.setnonce_str(nonce_str);
    unifiedorder.setsign(sign);
    unifiedorder.setbody(body);
    unifiedorder.setdetail(detail);
    unifiedorder.setattach(attach);
    unifiedorder.setout_trade_no(out_trade_no);
    unifiedorder.settotal_fee(total_fee);
    unifiedorder.setspbill_create_ip(spbill_create_ip);
    unifiedorder.settime_start(time_start);
    unifiedorder.settime_expire(time_expire);
    unifiedorder.setnotify_url(notify_url);
    unifiedorder.settrade_type(trade_type);

    system.out.println(md5utils.md5("fenxiangzhuyi") + "========================");

    //构造xml参数
    string xmlinfo = httpxmlutils.xmlinfo(unifiedorder);

    string wxurl = "https://api.mch.weixin.qq.com/pay/unifiedorder";

    string method = "post";

    string weixinpost = httpxmlutils.httpsrequest(wxurl, method, xmlinfo).tostring();

    system.out.println(weixinpost);

    parsexmlutils.jdomparsexml(weixinpost);



    string json = jsonutil.xml2jsonstring(weixinpost);

    system.out.println("=========================================================");

    bean b = jsonutil.getsinglebean(json, bean.class);
    if(null!=b){
      weixinorder weixin = b.getxml();
      //参数:开始生成签名
      sortedmap<object,object> par = new treemap<object,object>();
      par.put("appid", weixin.getappid());
      par.put("partnerid", weixin.getmch_id());
      par.put("prepayid", weixin.getprepay_id());
      par.put("package", "sign=wxpay");
      par.put("noncestr", weixin.getnonce_str());

      //时间戳
       date date = new date();
       long time = date.gettime();
       //mysq 时间戳只有10位 要做处理
       string dateline = time + "";
       dateline = dateline.substring(0, 10);

      par.put("timestamp", dateline);

      string signnew = wxsignutils.createsign("utf-8", par);
      system.out.println("再次签名是:"+signnew);


      setpay setpay = new setpay();

      setpay.setappid(weixin.getappid());
      setpay.setpartnerid(weixin.getmch_id());
      setpay.setprepayid(weixin.getprepay_id());
      setpay.setnoncestr(weixin.getnonce_str());

      setpay.settimestamp(dateline);
      setpay.setsign(signnew);
      setpay.setpack("sign=wxpay");

      jsonobject js = jsonobject.fromobject(setpay);
      stringbuilder msg = new stringbuilder();
      msg.append("{\"code\":\"1\",");
      msg.append("\"msg\":\"查询成功!\",");
      msg.append("\"datas\":");
      msg.append(js.tostring());
      msg.append("}");

      system.out.println(js);

      return msg.tostring();
    }
    stringbuilder msg = new stringbuilder();
    msg.append("{\"code\":\"1\",");
    msg.append("\"msg\":\"查询成功!\",");
    msg.append("\"datas\":");
    msg.append("支付失败!");
    msg.append("}");


    return msg.tostring();

  }

2.1、微信支付签名算法sign

package com.wx.weixincontroller.pay.weixin.utils;

import java.util.iterator;
import java.util.map;
import java.util.set;
import java.util.sortedmap;

import com.wx.weixin.utils.md5utils;

/**
 * 微信支付签名
 * @author iyjrg_xiebin
 * @date 2016年10月25日下午4:47:07
 */
public class wxsignutils {
  //http://mch.weixin.qq.com/wiki/doc/api/index.php?chapter=4_3
  //商户key:改成公司申请的即可
  //32位密码设置地址:http://www.sexauth.com/ jdex1hvufnm1sdcb0e81t36k0d0f15nc

  private static string key = "***cb**e**ef**c*e*d***e*fd***cb*";

  /**
   * 微信支付签名算法sign
   * @param characterencoding
   * @param parameters
   * @return
   */
  @suppresswarnings("rawtypes")
  public static string createsign(string characterencoding,sortedmap<object,object> parameters){


    stringbuffer sb = new stringbuffer();
    set es = parameters.entryset();//所有参与传参的参数按照accsii排序(升序)
    iterator it = es.iterator();
    while(it.hasnext()) {
      map.entry entry = (map.entry)it.next();
      string k = (string)entry.getkey();
      object v = entry.getvalue();
      if(null != v && !"".equals(v) 
          && !"sign".equals(k) && !"key".equals(k)) {
        sb.append(k + "=" + v + "&");
      }
    }
    sb.append("key=" + key);
    system.out.println("字符串拼接后是:"+sb.tostring());
    string sign = md5util.md5encode(sb.tostring(), characterencoding).touppercase();
    return sign;
  }

}

2.2、post提交xml格式的参数

package com.wx.weixincontroller.pay.weixin.utils;

import java.io.bufferedreader;
import java.io.ioexception;
import java.io.inputstream;
import java.io.inputstreamreader;
import java.io.outputstream;
import java.io.outputstreamwriter;
import java.net.httpurlconnection;
import java.net.malformedurlexception;
import java.net.url;

import javax.net.ssl.httpsurlconnection;

import com. com.wx.weixin.wxcontroller.pay.weixin.entity.unifiedorder;

/**
 * post提交xml格式的参数
 * @author iyjrg_xiebin
 * @date 2016年10月25日下午3:33:38
 */
public class httpxmlutils {

  /**
   * 开始post提交参数到接口
   * 并接受返回
   * @param url
   * @param xml
   * @param method
   * @param contenttype
   * @return
   */
  public static string xmlhttpproxy(string url,string xml,string method,string contenttype){
    inputstream is = null;
    outputstreamwriter os = null;

    try {
      url _url = new url(url);
      httpurlconnection conn = (httpurlconnection) _url.openconnection();
      conn.setdoinput(true);  
      conn.setdooutput(true);  
      conn.setrequestproperty("content-type", "text/xml");
      conn.setrequestproperty("pragma:", "no-cache"); 
      conn.setrequestproperty("cache-control", "no-cache"); 
      conn.setrequestmethod("post");
      os = new outputstreamwriter(conn.getoutputstream());
      os.write(new string(xml.getbytes(contenttype)));
      os.flush();

      //返回值
      is = conn.getinputstream();
      return getcontent(is, "utf-8");
    } catch (malformedurlexception e) {
      e.printstacktrace();
    } catch (ioexception e) {
      e.printstacktrace();
    } finally{
      try {
        if(os!=null){os.close();}
        if(is!=null){is.close();}
      } catch (ioexception e) {
        e.printstacktrace();
      }
    }
    return null;
  }

  /**
   * 解析返回的值
   * @param is
   * @param charset
   * @return
   */
  public static string getcontent(inputstream is, string charset) {
    string pagestring = null;
    inputstreamreader isr = null;
    bufferedreader br = null;
    stringbuffer sb = null;
    try {
      isr = new inputstreamreader(is, charset);
      br = new bufferedreader(isr);
      sb = new stringbuffer();
      string line = null;
      while ((line = br.readline()) != null) {
        sb.append(line + "\n");
      }
      pagestring = sb.tostring();
    } catch (exception e) {
      e.printstacktrace();
    } finally {
      try {
        if (is != null){
          is.close();
        }
        if(isr!=null){
          isr.close();
        }
        if(br!=null){
          br.close();
        }
      } catch (ioexception e) {
        e.printstacktrace();
      }
      sb = null;
    }
    return pagestring;
  }

  /**
   * 构造xml参数
   * @param xml
   * @return
   */
  public static string xmlinfo(unifiedorder unifiedorder){
    //构造xml参数的时候,至少又是个必传参数
    /*
     * <xml>
        <appid>wx2421b1c4370ec43b</appid>
        <attach>支付测试</attach>
        <body>jsapi支付测试</body>
        <mch_id>10000100</mch_id>
        <nonce_str>1add1a30ac87aa2db72f57a2375d8fec</nonce_str>
        <notify_url>http://wxpay.weixin.qq.com/pub_v2/pay/notify.v2.php</notify_url>
        <openid>oupf8umuajo_m2pxb1q9znjwes6o</openid>
        <out_trade_no>1415659990</out_trade_no>
        <spbill_create_ip>14.23.150.211</spbill_create_ip>
        <total_fee>1</total_fee>
        <trade_type>jsapi</trade_type>
        <sign>0cb01533b8c1ef103065174f50bca001</sign>
      </xml>
     */

    if(unifiedorder!=null){
      stringbuffer bf = new stringbuffer();
      bf.append("<xml>");

      bf.append("<appid><![cdata[");
      bf.append(unifiedorder.getappid());
      bf.append("]]></appid>");

      bf.append("<mch_id><![cdata[");
      bf.append(unifiedorder.getmch_id());
      bf.append("]]></mch_id>");

      bf.append("<nonce_str><![cdata[");
      bf.append(unifiedorder.getnonce_str());
      bf.append("]]></nonce_str>");

      bf.append("<sign><![cdata[");
      bf.append(unifiedorder.getsign());
      bf.append("]]></sign>");

      bf.append("<body><![cdata[");
      bf.append(unifiedorder.getbody());
      bf.append("]]></body>");

      bf.append("<detail><![cdata[");
      bf.append(unifiedorder.getdetail());
      bf.append("]]></detail>");

      bf.append("<attach><![cdata[");
      bf.append(unifiedorder.getattach());
      bf.append("]]></attach>");

      bf.append("<out_trade_no><![cdata[");
      bf.append(unifiedorder.getout_trade_no());
      bf.append("]]></out_trade_no>");

      bf.append("<total_fee><![cdata[");
      bf.append(unifiedorder.gettotal_fee());
      bf.append("]]></total_fee>");

      bf.append("<spbill_create_ip><![cdata[");
      bf.append(unifiedorder.getspbill_create_ip());
      bf.append("]]></spbill_create_ip>");

      bf.append("<time_start><![cdata[");
      bf.append(unifiedorder.gettime_start());
      bf.append("]]></time_start>");

      bf.append("<time_expire><![cdata[");
      bf.append(unifiedorder.gettime_expire());
      bf.append("]]></time_expire>");

      bf.append("<notify_url><![cdata[");
      bf.append(unifiedorder.getnotify_url());
      bf.append("]]></notify_url>");

      bf.append("<trade_type><![cdata[");
      bf.append(unifiedorder.gettrade_type());
      bf.append("]]></trade_type>");


      bf.append("</xml>");
      return bf.tostring();
    }

    return "";
  }




  /**
   * post请求并得到返回结果
   * @param requesturl
   * @param requestmethod
   * @param output
   * @return
   */
  public static string httpsrequest(string requesturl, string requestmethod, string output) {
    try{
      url url = new url(requesturl);
      httpsurlconnection connection = (httpsurlconnection) url.openconnection();
      connection.setdooutput(true);
      connection.setdoinput(true);
      connection.setusecaches(false);
      connection.setrequestmethod(requestmethod);
      if (null != output) {
        outputstream outputstream = connection.getoutputstream();
        outputstream.write(output.getbytes("utf-8"));
        outputstream.close();
      }
      // 从输入流读取返回内容
      inputstream inputstream = connection.getinputstream();
      inputstreamreader inputstreamreader = new inputstreamreader(inputstream, "utf-8");
      bufferedreader bufferedreader = new bufferedreader(inputstreamreader);
      string str = null;
      stringbuffer buffer = new stringbuffer();
      while ((str = bufferedreader.readline()) != null) {
        buffer.append(str);
      }
      bufferedreader.close();
      inputstreamreader.close();
      inputstream.close();
      inputstream = null;
      connection.disconnect();
      return buffer.tostring();
    }catch(exception ex){
      ex.printstacktrace();
    }

    return "";
  }

}


3、微信支付–回调通知业务处理

 //通知处理类
 @responsebody
 @requestmapping(value = "/returnmsg.do", produces = "text/html;charset=utf-8",method={requestmethod.post})
    public string returnmsg(httpservletrequest request, httpservletresponse response) throws exception {

      // 解析结果存储在hashmap
      map<string, string> map = new hashmap<string, string>();
      inputstream inputstream = request.getinputstream();

      // 读取输入流
      saxreader reader = new saxreader();
      document document = reader.read(inputstream);
      // 得到xml根元素
      element root = document.getrootelement();
      // 得到根元素的所有子节点
      list<element> elementlist = root.elements();

      // 遍历所有子节点
      for (element e : elementlist) {
        map.put(e.getname(), e.gettext());
      }

      jsonobject json = jsonobject.fromobject(map);

      system.out.println("===消息通知的结果:" + json.tostring() + "==========================");
      system.out.println("===return_code===" + map.get("return_code"));
      system.out.println("===return_msg===" + map.get("return_msg"));
      system.out.println("===out_trade_no===" + map.get("out_trade_no"));

      //验证签名的过程

      //判断是否支付成功
      if(map.get("return_code").equals("success")) {

          /**
          *支付成功之后的业务处理
          */

          // 释放资源
          inputstream.close();
          inputstream = null;


          //bis.close();
          return "success";
        }

      }
      if (map.get("return_code").equals("fail")) {

        /**
         *支付失败后的业务处理
         */

          // 释放资源
          inputstream.close();

          inputstream = null;

          return "success";
        }


      }

      // 释放资源
      inputstream.close();
      inputstream = null;

      return "success";

    }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网