java实现微信公众号平台JSAPI微信支付

多看看微信支付开发api吧

点我导航去看api,开发流程图看不看都可以咧

支付流程

待写

maven依赖

<dependency>
    <groupId>commons-httpclient</groupId>
    <artifactId>commons-httpclient</artifactId>
    <version>3.1</version>
</dependency>

需要用到的工具类

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ClassPathResource;
import org.xml.sax.InputSource;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.net.ssl.SSLContext;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.net.InetAddress;
import java.security.KeyStore;
import java.security.MessageDigest;
import java.util.*;


/**
 * 微信工具类
 *
 */
public class WChartUtils {

    private static Logger log = LoggerFactory.getLogger(WChartUtils.class);
    //公众账号ID
    public final static String APPID = "aaa";
    //商户号
    public final static String MCHID = "bbb";
    //商户密钥
    public final static String APPSECRET = "ccc";
    //虽然官方文档不是必须参数,但是不送有时候会验签失败
    public final static String MD5 = "MD5";
    //退款需要的证书路径
    public final static String certifi_path = "/data/...";
    //H5支付标记
    public final static String trade_type = "JSAPI";

    //调用统一下单时需要提供得回调接口
    public final static String callback_notify = "http://.../sub/json/notifyOrder";
    
    //获取code接口
    public final static String getCodeUrl = " https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + APPID + "&redirect_uri=http://114.gxtx.163.cn/weixin/login&response_type=code&scope=snsapi_base&state=123#wechat_redirect";

    //获取网页授权登录access_token 接口地址Get
    public final static String OAUTH_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";

    //微信统一下单接口
    public final static String ORDER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder";
    //微信退款接口
    public final static String REFUND_URL = "https://api.mch.weixin.qq.com/secapi/pay/refund";
    //微信查询订单
    public final static String QUERY_ORDER_STATUS = "https://api.mch.weixin.qq.com/pay/orderquery";

    /**
     * 获取openId
     *
     * @param code
     * @return
     * @throws IOException
     */
    public static String getOAuthOpenId(String code) {
        String url = OAUTH_ACCESS_TOKEN_URL.replace("APPID", APPID).replace("SECRET", APPSECRET).replace("CODE", code);
        String result = HttpsUtil.getconnbyget(url);
        JSONObject json = JSONObject.parseObject(result);
        String openId = json.getString("openid");
        if (openId == null) {
            String errorCode = json.getString("errcode");
            String errorMsg = json.getString("errmsg");
            System.out.println(json.toString());
            log.error("获取openid失败:错误代码:" + errorCode + "错误信息:" + errorMsg);
            return null;
        }
        return openId;
    }


    /**
     * Md5 加密工具
     *
     * @param s String   not null
     * @return 加密后的 MD5 值 32位大写的
     */
    public static String md5(String s) {
        char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
        try {
            byte[] btInput = s.getBytes();
            // 获得MD5摘要算法的 MessageDigest 对象
            MessageDigest mdInst = MessageDigest.getInstance("MD5");
            // 使用指定的字节更新摘要
            mdInst.update(btInput);
            // 获得密文
            byte[] md = mdInst.digest();
            // 把密文转换成十六进制的字符串形式
            int j = md.length;
            char str[] = new char[j * 2];
            int k = 0;
            for (int i = 0; i < j; i++) {
                byte byte0 = md[i];
                str[k++] = hexDigits[byte0 >>> 4 & 0xf];
                str[k++] = hexDigits[byte0 & 0xf];
            }
            return new String(str);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 生成 HMACSHA256
     *
     * @param data 待处理数据
     * @param key  密钥
     * @return 加密结果
     * @throws Exception
     */
    public static String HMACSHA256(String data, String key) throws Exception {
        Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
        SecretKeySpec secret_key = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256");
        sha256_HMAC.init(secret_key);
        byte[] array = sha256_HMAC.doFinal(data.getBytes("UTF-8"));
        StringBuilder sb = new StringBuilder();
        for (byte item : array) {
            sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
        }
        return sb.toString().toUpperCase();
    }


    /**
     * 生成签名. 注意,若含有sign_type字段,必须和signType参数保持一致。
     *
     * @param data 待签名数据
     * @return 签名
     */
    public static String generateSignature(Map<String, String> data) throws Exception {
        Set<String> keySet = data.keySet();
        String[] keyArray = keySet.toArray(new String[keySet.size()]);
        Arrays.sort(keyArray);
        StringBuilder sb = new StringBuilder();
        for (String k : keyArray) {
            if ("sign".equals(k)) {
                continue;
            }
            if (data.get(k).trim().length() > 0) // 参数值为空,则不参与签名
                sb.append(k).append("=").append(data.get(k).trim()).append("&");
        }
        sb.append("key=").append(APPSECRET);
        return md5(sb.toString()).toUpperCase();
    }


    /**
     * 生成字母+数字(8位)随机数
     *
     * @param length 长度
     * @return val 转换好的文本
     */
    public static String getStringRandom(int length) {
        String val = "";
        Random random = new Random();
        //length为几位密码
        for (int i = 0; i < length; i++) {
            String charOrNum = random.nextInt(2) % 2 == 0 ? "char" : "num";
            //输出字母还是数字
            if ("char".equalsIgnoreCase(charOrNum)) {
                //输出是大写字母还是小写字母
                int temp = random.nextInt(2) % 2 == 0 ? 65 : 97;
                val += (char) (random.nextInt(26) + temp);
            } else if ("num".equalsIgnoreCase(charOrNum)) {
                val += String.valueOf(random.nextInt(10));
            }
        }
        return val;
    }

    /**
     * 元转换成分
     *
     * @param amount
     * @return
     */
    public static String getMoney(String amount) {
        if (amount == null) {
            return "";
        }
        // 金额转化为分为单位
        String currency = amount.replaceAll("\\$|\\¥|\\,", "");  //处理包含, ¥ 或者$的金额
        int index = currency.indexOf(".");
        int length = currency.length();
        Long amLong = 0l;
        if (index == -1) {
            amLong = Long.valueOf(currency + "00");
        } else if (length - index >= 3) {
            amLong = Long.valueOf((currency.substring(0, index + 3)).replace(".", ""));
        } else if (length - index == 2) {
            amLong = Long.valueOf((currency.substring(0, index + 2)).replace(".", "") + 0);
        } else {
            amLong = Long.valueOf((currency.substring(0, index + 1)).replace(".", "") + "00");
        }
        return amLong.toString();
    }

    /**
     * 请求微信接口
     *
     * @param xmlParam
     * @return
     */
    public static Map getMwebUrl(String url, String xmlParam) {
        String jsonStr = null;
        HttpClient httpClient = new HttpClient();
        Map map = new HashMap<>();
        try {
            PostMethod method = null;
            RequestEntity reqEntity = new StringRequestEntity(xmlParam, "text/json", "UTF-8");
            method = new PostMethod(url);
            method.setRequestEntity(reqEntity);
            method.addRequestHeader("Content-Type", "application/json;charset=utf-8");
            httpClient.executeMethod(method);
            StringBuffer resBodyBuf = new StringBuffer();
            byte[] responseBody = new byte[1024];
            int readCount = 0;
            BufferedInputStream is = new BufferedInputStream(method.getResponseBodyAsStream());
            while ((readCount = is.read(responseBody, 0, responseBody.length)) != -1) {
                resBodyBuf.append(new String(responseBody, 0, readCount, "utf-8"));
            }
            jsonStr = resBodyBuf.toString();
            System.out.println(jsonStr);
            map = parseXmlToList(jsonStr);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return map;
    }


    /**
     * description: 解析微信通知xml
     *
     * @param xml
     * @return
     * @author ex_yangxiaoyi
     * @see
     */
    @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;

    }

    /**
     * 获取用户实际ip
     *
     * @param request
     * @return
     */
    public static String getIpAddr(HttpServletRequest request) {
        String ipAddress = request.getHeader("x-forwarded-for");
        if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("Proxy-Client-IP");
        }
        if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getRemoteAddr();
            if (ipAddress.equals("127.0.0.1") || ipAddress.equals("0:0:0:0:0:0:0:1")) {
                //根据网卡取本机配置的IP
                InetAddress inet = null;
                try {
                    inet = InetAddress.getLocalHost();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                ipAddress = inet.getHostAddress();
            }
        }
        //对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割
        if (ipAddress != null && ipAddress.length() > 15) { //"***.***.***.***".length() = 15
            if (ipAddress.indexOf(",") > 0) {
                ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
            }
        }
        return ipAddress;
    }


    private static int socketTimeout = 10000;// 连接超时时间,默认10秒
    private static int connectTimeout = 30000;// 传输超时时间,默认30秒
    private static RequestConfig requestConfig;// 请求器的配置
    private static CloseableHttpClient httpClient;// HTTP请求器

    /**
     * 通过Https往API post xml数据
     *
     * @param url    API地址
     * @param xmlObj 要提交的XML数据对象
     * @return
     */
    public static String postData(String url, String xmlObj) {
        // 加载证书
        try {
            initCert();
        } catch (Exception e) {
            e.printStackTrace();
        }
        String result = null;
        HttpPost httpPost = new HttpPost(url);
        // 得指明使用UTF-8编码,否则到API服务器XML的中文不能被成功识别
        StringEntity postEntity = new StringEntity(xmlObj, "UTF-8");
        httpPost.addHeader("Content-Type", "text/xml");
        httpPost.setEntity(postEntity);
        // 根据默认超时限制初始化requestConfig
        requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout).build();
        // 设置请求器的配置
        httpPost.setConfig(requestConfig);
        try {
            HttpResponse response = null;
            try {
                response = httpClient.execute(httpPost);
            } catch (IOException e) {
                e.printStackTrace();
            }
            HttpEntity entity = response.getEntity();
            try {
                result = EntityUtils.toString(entity, "UTF-8");
            } catch (IOException e) {
                e.printStackTrace();
            }
        } finally {
            httpPost.abort();
        }
        return result;
    }

    /**
     * 加载证书
     *
     * @throws Exception
     */
    private static void initCert() throws Exception {
        // 证书密码,默认为商户ID
        String key = MCHID;
        // 证书的路径
        // 指定读取证书格式为PKCS12
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        // 读取本机存放的PKCS12证书文件
        ClassPathResource cp = new ClassPathResource(certifi_path);
        InputStream instream = cp.getInputStream();
        try {
            // 指定PKCS12的密码(商户ID)
            keyStore.load(instream, key.toCharArray());
        } finally {
            instream.close();
        }
        SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, key.toCharArray()).build();
        SSLConnectionSocketFactory sslsf =
                new SSLConnectionSocketFactory(sslcontext, new String[]{"TLSv1"}, null,
                        SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
        httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
    }


    /**
     * 确认保存订单(未支付状态)
     * 需要:
     *
     * @return
     */
    @SuppressWarnings({"rawtypes", "unused"})
    @RequestMapping(value = "/saveOrder1.0", method = RequestMethod.POST)
    @ResponseBody
    public Map saveOrder(HttpServletRequest request, HttpServletResponse response, @RequestBody OrOrderInfo orOrderInfo) {
        if (。。。) {
            return R.error(40002, "msg", "参数错误!");
        }
        Map<String, Object> result = new HashMap<>();
       
        orOrderInfo.setUserId(one.getId());
        Random random = new Random();
        int rannum = (int) (random.nextDouble() * (99999 - 10000 + 1)) + 10000;
        //生成系统订单号
        orOrderInfo.setOrderNum(DateParse.format(new Date(), "yyyyMMddHHmmss") + rannum);
        
        //请求预付款统一下单接口
        Map map = weixinPayWap(request, response, orOrderInfo);
        if (Integer.valueOf(map.get("code") + "") == 200) {
            boolean save = orOrderInfoService.save(orOrderInfo);
            if (save) {
                Map data = (Map) map.get("data");
                data.put("orderId", orOrderInfo.getId());
                return R.success(null, "data", data);
            }
            return R.error(null, null, null);
        } else {
            return map;
        }
    }

    /**
     * 因为前端支付后返回的通知支付成功不保证不被修改过,所以要请求自己系统后台确认,根据订单id确认支付是否真的成功
     *
     * @return
     */
    @SuppressWarnings({"unchecked", "rawtypes", "unused"})
    @RequestMapping(value = "/queryByOrderIdSuccess1.0", method = RequestMethod.POST)
    @ResponseBody
    public Map queryByOrderIdSuccess1(HttpServletRequest request, @RequestBody Map mapEntity) throws Exception {
        Integer orderId = Integer.valueOf("" + mapEntity.get("orderId"));
        if (orderId == null) {
            return R.error(40002, "msg", "orderId订单id为空");
        }
        OrOrderInfo entity = orOrderInfoService.getById(orderId);
        if (entity == null) {
            return R.error(null, "msg", "orderId订单id无效");
        }
        if ("1".equals(entity.getOrderStatus())) {
            return R.success(null, "status", true);//支付成功
        }
        //还是未支付状态,有可能是微信支付系统调取我们的回调地址通知我们有一定的延迟,所以我们要主动向微信支付系统查询该订单是否已经支付成功
        if ("0".equals(entity.getOrderStatus())) {
            //请求查询订单
            //随机数
            String nonce_str = WChartUtils.getStringRandom(16);
            Map<String, String> parMap = new HashMap<>();
            parMap.put("appid", WChartUtils.APPID);//公众账号ID
            parMap.put("mch_id", WChartUtils.MCHID);//商户号
            //parMap.put("transaction_id", entity.getTransactionId());
            parMap.put("out_trade_no", entity.getOrderNum());//订单号
            parMap.put("nonce_str", nonce_str);
            //签名MD5加密并转化为大写
            String sign = WChartUtils.generateSignature(parMap);
            System.out.println("签名数据sign======" + sign);
            //封装xml报文
            String xml = "" +
                    "" + WChartUtils.APPID + "" +
                    "" + WChartUtils.MCHID + "" +
                    "" + nonce_str + "" +
                    "" + entity.getOrderNum() + "" +
                    "" + sign + "" +
                    "";
            Map map = WChartUtils.getMwebUrl(WChartUtils.QUERY_ORDER_STATUS, xml);//查询订单
            String return_code = (String) map.get("return_code");
            String result_code = (String) map.get("result_code");
            String return_msg = (String) map.get("return_msg");
            String trade_state = (String) map.get("trade_state");
            if ("SUCCESS".equals(return_code) && "SUCCESS".equals(result_code)) {
                String newWxsign = (String) map.get("sign");
                map.remove("sign");
                String wxSign = WChartUtils.generateSignature(map);
                //签名验证
                if (wxSign.equals(newWxsign)) {
                    if ("SUCCESS".equals(trade_state)) {
                        entity.setOrderStatus("1");
                        orOrderInfoService.updateById(entity);
                        return R.success(null, "status", true);//支付成功
                    } else {
                        return R.success(null, "status", false);//支付失败
                    }
                }
            }
        }
        return R.success(null, "status", false);
    }

    /**
     * 若下单未支付,重新调起支付界面。根据订单id获取需要重新调取的支付参数
     *
     * @return
     */
    @SuppressWarnings({"unchecked", "rawtypes", "unused"})
    @RequestMapping(value = "/queryByOrderIdRefund1.0", method = RequestMethod.POST)
    @ResponseBody
    public Map queryByOrderIdRefund(HttpServletRequest request, @RequestBody Map mapEntity) throws Exception {
        Integer orderId = Integer.valueOf("" + mapEntity.get("orderId"));
        if (orderId == null) {
            return R.error(40002, "msg", "orderId订单id为空");
        }
        OrOrderInfo entity = orOrderInfoService.getById(orderId);
        if (entity == null || !"0".equals(entity.getOrderStatus())) {
            return R.error(null, "msg", "orderId订单id无效");
        }
        //判断支付失效时间
        if (new Date().after(entity.getExpireDate())) {
            return R.error(40005, "msg", "预支付时间已过期");
        }
        Map<String, Object> result = new HashMap<>();
        String new_nonce_str = WChartUtils.getStringRandom(16);
        String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
        Map<String, String> newParMap = new HashMap<>();
        //前端调起支付界面需要的参数
        newParMap.put("appId", WChartUtils.APPID);//公众账号ID
        newParMap.put("timeStamp", timestamp);//时间戳
        newParMap.put("nonceStr", new_nonce_str);//随机字符串
        newParMap.put("package", "prepay_id=" + entity.getPrepayId());//预付款id
        newParMap.put("signType", WChartUtils.MD5);//签名类型
        //签名MD5加密并转化为大写
        String paySign = WChartUtils.generateSignature(newParMap);
        System.out.println("签名数据paySign======" + paySign);
        result.put("appId", WChartUtils.APPID);//预支付id
        result.put("timestamp", timestamp);//时间戳
        result.put("nonceStr", new_nonce_str);//随机字符串
        result.put("package", "prepay_id=" + entity.getPrepayId());//预支付id
        result.put("signType", WChartUtils.MD5);//签名类型
        result.put("paySign", paySign);//签名
        return R.success(null, "data", result);
    }


    /**
     * 预支付下单接口
     *
     * @param request
     * @param response
     * @param orOrderInfo
     * @return
     */

    public Map weixinPayWap(HttpServletRequest request, HttpServletResponse response, OrOrderInfo orOrderInfo) {
        WxUser user = (WxUser) request.getAttribute("currentUser");
        String openid = user.getOpenId();
        String spbill_create_ip = WChartUtils.getIpAddr(request);//生产环境ip
        System.out.println("spbill_create_ip=" + spbill_create_ip);
        String subject = "test下单";//前端上送的支付主题
        String finalmoney = WChartUtils.getMoney(orOrderInfo.getAmount().toString()); //金额转化为分为单位 微信支付以分为单位
        String out_trade_no = orOrderInfo.getOrderNum();//订单号
        //随机数
        String nonce_str = WChartUtils.getStringRandom(16);
        //签名数据
        String prepay_id = "";
        Map map = new HashMap();
        Map<String, Object> result = new HashMap<>();
        try {
            Map<String, String> parMap = new HashMap<>();
            parMap.put("appid", WChartUtils.APPID);//公众账号ID
            parMap.put("body", subject);//商品描述
            parMap.put("mch_id", WChartUtils.MCHID);//商户号
            parMap.put("nonce_str", nonce_str);//随机字符串
            parMap.put("notify_url", WChartUtils.callback_notify);//通知地址,用于前端调取支付成功后,微信支付系统通过调取该地址,将信息传给我们是否支付成功
            parMap.put("openid", openid);
            parMap.put("out_trade_no", out_trade_no);//商户订单号===系统订单号
            parMap.put("spbill_create_ip", spbill_create_ip);//终端IP
            parMap.put("total_fee", finalmoney);//订单总金额,单位为分
            parMap.put("trade_type", WChartUtils.trade_type);//交易类型
            //签名MD5加密并转化为大写
            String sign = WChartUtils.generateSignature(parMap);
            System.out.println("签名数据sign======" + sign);
            //统一下单二次加密

            //封装xml报文
            String xml = "" +
                    "" + WChartUtils.APPID + "" +
                    "" + WChartUtils.MCHID + "" +
                    "" + nonce_str + "" +
                    "" + sign + "" +
                    "" + subject + "" +//
"" + out_trade_no + "" +
"" + finalmoney + "" +//
"" + WChartUtils.trade_type + "" +
"" + WChartUtils.callback_notify + "" +
"" + openid + "" +
"" + spbill_create_ip + "" +
"";
/*返回格式










*/
map = WChartUtils.getMwebUrl(WChartUtils.ORDER_URL, xml);//调用下单统计支付接口
String return_code = (String) map.get("return_code");
String result_code = (String) map.get("result_code");
String return_msg = (String) map.get("return_msg");
if ("SUCCESS".equals(return_code) && "SUCCESS".equals(result_code)) {
/* Map signMap = new HashMap<>();
signMap.put("appid", (String) map.get("appid"));
signMap.put("mch_id", (String) map.get("mch_id"));
signMap.put("nonce_str", (String) map.get("nonce_str"));
signMap.put("prepay_id", (String) map.get("prepay_id"));
signMap.put("trade_type", (String) map.get("trade_type"));
String wxSign = WChartUtils.generateSignature(signMap);*/
String newWxsign = (String) map.get("sign");
map.remove("sign");
//将微信传回的参数排除签名参数后,生成新的签名,用来和参数签名进行比较
String wxSign = WChartUtils.generateSignature(map);
//验证微信返回的签名,和手动生成的签名是否相等
if (wxSign.equals(newWxsign)) {
prepay_id = (String) map.get("prepay_id");//预支付交易会话标识
//生成随机字符串
//随机数
String new_nonce_str = WChartUtils.getStringRandom(16);
String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
Map<String, String> newParMap = new HashMap<>();
newParMap.put("appId", WChartUtils.APPID);//公众账号ID
newParMap.put("timeStamp", timestamp);//时间戳
newParMap.put("nonceStr", new_nonce_str);//随机字符串
newParMap.put("package", "prepay_id=" + prepay_id);//预付款id
newParMap.put("signType", WChartUtils.MD5);//签名类型
//签名MD5加密并转化为大写
String paySign = WChartUtils.generateSignature(newParMap);
System.out.println("签名数据paySign======" + paySign);
//前端需要的参数用来调取支付界面
result.put("appId", WChartUtils.APPID);
result.put("timestamp", timestamp);//时间戳
result.put("nonceStr", new_nonce_str);//随机字符串
result.put("package", "prepay_id=" + prepay_id);//预支付id
result.put("signType", WChartUtils.MD5);//签名类型
result.put("paySign", paySign);//签名
orOrderInfo.setPrepayId(prepay_id);
Date expireDate = new Date();
expireDate.setTime(expireDate.getTime() + (2L * 60L * 60L * 1000L));
orOrderInfo.setExpireDate(expireDate);
System.out.println("prepay_id=" + prepay_id);
} else {
System.out.println("sign验证签名无效==生成的:" + wxSign);
System.out.println("sign验证签名无效==微信返回的:" + newWxsign);
return R.error(40001, "msg", "返回sign验证签名无效");
}
} else {
System.out.println("统一支付接口获取预支付订单出错:" + return_msg);
return R.error(40001, "msg", "统一支付接口获取预支付订单出错");
}
} catch (Exception e) {
System.out.println("统一支付接口获取预支付订单出错");
return R.error(40001, "msg", "统一支付接口获取预支付订单出错");
}
result.put("orderNum", out_trade_no);//订单号;
//添加微信支付记录日志等操作
return R.success(null, "data", result);
}
/**
* 回调接口,微信支付系统通过调用该接口,将支付是否成功信息告诉我们
*
* @param request
* @param response
* @throws Exception
*/
@RequestMapping(value = "/notifyOrder")
public void weixinPayNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
BufferedReader reader = request.getReader();
String line = "";
Map map = new HashMap();
String xml = "";
JSONObject dataInfo = new JSONObject();
StringBuffer inputString = new StringBuffer();
while ((line = reader.readLine()) != null) {
inputString.append(line);
}
request.getReader().close();
System.out.println("----接收到的报文---" + inputString.toString());
if (inputString.toString().length() > 0) {
map = WChartUtils.parseXmlToList(inputString.toString());
} else {
System.out.println("接受微信报文为空");
}
System.out.println("map=" + map);
if (map != null && "SUCCESS".equals(map.get("result_code")) && StringUtils.isNotBlank((String) map.get("sign"))) {
//成功的业务。。。
xml = "";
String total_fee = (String) map.get("total_fee");//支付金额
//double v = Double.valueOf(total_fee) / 100;
//订单号
String out_trade_no = String.valueOf(Long.parseLong(map.get("out_trade_no").toString().split("O")[0]));
//String totalAmount = String.valueOf(v);//具体支付金额
String appId = (String) map.get("appid");
System.out.println("订单号out_trade_no:" + out_trade_no);
String signFromWechat = (String) map.get("sign");
//清除掉返回数据中的sign数据,因为sign本身是不参与签名的
map.remove("sign");
String newSign = WChartUtils.generateSignature(map);
//验证签名,是否被修改过
if (signFromWechat.equals(newSign)) {
//根据订单号修改订单状态
if (WChartUtils.APPID.equals(appId)) {
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.eq("order_num", out_trade_no);
OrOrderInfo entity = orOrderInfoService.getOne(queryWrapper);
if (entity != null && "0".equals(entity.getOrderStatus())) {
String finalmoney = WChartUtils.getMoney(entity.getAmount().toString()); //金额转化为分为单位 微信支付以分为单位
if (finalmoney.equals(total_fee)) {
entity.setOrderStatus("1");
entity.setTransactionId((String) map.get("transaction_id"));
entity.setPayTime(DateParse.parse((String) map.get("time_end"), "yyyyMMddHHmmss"));
orOrderInfoService.updateById(entity);
} else {
xml = "";
}
}
}
} else {
//失败
xml = "";
}
} else {
//失败
xml = "";
}
System.out.println(xml);
//告诉微信端已经确认支付成功或者支付失败
response.getWriter().write(xml);
}

你可能感兴趣的:(java,微信支付)