• 技术文章 >Java >java教程

    Java中调用微信支付功能的实例分析

    黄舟黄舟2017-08-20 09:11:26原创1174
    这篇文章主要介绍了Java编程调用微信支付功能的方法,结合实例形式详细分析了java微信支付功能的原理、操作流程及相关实现技巧,需要的朋友可以参考下

    本文实例讲述了Java编程调用微信支付功能的方法。分享给大家供大家参考,具体如下:

    从调用处开始

    我的流程: 1.点击“支付”按钮,去后台 —-> 2.后台生成支付所需数据返回页面 —-> 3.页面点击“确认支付”调用微信支付js。完成支付功能

    支付按钮


    <p class="button" id="pay" onclick="payBox()">支付</p>

    支付按钮js


    function payBox(){
        //获得支付的钱数
        var money = $(".money input").val();
        //后台路径,加上参数
        location.href = "/XXX/XXX/XXXX/XXXX?money ="+money;
    }

    后台方法(例:index())

    注释:

    getPara( ) == request.getParameter(name);
    setAttr( ) == request.setAttribute(name, value);
    render() == 我现在所用框架返回页面的一种方法。

    首先得OpenId;下面是具体方法。


    public String getOpenId(){
      String code = getPara("code");
      String openid = "";
        if (StringUtils.isEmpty(openid) && !StringUtils.isEmpty(code)) {
          SnsAccessToken token = SnsAccessTokenApi.getSnsAccessToken("你的APPID","你的appsecret密码",
              code);
          openid = token.getOpenid();
        }
        getSession().setAttribute("openandid",openid);
        return openid;
    }
    public void index() throws Exception{
        String openid = getOpenId();
        //得到金额
        String money= getPara("money");
        Map<String ,String > map=new HashMap<String,String>();
        //获取随机串
        String nonceStr=UUID.randomUUID().toString().substring(0, 32);
        //可以是支付物品的订单号。一个号码,看自己怎么给
        String out_trade_no="123456789";
        //支付金额。微信默认支付是(1=0.01)的比例,下面是将金额换算成微信可识别的
        BigDecimal re1=new BigDecimal(expressCharge);
        BigDecimal re2=new BigDecimal(Float.toString(100.00f));
        Float aa = re1.multiply(re2).floatValue();
        String total_fee = String.valueOf(aa);
        String[] smill = total_fee.split("\\.");
        total_fee = smill[0];
        //微信的appid
        String appid="XXXXXXXXXXXXXXXXX";
        String mch_id="XXXXXXXXX";//商户号
        String body="xxxxxxx";//商品信息,可以自己起最好写英文
        //密匙,商户平台的支付API密匙,注意是商户平台,不是微信平台
        String key = "XXXXXXXXXXXXXXXXXXXXXXXXXXXX";
        long timestamp = System.currentTimeMillis() / 1000;
        map.put("appid", appid );
        map.put("mch_id", mch_id);
        map.put("nonce_str",nonceStr);
        map.put("body", body);
        map.put("out_trade_no", out_trade_no);
        map.put("total_fee", total_fee);
        map.put("spbill_create_ip",getRequest().getRemoteAddr());
        //这里是支付成功后返回的地址,微信会以XML形式放回数据,就是本篇文章的下一类(例:wxxml())方法名。
        map.put("notify_url", "http://www.XXXX.com/XXXX/XXXX/xxxx/wxxml");
        map.put("trade_type", "JSAPI");
        map.put("openid", openid);//传入OpenId
        //这里传入Map集合和key商户支付密匙
        String paySign=getPayCustomSign(map,key);
        map.put("sign",paySign);
        //将map转为XML格式
        String xml= ArrayToXml(map);
        //统一下单,这里不用改
        String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
        String xmlStr = HttpKit.post(url, xml);
        //prepayid由微信返回的 。
        String prepayid = "";
        if (xmlStr.indexOf("SUCCESS") != -1) {
          Map<String, String> map2 = doXMLParse(xmlStr);
          prepayid = (String) map2.get("prepay_id");
        }
        String paySign2=getPayCustomSign(signMap,key);
        setAttr("model", model);
        setAttr("appId", appid);
        setAttr("paytimestamp", String.valueOf(timestamp));
        setAttr("paynonceStr", nonceStr);
        setAttr("paypackage", "prepay_id="+prepayid);
        setAttr("paysignType","MD5");
        setAttr("paySign", paySign2);
        //去到确认支付页面,返回页面方式不同,(例:pay.html页面),下面
        render("/XXXX/pay.html");
    }
    /**
    * 获取支付所需签名
    * @param ticket
    * @param timeStamp
    * @param card_id
    * @param code
    * @return
    * @throws Exception
    */
    public static String getPayCustomSign(Map<String, String> bizObj,String key) throws Exception {
        String bizString = FormatBizQueryParaMap(bizObj, false);
        return sign(bizString, key);
    }
    /**
    * 字典排序
    * @param paraMap
    * @param urlencode
    * @return
    * @throws Exception
    */
    public static String FormatBizQueryParaMap(Map<String, String> paraMap,
      boolean urlencode) throws Exception {
        String buff = "";
        try {
          List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(paraMap.entrySet());
          Collections.sort(infoIds,
              new Comparator<Map.Entry<String, String>>() {
          public int compare(Map.Entry<String, String> o1,
             Map.Entry<String, String> o2) {
             return (o1.getKey()).toString().compareTo(
                      o2.getKey());
                }
              });
          for (int i = 0; i < infoIds.size(); i++) {
            Map.Entry<String, String> item = infoIds.get(i);
            //System.out.println(item.getKey());
            if (item.getKey() != "") {
              String key = item.getKey();
              String val = item.getValue();
              if (urlencode) {
                val = URLEncoder.encode(val, "utf-8");
              }
              buff += key + "=" + val + "&";
            }
          }
          if (buff.isEmpty() == false) {
            buff = buff.substring(0, buff.length() - 1);
          }
        } catch (Exception e) {
          throw new Exception(e.getMessage());
        }
        return buff;
    }
    //支付所需签名处调用此方法
    public static String sign(String content, String key)
      throws Exception{
        String signStr = "";
        signStr = content + "&key=" + key;
        return MD5(signStr).toUpperCase();
    }
    //上一方法,MD5加密处理
    public final static String MD5(String s) {
        char hexDigits[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
        try {
          byte[] btInput = s.getBytes();
          MessageDigest mdInst = MessageDigest.getInstance("MD5");
          mdInst.update(btInput);
          byte[] md = mdInst.digest();
          int j = md.length;
          char str[] = new char[j * 2];
          int k = 0;
          for (int i = 0; i < j; i++) {
            byte byte0 = md[i];
            str[k++] = hexDigits[byte0 >>> 4 & 0xf];
            str[k++] = hexDigits[byte0 & 0xf];
          }
          return new String(str);
        } catch (Exception e) {
          e.printStackTrace();
          return null;
        }
    }
    //转为XML格式
    public static String ArrayToXml(Map<String, String> arr) {
        String xml = "<xml>";
        Iterator<Entry<String, String>> iter = arr.entrySet().iterator();
        while (iter.hasNext()) {
          Entry<String, String> entry = iter.next();
          String key = entry.getKey();
          String val = entry.getValue();
          if (IsNumeric(val)) {
            xml += "<" + key + ">" + val + "</" + key + ">";
          } else
            xml += "<" + key + "><![CDATA[" + val + "]]></" + key + ">";
        }
        xml += "</xml>";
        return xml;
    }
    public static boolean IsNumeric(String str) {
        if (str.matches("\\d *")) {
          return true;
        } else {
          return false;
        }
    }
    //解析XML
    private Map<String, String> doXMLParse(String xml)
        throws XmlPullParserException, IOException {
          InputStream inputStream = new ByteArrayInputStream(xml.getBytes());
          Map<String, String> map = null;
          XmlPullParser pullParser = XmlPullParserFactory.newInstance()
              .newPullParser();
          pullParser.setInput(inputStream, "UTF-8");// 为xml设置要解析的xml数据
          int eventType = pullParser.getEventType();
          while (eventType != XmlPullParser.END_DOCUMENT) {
            switch (eventType) {
            case XmlPullParser.START_DOCUMENT:
              map = new HashMap<String, String>();
              break;
            case XmlPullParser.START_TAG:
              String key = pullParser.getName();
              if (key.equals("xml"))
                break;
              String value = pullParser.nextText();
              map.put(key, value);
              break;
            case XmlPullParser.END_TAG:
              break;
            }
            eventType = pullParser.next();
          }
          return map;
    }

    pay页面(上面步骤执行完后去的页面)

    此处是页面js代码,接受后台代码传回来的参数。现在用的是BSL模板引擎,参数可以以EL表达式方式接收。可先将后台传会的参数,放在几个input类型type=”hidden”标签标签中。


    <input type="hidden" name="appId" value="${appId}" id="appid" />

    js中得到值


    var appid = $("#appid").val();

    js引用


    <script type="text/javascript" src="${staticPath}/front/js/weixin.js"></script>

    下面是JS代码,由于是bsl,自己看着传参数吧,反正都是后台来的。


    <p class="button" id="onlinePayNow">确认支付</p>


    //先写一个点击事件,当点击id为onlinePayNow的按钮时,触发该事件。
    $("#onlinePayNow").click(function getpay(){
      if (typeof WeixinJSBridge=="undefined") {
        if (document.addEventListener) {document.addEventListener('WeixinJSBridgeReady',onBridgeReady,false);
        }else if(document.attachEvent){document.attachEvent('WeixinJSBridgeReady',onBridgeReady);document.attachEvent('onWeixinJSBridgeReady',onBridgeReady);
        }
      }else{
        //如果报错,可用下面方法看看是不是参数缺少。
        /* alert('${appId}');
        alert('${paytimestamp}');
        alert('${paynonceStr}');
        alert('${paypackage}');
        alert('${paysignType}');
        alert('${paySign}'); */
        //调用下面方法。开启微信支付。
        onBridgeReady();
      }
    })
    function onBridgeReady(){
      WeixinJSBridge.invoke('getBrandWCPayRequest', {
        "appId" : '${appId}', //公众号名称,由商户传入
        "timeStamp" : '${paytimestamp}', //时间戳,自1970年以来的秒数
        "nonceStr" : '${paynonceStr}', //随机串
        "package" : '${paypackage}',
        "signType" : '${paysignType}', //微信签名方式:
        "paySign" : '${paySign}' //微信签名
      }, function(res) {
        //alert(res.err_msg); // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返
        if(res.err_msg == "get_brand_wcpay_request:ok"){
        //支付成功,完成后去到哪个页面。
        window.location.href="/XXXX/xxxx.html" rel="external nofollow" ;
        }
      });
    }

    在微信公众平台配置,支付授权目录。

    授权目录建议:

    http://www.XXXX.com/XXXX/xxx/index/

    我觉得最好写后台是action地址就写Action地址,Controller就写Controller地址,如果有Spring注解,就写注解后名称。

    我所导入的包(java后台,就是index方法。)


    import java.io.ByteArrayInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.math.BigDecimal;
    import java.net.URLEncoder;
    import java.security.MessageDigest;
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.Comparator;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;
    import java.util.Map.Entry;
    import java.util.UUID;
    import org.xmlpull.v1.XmlPullParser;
    import org.xmlpull.v1.XmlPullParserException;
    import org.xmlpull.v1.XmlPullParserFactory;
    import com.jfinal.kit.HttpKit;
    import com.uitrs.express.common.Constants;

    以上就是Java中调用微信支付功能的实例分析的详细内容,更多请关注php中文网其它相关文章!

    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。
    专题推荐:Java 实例分析 功能
    上一篇:Java如何实现原生socket通信机制的原理详解 下一篇:关于Java如何调用微信客服消息来完成发货通知的实例(图)
    20期PHP线上班

    相关文章推荐

    • 【活动】充值PHP中文网VIP即送云服务器• JAVA接口与抽象类详细解析• Java实现多线程的四种方式• Java基础之volatile详解• Java中super关键字的用法详解• 归纳整理Java线程面试题
    1/1

    PHP中文网