微信支付+支付寶支付

微信支付參考連接:

  (1)微信公衆平臺開發文檔http://mp.weixin.qq.com/wiki/home/index.htmlphp

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

  (3)接口調試工具http://mp.weixin.qq.com/debug/web

  (4)開發者問答系統http://mp.weixin.qq.com/qa/home/index.htmljson

  (5)JSSDK實例代碼http://demo.open.weixin.qq.com/jssdk/js/demo.jsapi

  (6)商戶後臺登錄界面https://pay.weixin.qq.com/index.php/home/login?return_url=%2F微信

  (7)商戶平臺開發文檔http://pay.weixin.qq.com/wiki/doc/api/index.htmlsession

  (8)基於H5的微信支付開發詳解http://daimajun.com/web/31.htmlapp

  (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  傳給 調起微信支付功能

 

注:一些用到的方法

一、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;

    }

二、將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());
}

三、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();
    }

 四、微信回調函數

/**
     * 微信支付 回調函數
     */
    @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+"\r\n");
         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;
    }
相關文章
相關標籤/搜索