微信支付+支付宝支付

微信支付参考链接:

  (1)微信公众平台开发文档http://mp.weixin.qq.com/wiki/home/index.html

  (2)微信支付普通商户接入文档https://pay.weixin.qq.com/wiki/doc/api/index.html

  (3)接口调试工具http://mp.weixin.qq.com/debug/

  (4)开发者问答系统http://mp.weixin.qq.com/qa/home/index.html

  (5)JSSDK实例代码http://demo.open.weixin.qq.com/jssdk/js/demo.js

  (6)商户后台登陆界面https://pay.weixin.qq.com/index.php/home/login?return_url=%2F

  (7)商户平台开发文档http://pay.weixin.qq.com/wiki/doc/api/index.html

  (8)基于H5的微信支付开发详解http://daimajun.com/web/31.html

  (9)在Web应用中接入微信支付的流程http://www.cnblogs.com/alex1128/p/wxpay.html

获取时间戳:

  var timestamp1 = Date.parse(new Date());
  var timestamp2 = (new Date()).valueOf();
  var timestamp3 = new Date().getTime();
注:第一种获取的时间戳是把毫秒改成000显示,第二种和第三种获取了当前毫秒的时间戳。
  获取秒级别的时间戳,可以/1000。

支付宝支付

(1)即时支付:https://b.alipay.com/order/productDetail.htm?productId=2015110218012942

(2)在线文档:https://doc.open.alipay.com/doc2/detail?treeId=62&articleId=103566&docType=1

设定时间格式化函数:

Date.prototype.format = function (format) {
    var args = {
        "M+": this.getMonth() + 1,
        "d+": this.getDate(),
        "h+": this.getHours(),
        "m+": this.getMinutes(),
        "s+": this.getSeconds(),
    };
    if (/(y+)/.test(format))
        format = format.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
    for (var i in args) {
        var n = args[i];
        if (new RegExp("(" + i + ")").test(format))
            format = format.replace(RegExp.$1, RegExp.$1.length == 1 ? n : ("00" + n).substr(("" + n).length));
    }
    return format;
};

微信支付(统一下单)

      思路:

      ①将appid、mch_id、nonce_str、body、attach、out_trade_no、total_fee、spbill_create_ip、notify_url、trade_type 这些参数以键值对的形式拼接起来用MD5进行第一次签名

     ②拼接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>

,把这个xml 交个  "https://api.mch.weixin.qq.com/pay/unifiedorder"  在微信 生成一个预支付订单号prepay_id

   ③将 appid、partner、prepay_id、nonce_str、timestamp、partnerkey、key、package  通过键值对的形式拼接,然后MD5加密处理,和第一步加密方式一样进行第二次签名

  ④将appid、partnerid、prepayid、package、noncestr、timestamp、sign  传给 调起微信支付功能

注:一些用到的方法

1、MD5  将map 拼接成键值对的串,然后进行加密

/**
     * 创建md5摘要,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。
     */
    public String createSign(SortedMap<String, String> packageParams) {
        StringBuffer sb = new StringBuffer();
        Set es = packageParams.entrySet();
        Iterator it = es.iterator();
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            String k = (String) entry.getKey();
            String v = (String) entry.getValue();
            if (null != v && !"".equals(v) && !"sign".equals(k)
                    && !"key".equals(k)) {
                sb.append(k + "=" + v + "&");
            }
        }
        sb.append("key=" + this.getKey());
        String sign = MD5Util.MD5Encode(sb.toString(), this.charset)
                .toUpperCase();
        return sign;

    }

2、将xml交给 "https://api.mch.weixin.qq.com/pay/unifiedorder"  解析生成 预支付订单

    如果参数提交失败,会在try里的 if 中 返回  开发的时候建议打断点,我是存session ,然后返回错误信息msg

/**
   *description:获取预支付id
   *@param urls
   *@param xmlParam
   *@return
   * @author ex_yangxiaoyi
   * @see
   */
  public static String getPayNo(String url,String xmlParam){
      Subject currentUser = SecurityUtils.getSubject();  
      Session session = currentUser.getSession();
      
      DefaultHttpClient client = new DefaultHttpClient();
      client.getParams().setParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS, true);
      HttpPost httpost= HttpClientConnectionManager.getPostMethod(url);
      String prepay_id = "";
     try {
         httpost.setEntity(new StringEntity(xmlParam, "UTF-8"));
         HttpResponse response = httpclient.execute(httpost);
         String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");
        if(jsonStr.indexOf("FAIL")!=-1){
            session.setAttribute("error_msg", jsonStr);
            return prepay_id;
        }
        Map map = doXMLParse(jsonStr);
        prepay_id  = (String) map.get("prepay_id");
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return prepay_id;
  }
 public static InputStream String2Inputstream(String str) {
       return new ByteArrayInputStream(str.getBytes());
}

3、xml解析

/**
     * 解析xml,返回第一级元素键值对。如果第一级元素有子节点,则此节点的值是子节点的xml数据。
     * @param strxml
     * @return
     * @throws JDOMException
     * @throws IOException
     */
    public static Map doXMLParse(String strxml) throws Exception {
        if(null == strxml || "".equals(strxml)) {
            return null;
        }
        
        Map m = new HashMap();
        InputStream in = String2Inputstream(strxml);
        SAXBuilder builder = new SAXBuilder();
        Document doc = builder.build(in);
        Element root = doc.getRootElement();
        List list = root.getChildren();
        Iterator it = list.iterator();
        while(it.hasNext()) {
            Element e = (Element) it.next();
            String k = e.getName();
            String v = "";
            List children = e.getChildren();
            if(children.isEmpty()) {
                v = e.getTextNormalize();
            } else {
                v = getChildrenText(children);
            }
            
            m.put(k, v);
        }
        
        //关闭流
        in.close();
        
        return m;
    }
/**
     * 获取子结点的xml
     * @param children
     * @return String
     */
    public static String getChildrenText(List children) {
        StringBuffer sb = new StringBuffer();
        if(!children.isEmpty()) {
            Iterator it = children.iterator();
            while(it.hasNext()) {
                Element e = (Element) it.next();
                String name = e.getName();
                String value = e.getTextNormalize();
                List list = e.getChildren();
                sb.append("<" + name + ">");
                if(!list.isEmpty()) {
                    sb.append(getChildrenText(list));
                }
                sb.append(value);
                sb.append("</" + name + ">");
            }
        }
        
        return sb.toString();
    }

 4、微信回调函数

/**
     * 微信支付 回调函数
     */
    @RequestMapping("/notify")
    @ResponseBody
    protected void notify(HttpServletRequest request,
            HttpServletResponse response) throws Exception {
        
        PageData pd=new PageData();
        logBefore(logger, "微信支付  回调函数");
        //把如下代码贴到的你的处理回调的servlet 或者.do 中即可明白回调操作
        logger.info("微信支付回调数据开始");
        //示例报文
        //String xml = "<xml><appid><![CDATA[wxb4dc385f953b356e]]></appid><bank_type><![CDATA[CCB_CREDIT]]></bank_type><cash_fee><![CDATA[1]]></cash_fee><fee_type><![CDATA[CNY]]></fee_type><is_subscribe><![CDATA[Y]]></is_subscribe><mch_id><![CDATA[1228442802]]></mch_id><nonce_str><![CDATA[1002477130]]></nonce_str><openid><![CDATA[o-HREuJzRr3moMvv990VdfnQ8x4k]]></openid><out_trade_no><![CDATA[1000000000051249]]></out_trade_no><result_code><![CDATA[SUCCESS]]></result_code><return_code><![CDATA[SUCCESS]]></return_code><sign><![CDATA[1269E03E43F2B8C388A414EDAE185CEE]]></sign><time_end><![CDATA[20150324100405]]></time_end><total_fee>1</total_fee><trade_type><![CDATA[JSAPI]]></trade_type><transaction_id><![CDATA[1009530574201503240036299496]]></transaction_id></xml>";
        String inputLine;
        String notityXml = "";
        String resXml = "";

        try {
            while ((inputLine = request.getReader().readLine()) != null) {
                notityXml += inputLine;
            }
            request.getReader().close();
        } catch (Exception e) {
            e.printStackTrace();
        }

        System.out.println("接收到的报文:" + notityXml);
        
        BufferedWriter writer = new BufferedWriter(new FileWriter(new File("c:\ResultXml.txt"),true));
         //
         writer.write(DateUtil.getTime()+notityXml+"
");
         writer.close();
        
        Map m = parseXmlToList2(notityXml);
        WxPayResult wpr = new WxPayResult();
        wpr.setAppid(m.get("appid").toString());
        wpr.setBankType(m.get("bank_type").toString());
        wpr.setCashFee(m.get("cash_fee").toString());
        wpr.setFeeType(m.get("fee_type").toString());
        wpr.setIsSubscribe(m.get("is_subscribe").toString());
        wpr.setMchId(m.get("mch_id").toString());
        wpr.setNonceStr(m.get("nonce_str").toString());
        wpr.setOpenid(m.get("openid").toString());
        wpr.setOutTradeNo(m.get("out_trade_no").toString());
        wpr.setResultCode(m.get("result_code").toString());
        wpr.setReturnCode(m.get("return_code").toString());
        wpr.setSign(m.get("sign").toString());
        wpr.setTimeEnd(m.get("time_end").toString());
        wpr.setTotalFee(m.get("total_fee").toString());
        wpr.setTradeType(m.get("trade_type").toString());
        wpr.setTransactionId(m.get("transaction_id").toString());
        
        if("SUCCESS".equals(wpr.getResultCode())){
            //支付成功
            resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
            + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
            //修改订单状态
            pd.put("WX_ORDER", wpr.getOutTradeNo());
            wxPayService.editStatusByOutId(pd);
            //保存订单信息
            pd.put("WX_ORDER_ID", UuidUtil.get32UUID());//微信订单主键ID
            pd.put("OPEN_ID", wpr.getOpenid());//用户的OPEN_ID
            pd.put("MCH_ID", wpr.getMchId());//商户号
            pd.put("NONCE_STR", wpr.getNonceStr());//随机字符串
            pd.put("SIGN", wpr.getSign());//SIGN
            pd.put("CASH_FEE", wpr.getCashFee());//现金支付金额
            pd.put("TOTAL_FEE", wpr.getTotalFee());//总金额
            pd.put("BANK_TYPE", wpr.getBankType());//付款银行
            pd.put("TRADE_TYPE", wpr.getTradeType());//交易类型
            pd.put("RESULT_CODE", wpr.getResultCode());//业务结果
            pd.put("TRANSACTION_ID", wpr.getTotalFee());//微信支付订单号
            pd.put("TIME_END", wpr.getTimeEnd());//微信支付完成时间
            wxPayService.saveWxOrder(pd);
        }else{
            resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
            + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
        }

        System.out.println("微信支付回调数据结束");

        BufferedOutputStream out = new BufferedOutputStream(
                response.getOutputStream());
        out.write(resXml.getBytes());
        out.flush();
        out.close();

    }

解析微信通知xml

/**
     * description: 解析微信通知xml
     * 
     * @param xml
     * @return
     * @author ex_yangxiaoyi
     * @see
     */
    @SuppressWarnings({ "unused", "rawtypes", "unchecked" })
    private static Map parseXmlToList2(String xml) {
        Map retMap = new HashMap();
        try {
            StringReader read = new StringReader(xml);
            // 创建新的输入源SAX 解析器将使用 InputSource 对象来确定如何读取 XML 输入
            InputSource source = new InputSource(read);
            // 创建一个新的SAXBuilder
            SAXBuilder sb = new SAXBuilder();
            // 通过输入源构造一个Document
            Document doc = (Document) sb.build(source);
            Element root = doc.getRootElement();// 指向根节点
            List<Element> es = root.getChildren();
            if (es != null && es.size() != 0) {
                for (Element element : es) {
                    retMap.put(element.getName(), element.getValue());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return retMap;
    }
原文地址:https://www.cnblogs.com/sweetyu/p/5163091.html