微信H5支付(基於Java實現微信H5支付)


微信的H5支付區別與APP支付,主要在於預下單(返回的參數不一樣),其它大體相同(基本沒什么區別,區別在於有些人加密喜歡用MD5有些人喜歡用官方提供的加密方式加密,我用的是官方的),貼一下H5支付預下單的業務層以及控制層代碼方便以后參考,其它代碼可以參考微信APP支付

  • 業務層(預下單)
import com.aone.app.common.util.RandomNumUtil;
import com.aone.app.common.wx.*;
import com.aone.app.service.WxH5PayService;
import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

@Service
public class WxH5PayServiceImpl implements WxH5PayService {

    private static final Logger logger = LoggerFactory.getLogger("WxH5PayServiceImpl");
    @Autowired
    private WxCfg wxCfg;

    /**
     * /H5微信支付(預下單)
     * @param type
     * @param out_trade_no
     * @param money
     * @return
     * @throws Exception
     */
    @Override
    public Map<String, String> dounifiedOrder(String type, String out_trade_no, String money, HttpServletRequest request) throws Exception {
        //返回參數
        Map<String, String> returnMap = new HashMap<>();
        //微信配置
        WXConfigUtil config = new WXConfigUtil();
        WXPay wxpay = new WXPay(config);
        //請求參數封裝
        Map<String, String> data = new HashMap<>();
        data.put("appid", config.getAppID());
        data.put("mch_id", config.getMchID());
        data.put("nonce_str", WXPayUtil.generateNonceStr());
        data.put("body", "H5訂單支付");
        data.put("out_trade_no", RandomNumUtil.getOrderIdByTime());//訂單號
        data.put("total_fee", "1");//支付金額
        data.put("spbill_create_ip", IpAddr.getIpAddr(request)); //自己的服務器IP地址
        data.put("notify_url", wxCfg.getH5NotifyUrl());//異步通知地址(請注意必須是外網)
        data.put("trade_type", wxCfg.getH5Type());//交易類型
        data.put("attach", type);//附加數據,在查詢API和支付通知中原樣返回,該字段主要用於商戶攜帶訂單的自定義數據
        String s = WXPayUtil.generateSignature(data, config.getKey());  //簽名
        data.put("sign", s);//簽名
        try {
            logger.info("sign{}",data.get("sign"));
            //使用官方API請求預付訂單
            Map<String, String> response = wxpay.unifiedOrder(data);
            String returnCode = response.get("return_code");//獲取返回碼
            logger.info("返回碼{}",returnCode); //獲取返回碼
            //若返回碼為SUCCESS,則會返回一個result_code,再對該result_code進行判斷
            if (returnCode.equals("SUCCESS")) {
                returnMap.put("ok", "200");
                //拼接返回跳轉地址
                String url= UrlEnCode.urlEncode(wxCfg.getRedirect_url());
                logger.info("url{}",url);
                returnMap.put("url", response.get("mweb_url")+"&redirect_url="+url);
            } else {
                returnMap.put("ok", "201");
                returnMap.put("url",null);
                return returnMap;
            }
        } catch (Exception e) {
            System.out.println(e);
            //系統等其他錯誤的時候
        }
        return returnMap;
    }


}
  • 控制層下單接口以及回調接口
import com.aone.app.common.wx.XMLUtils;
import com.aone.app.service.WxH5PayService;
import io.swagger.annotations.Api;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("h5pay")
@Api("H5支付")
public class PayH5Controller {

    private static final Logger log = LoggerFactory.getLogger("PayH5Controller");

    @Autowired
    private WxH5PayService  wxH5PayService;

    /**
     * H5支付統一下單
     * @param request
     * @return
     * @throws Exception
     */
    @ResponseBody
    @RequestMapping(value = "wxPay")
    public Map<String, String> weixinPay(HttpServletRequest request) throws Exception{
        String  type= request.getParameter("type");
        String  orderNo= request.getParameter("orderNo");
        String  money= request.getParameter("money");     
        return wxH5PayService.dounifiedOrder(type,orderNo, money,request);
    }

    /**
     * H5微信支付異步結果通知
     * @param request
     * @param response
     * @throws Exception
     */
    @RequestMapping(value = "notify")
    public void weixinPayNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
        BufferedReader reader = request.getReader();
        String line = "";
        Map map = new HashMap();
        String xml = "<xml><return_code><![CDATA[FAIL]]></xml>";;
        StringBuffer inputString = new StringBuffer();
        while ((line = reader.readLine()) != null) {
            inputString.append(line);
        }
        request.getReader().close();
        log.error("----接收到的報文---{}",inputString.toString());
        if(inputString.toString().length()>0){
            map = XMLUtils.parseXmlToList(inputString.toString());
        }else{
            log.error("接受微信報文為空");
        }
        log.error("map={}",map);
        if(map!=null && "SUCCESS".equals(map.get("result_code"))){
            //成功的業務。。。
            xml = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
            String type=map.get("attach").toString();
            String orderNo=map.get("out_trade_no").toString();
            log.error("訂單號{}",map.get("out_trade_no"));log.error("其它必須參數{}",map.get("attach"));
            if(StringUtils.isEmpty(type)||StringUtils.isEmpty(orderNo)){
                log.error("當前參數類型異常");
            }else{
               //回調業務處理

            }
        }else{
            //失敗的業務。。。
        }
        //告訴微信端已經確認支付成功
        response.getWriter().write(xml);
    }


}
  • H5回調接口中解析微信通知XML的工具類
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import org.xml.sax.InputSource;

import java.io.StringReader;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class XMLUtils {

    /**
     * 解析微信通知xml
     * @param xml
     * @return
     */
    @SuppressWarnings({ "unused", "rawtypes", "unchecked" })
    public static Map parseXmlToList(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;

    }
}

微信支付過程中所需其它參數(應用AppID,商戶密鑰,商戶號,以及商戶證書的下載),參考微信官方開發文檔。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM