欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2024-02-28 08:28:40
一、微信app支付接入商户服务中心 [申请流程指引] (https://open.weixin.qq.com/cgi-bin/showdocument?actio...

一、微信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";

    }

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