微信公众号支付H5-java版代码

1,工具类

package net.jeeshop.core.util;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;

import java.io.*;
import java.math.BigDecimal;
import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;

/**
 */
public class PayCommonUtil {
    //微信参数配置
    public static String API_KEY = "xxxxxxxxxxxxxx";
    // APPID
    public static String APPID = "wx323323333333";
    // 商户ID
    public static String MCH_ID = "123232323";

    /**
     * 发起支付
     *
     * @param orderId 订单ID
     * @param amount  钱(元)
     * @param body    订单说明
     * @param openId  会员openID
     * @param ip      会员IP
     * @param url     回调URl
     * @return
     */
    public static SortedMap<String, String> pay(String orderId, BigDecimal amount, String body, String openId, String ip, String url) {
        String error = "";
        String prepayId = getPrepayId(orderId, amount, body, openId, url, ip);

        SortedMap<String, String> map = new TreeMap<String, String>();
        map.put("appId", PayCommonUtil.APPID);
        map.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000));
        map.put("nonceStr", PayCommonUtil.getRandomString(32));

        if (prepayId == null) {
            error = "验签失败!";
            map.put("error", error);
        }

        map.put("package", "prepay_id=" + prepayId);
        map.put("signType", "MD5");
        String sign = PayCommonUtil.createSign("UTF-8", map);
        map.put("paySign", sign);
        return map;
    }

    /**
     * 返回微信预支付prepay_id
     *
     * @param orderId    订单ID
     * @param amount     钱(元)
     * @param body       订单说明
     * @param openid     会员openID
     * @param notify_url 回调URl
     * @param ip         会员IP
     * @return
     */
    public static String getPrepayId(String orderId, BigDecimal amount, String body, String openid, String notify_url, String ip) {
        SortedMap<String, String> para = new TreeMap<String, String>();
        para.put("appid", PayCommonUtil.APPID);
        para.put("mch_id", PayCommonUtil.MCH_ID);
        para.put("nonce_str", PayCommonUtil.getRandomString(32));
        para.put("body", body);
        para.put("out_trade_no", orderId);
        para.put("fee_type", "CNY");

        BigDecimal total = amount.multiply(new BigDecimal(100));
        java.text.DecimalFormat df = new java.text.DecimalFormat("0");

        para.put("total_fee", df.format(total));
        para.put("spbill_create_ip", ip);
        para.put("notify_url", notify_url);
        para.put("trade_type", "JSAPI");
        para.put("openid", openid);
        String sign = createSign("UTF-8", para);
        para.put("sign", sign);
        String requestXML = PayCommonUtil.getRequestXml(para);
        String result = PayCommonUtil.httpsRequest("https://api.mch.weixin.qq.com/pay/unifiedorder", "POST", requestXML);
        Map<String, String> map = null;
        try {
            map = PayCommonUtil.doXMLParse(result);

// 返回信息
            if ("SUCCESS".equals(map.get("return_code")) && "SUCCESS".equals(map.get("result_code"))) {
                return map.get("prepay_id");
            } else {
                return null;
            }
        } catch (JDOMException e) {
            return null;
        } catch (IOException e) {
            return null;
        }
    }

    //随机字符串生成
    private static String getRandomString(int length) {
        String base = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        Random random = new Random();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            int number = random.nextInt(base.length());
            sb.append(base.charAt(number));
        }
        return sb.toString();
    }

    //请求xml组装
    private static String getRequestXml(SortedMap<String, String> parameters) {
        StringBuffer sb = new StringBuffer();
        sb.append("<xml>");
        Set es = parameters.entrySet();
        Iterator it = es.iterator();
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            String key = (String) entry.getKey();
            String value = (String) entry.getValue();
            if ("attach".equalsIgnoreCase(key) || "body".equalsIgnoreCase(key) || "sign".equalsIgnoreCase(key)) {
                sb.append("<" + key + ">" + "<![CDATA[" + value + "]]></" + key + ">");
            } else {
                sb.append("<" + key + ">" + value + "</" + key + ">");
            }
        }
        sb.append("</xml>");
        return sb.toString();
    }

    // 生成签名
    private static String createSign(String characterEncoding, SortedMap<String, String> parameters) {
        StringBuffer sb = new StringBuffer();
        Set es = parameters.entrySet();
        Iterator it = es.iterator();
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            String k = (String) entry.getKey();
            Object v = entry.getValue();
            if (null != v && !"".equals(v)
                    && !"sign".equals(k) && !"key".equals(k)) {
                sb.append(k + "=" + v + "&");
            }
        }
        sb.append("key=" + API_KEY);
        String sign = MD5.MD5Encode(sb.toString(), characterEncoding).toUpperCase();
        return sign;
    }

    /**
     * 验证回调签名
     */
    public static boolean isTenpaySign(Map<String, String> map) {
        String charset = "utf-8";
        String signFromAPIResponse = map.get("sign");
// API返回的数据签名数据不存在,有可能被第三方篡改!!!
        if (signFromAPIResponse == null || signFromAPIResponse.equals("")) {
            return false;
        }

//过滤空 设置 TreeMap
        SortedMap<String, String> packageParams = new TreeMap<String, String>();
        for (String parameter : map.keySet()) {
            String parameterValue = map.get(parameter);
            String v = "";
            if (null != parameterValue) {
                v = parameterValue.trim();
            }
            packageParams.put(parameter, v);
        }

        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 (!"sign".equals(k) && null != v && !"".equals(v)) {
                sb.append(k + "=" + v + "&");
            }
        }
        sb.append("key=" + API_KEY);
//算出签名
        String resultSign = "";
        String tobesign = sb.toString();
        if (null == charset || "".equals(charset)) {
            resultSign = MD5.MD5Encode(tobesign, charset).toUpperCase();
        } else {
            resultSign = MD5.MD5Encode(tobesign, charset).toUpperCase();
        }
        String tenpaySign = ((String) packageParams.get("sign")).toUpperCase();
        return tenpaySign.equals(resultSign);
    }

    // 请求方法
    private static String httpsRequest(String requestUrl, String requestMethod, String outputStr) {
        try {

            URL url = new URL(requestUrl);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();

            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setUseCaches(false);
// 设置请求方式(GET/POST)
            conn.setRequestMethod(requestMethod);
            conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");
// 当outputStr不为null时向输出流写数据
            if (null != outputStr) {
                OutputStream outputStream = conn.getOutputStream();
// 注意编码格式
                outputStream.write(outputStr.getBytes("UTF-8"));
                outputStream.close();
            }
// 从输入流读取返回内容
            InputStream inputStream = conn.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            String str = null;
            StringBuffer buffer = new StringBuffer();
            while ((str = bufferedReader.readLine()) != null) {
                buffer.append(str);
            }
// 释放资源
            bufferedReader.close();
            inputStreamReader.close();
            inputStream.close();
            inputStream = null;
            conn.disconnect();
            return buffer.toString();
        } catch (ConnectException ce) {
        } catch (Exception e) {
        }
        return null;
    }

    //xml解析
    public static Map doXMLParse(String strxml) throws JDOMException, IOException {
        strxml = strxml.replaceFirst("encoding=".*"", "encoding="UTF-8"");

        if (null == strxml || "".equals(strxml)) {
            return null;
        }

        Map m = new HashMap();

        InputStream in = new ByteArrayInputStream(strxml.getBytes("UTF-8"));
        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;
    }

    /**
     * 循环查找子节点
     *
     * @param children
     * @return
     */
    private 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();
    }
}

 

2,action

package net.jeeshop.web.action.member.pay;

import com.alibaba.fastjson.JSON;
import net.jeeshop.core.AllinpayMain.StringUtils;
import net.jeeshop.core.front.SystemManager;
import net.jeeshop.core.util.PayCommonUtil;
import net.jeeshop.services.front.account.bean.Account;
import net.jeeshop.services.front.order.OrderService;
import net.jeeshop.services.front.order.bean.Order;
import net.jeeshop.services.front.orderpay.OrderpayService;
import net.jeeshop.services.front.orderpay.bean.Orderpay;
import net.jeeshop.web.util.LoginUserHolder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 * Created by Administrator on 2017-02-24.
 */
@Controller("WeiXinPayAction")
@RequestMapping("/member/webchatPay")
public class WeiXinPayAction {

    @Autowired
    private OrderService orderService;
    @Autowired
    private OrderpayService orderpayService;

    public static String wxnotify = "/api/json/money/wxpay/succ";

    @RequestMapping(value = "pay")
    @ResponseBody
    public String pay(HttpServletRequest request) throws Exception {
        HashMap<String, Object> map = new HashMap<String, Object>();
        Account acc = LoginUserHolder.getLoginAccount();
        if (LoginUserHolder.getLoginAccount() == null) {
            map.put("error","用户未登陆");
            return JSON.toJSONString(map);
        }

        String orderId = request.getParameter("orderId");

        // 没有订单ID
        if(StringUtils.isEmpty(orderId)){
            map.put("error","没有订单ID");
            return JSON.toJSONString(map);
        }

        Order order = orderService.selectById(orderId);
        if (order == null) {
            map.put("error","根据订单号查询不到订单信息!");
            return JSON.toJSONString(map);
        }

        // 订单状态不是未支付
        if(Order.order_paystatus_y.equals(order.getPaystatus())){
            map.put("error","订单已经支付!");
            return JSON.toJSONString(map);
        }

        SortedMap<String, String> retMap = new TreeMap<String, String>();
        retMap = PayCommonUtil.pay(orderId, new BigDecimal(order.getPtotal()), order.getRemark(), acc.getOpenId(), request.getRemoteAddr(), SystemManager.getInstance().getSystemSetting().getWww() + "member/webchatPay/success");

        if(!StringUtils.isEmpty(retMap.get("error"))){
            map.put("error",retMap.get("error"));
            return JSON.toJSONString(map);
        }

        return JSON.toJSONString(retMap);
    }

    @RequestMapping(value = "success")
    @ResponseBody
    public String success(HttpServletRequest request) throws Exception {
        InputStream inStream = request.getInputStream();
        ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = inStream.read(buffer)) != -1) {
            outSteam.write(buffer, 0, len);
        }
        String resultXml = new String(outSteam.toByteArray(), "utf-8");
        Map<String, String> params = PayCommonUtil.doXMLParse(resultXml);
        outSteam.close();
        inStream.close();
        if (PayCommonUtil.isTenpaySign(params) && "SUCCESS".equals(params.get("return_code")) && "SUCCESS".equals(params.get("result_code"))) {
            String orderId = params.get("out_trade_no");
            Orderpay orderpay = new Orderpay();
            orderpay.setOrderid(orderId);
            orderpay.setPaystatus(Orderpay.orderpay_paystatus_n);
            orderpay = orderpayService.selectOne(orderpay);

            // 获取订单ID
            Order order = orderService.selectById(orderId);
            if (order == null) {
                return "success";
            }

            // 订单状态不是未支付
            if(Order.order_paystatus_y.equals(order.getPaystatus())){
                return "success";
            }

            // 更新订单状态
            orderService.orderStatus("WAIT_SELLER_SEND_GOODS",orderpay,order);
            return "success";
        } else {
            // 支付失败
            return "fail";
        }
    }
}

  



3,页面JS
<script>
    $(function () {
        $("#btnPay").click(function () {
            if (confirm("确认支付?")) {
                onBridgeReady();
            }
            return false;
        });
    })

    function onBridgeReady(){
        if (typeof(WeixinJSBridge) == "undefined"){
            if( document.addEventListener ){
                document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
            }else if (document.attachEvent){
                document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
                document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
            }
        }

        $.ajax({
            dataType: "json",
            url: "${basepath}/member/webchatPay/pay",
            type: "POST",
            data: {orderId: "${payInfo.WIDout_trade_no!""}"},
            success: function (data) {
                if (data.error != null && data.error != "") {
                    alert(data.error);
                    return;
                }
                else {
                    alert("appId:" + data.appId + ",timeStamp:" + data.timeStamp + ",nonceStr:" + data.nonceStr + ",package:" + data.package + "signType:" + data.signType + ",paySign:" + data.paySign);
                    // 微信支付
                    wxPay(data.appId ,data.timeStamp ,data.nonceStr ,data.package ,data.signType ,data.paySign);
                }
            },
            error: function (data) {
                alert("支付启动错误");
            }
        });
    }

    // 微信支付
    function wxPay(appId,timeStamp,nonceStr,package,signType,paySign){
        WeixinJSBridge.invoke(
            'getBrandWCPayRequest', {
                "appId":appId,     //公众号名称,由商户传入
                "timeStamp":timeStamp,         //时间戳,自1970年以来的秒数
                "nonceStr":nonceStr, //随机串
                "package":package,
                "signType":signType,         //微信签名方式:
                "paySign":paySign //微信签名
            },
            function(res){
                if(res.err_msg == "get_brand_wcpay_request:ok" ) {
                    window.location.href = "${basepath}/member/account/orders";
                }else{
                    alert('支付失败'+res.err_msg);
                }
            }
        );
    }
</script>

  

4,相关配置

  1,微信支付->公众号支付->支付安全目录(注意:如果是ajax调用的话写的是调用的前的页面地址)

  2,公众号设置->功能设置->JS接口安全域名

  3,公众号设置->功能设置->网页授权域名

原文地址:https://www.cnblogs.com/lckblog/p/6442414.html