微信H5支付

2022-03-10 16:48:32 浏览数 (1)

微信支付分很多种,其中微信H5支付是给在手机浏览器上使用,在手机上发起付款,自动跳转到微信并付款

微信支付开发文档:https://pay.weixin.qq.com/wiki/doc/api/index.html

微信H5支付文档:https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=15_1

微信统一下单接口:https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=9_1

微信H5支付流程:

1、用户在商户侧完成下单,使用微信支付进行支付

2、由商户后台向微信支付发起下单请求(调用统一下单接口)注:交易类型trade_type=MWEB

3、统一下单接口返回支付相关参数给商户后台,如支付跳转url(参数名“mweb_url”),商户通过mweb_url调起微信支付中间页

4、中间页进行H5权限的校验,安全性检查(此处常见错误请见下文)

5、如支付成功,商户后台会接收到微信侧的异步通知

6、用户在微信支付收银台完成支付或取消支付,返回商户页面(默认为返回支付发起页面)

7、商户在展示页面,引导用户主动发起支付结果的查询

8,9、商户后台判断是否接到收微信侧的支付结果通知,如没有,后台调用我们的订单查询接口确认订单状态

10、展示最终的订单支付结果给用户

支付部分代码:

代码语言:javascript复制
   /**
     * 微信H5支付2号方案
     */
    @RequestMapping("/wapPay")
    @ResponseBody
    public net.sf.json.JSONObject pay(HttpServletRequest  request, HttpServletResponse response, Integer userid, Double money, Integer num)
            throws ServletException, IOException {

        request.setCharacterEncoding("UTF-8");
        net.sf.json.JSONObject json = new net.sf.json.JSONObject();

        String ip = null;

        //以下代码为获取请求的公网IP
        //X-Forwarded-For:Squid 服务代理
        String ipAddresses = request.getHeader("X-Forwarded-For");

        if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
            //Proxy-Client-IP:apache 服务代理
            ipAddresses = request.getHeader("Proxy-Client-IP");
        }

        if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
            //WL-Proxy-Client-IP:weblogic 服务代理
            ipAddresses = request.getHeader("WL-Proxy-Client-IP");
        }

        if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
            //HTTP_CLIENT_IP:有些代理服务器
            ipAddresses = request.getHeader("HTTP_CLIENT_IP");
        }

        if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
            //X-Real-IP:nginx服务代理
            ipAddresses = request.getHeader("X-Real-IP");
        }

        //有些网络通过多层代理,那么获取到的ip就会有多个,一般都是通过逗号(,)分割开来,并且第一个ip为客户端的真实IP
        if (ipAddresses != null && ipAddresses.length() != 0) {
            ip = ipAddresses.split(",")[0];
        }

        //还是不能获取到,最后再通过request.getRemoteAddr();获取
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
            ip = request.getRemoteAddr();
        }
        if (StrKit.isBlank(ip)) {
            ip = "127.0.0.1";
        }

        int intMoney =(int)(money * 100);
        //商户相关资料
        String appid = "***";//公众号appid
        String appsecret = "***";//公众号秘钥
        String partner = "***";//商户号
        String partnerkey = "***";//商户API秘钥

        //用于获取随机数
        String currTime = TenpayUtil.getCurrTime();//获取当前时间
        String strTime = currTime.substring(8, currTime.length());//8位日期
        String strRandom = TenpayUtil.buildRandom(4)   "";//四位随机数
        String strReq = strTime   strRandom;//10位序列号,可以自行调整

        String orderNo=appid userid  Sha1Util.getTimeStamp();//随机生成了一个订单号

        //商户号
        String mch_id = partner;

        //设备号   非必输
        String device_info="WEB";

        //随机数
        String nonce_str = strReq;

        //商品描述
        String body = "号码筛选充值";

        //附加数据
        String attach = "shengyu";

        //商户订单号
        String out_trade_no = orderNo;

        //总金额以分为单位,不带小数点
        int total_fee = intMoney;

//        String spbill_create_ip = request.getRemoteAddr();
        String spbill_create_ip = ip;

        String trade_type = "MWEB";//H5支付方式

        SortedMap<String, String> packageParams = new TreeMap<String, String>();
        packageParams.put("appid", appid);
        packageParams.put("mch_id", mch_id);
        packageParams.put("nonce_str", nonce_str);
        packageParams.put("body", body);
        packageParams.put("attach", attach);
        packageParams.put("out_trade_no", out_trade_no);
        packageParams.put("total_fee", String.valueOf((intMoney)));
        packageParams.put("spbill_create_ip", spbill_create_ip);
        packageParams.put("notify_url", notify_url);
        packageParams.put("trade_type", trade_type);
        RequestHandler reqHandler = new RequestHandler(request, response);
        reqHandler.init(appid, appsecret, partnerkey);

        //获取签名
        String sign = reqHandler.createSign(packageParams);

        String xml="<xml>" 
                "<appid>" appid "</appid>" 
                "<mch_id>" mch_id "</mch_id>" 
                "<nonce_str>" nonce_str "</nonce_str>" 
                "<sign>" sign "</sign>" 
                "<body>" body "</body>" 
                "<attach>" attach "</attach>" 
                "<out_trade_no>" out_trade_no "</out_trade_no>" 
                "<total_fee>" total_fee "</total_fee>" 
                "<spbill_create_ip>" spbill_create_ip "</spbill_create_ip>" 
                "<notify_url>" notify_url "</notify_url>" 
                "<out_trade_no>"  orderNo "</out_trade_no>" 
                "<trade_type>" trade_type "</trade_type>" 
                "</xml>";

        String allParameters = "";//没用
        try {
            allParameters =  reqHandler.genPackage(packageParams);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        //请求微信统一下单接口,成功后返回预支付交易会话标识prepay_id
        String createOrderURL = "https://api.mch.weixin.qq.com/pay/unifiedorder";
        String prepay_id = "";
        String mweb_url="";
        try {
            Map<String ,String> returnmap= new GetWxOrderno().getPayNo(createOrderURL, xml);
            prepay_id=returnmap.get("prepay_id");
            mweb_url=returnmap.get("mweb_url");
            if(prepay_id.equals("")){
                json.put("msg","统一支付接口获取预支付订单出错");
                return json;
            }
            //这里可以放增加订单信息

        } catch (Exception e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

        //生成H5调起微信支付API相关参数(前端页面js的配置参数)
        SortedMap<String, String> finalpackage = new TreeMap<String, String>();
        String timestamp = Sha1Util.getTimeStamp();//当前时间的时间戳
        String packages = "prepay_id=" prepay_id;;//订单详情扩展字符串
        finalpackage.put("appId", appid);//公众号appid
        finalpackage.put("timeStamp", timestamp);
        finalpackage.put("nonceStr", strReq); //随机数
        finalpackage.put("package", packages);
        finalpackage.put("signType", "MD5");//签名方式
        String finalsign = reqHandler.createSign(finalpackage);//签名

        String returnurl_1="";
        try {
            returnurl_1=returnurl;
            // 将普通字符创转换成application/x-www-from-urlencoded字符串
            returnurl_1 = URLEncoder.encode(returnurl, "GBK"); 
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        json.put("appId", appid);
        json.put("timeStamp", timestamp);
        json.put("nonceStr", strReq);
        json.put("packages", packages);
        json.put("sign", finalsign);
        json.put("mweb_url", mweb_url "&redirect_url=" returnurl);// "&redirect_url=wap/rechargeSuccess.html"
        return json;
    }

    /**
     * 支付完成的回调,修改订单状态等
     * @return
     */
    @ResponseBody
    @RequestMapping("/trueOrder")
    public String notify(HttpServletRequest request, HttpServletResponse response)
            throws Exception {

        BufferedReader br = new BufferedReader(new InputStreamReader((ServletInputStream) request.getInputStream()));
        String line = null;
        StringBuilder sb = new StringBuilder();
        while ((line = br.readLine()) != null) {
            sb.append(line);
        }

        StringBuilder jsonStr = sb;
        Map<String, Object> dataMap = new HashMap<String, Object>();

        Map map = doXMLParse(jsonStr.toString());
        String out_trade_no  = (String) map.get("out_trade_no");//获取订单号
        //下面是根据订单号修改订单状态、账户余额等

        //返回,如果不加可能会请求多次
        return  "<xml>"  
                "<return_code><![CDATA[SUCCESS]]></return_code>"  
                "<return_msg><![CDATA[支付成功]]></return_msg>"  
                "</xml>";
    }

0 人点赞