1、引入依赖:(对于依赖冲突自行解决)

<dependency>
            <groupId>com.github.binarywang</groupId>
            <artifactId>weixin-java-pay</artifactId>
            <!--<version>3.4.9.B</version>-->
            <version>3.5.0</version>
            <exclusions>
                <exclusion>
                    <artifactId>httpclient</artifactId>
                    <groupId>org.apache.httpcomponents</groupId>
                </exclusion>
                <exclusion>
                    <artifactId>commons-lang3</artifactId>
                    <groupId>org.apache.commons</groupId>
                </exclusion>
                <exclusion>
                    <artifactId>commons-beanutils</artifactId>
                    <groupId>commons-beanutils</groupId>
                </exclusion>
                <exclusion>
                    <artifactId>guava</artifactId>
                    <groupId>com.google.guava</groupId>
                </exclusion>
            </exclusions>
        </dependency>

2、

package com.dhht.wechat.controller;

import com.dhht.wechat.VO.PayVO;
import com.dhht.wechat.service.PayService;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

/*
 * @Author: sh
 * @Description: WxPayController
 * @Date: 11:06 2019/7/17
 */

@RestController
@RequestMapping("wechat/")
public class WxPayController {

    @Resource
    private PayService payService;


    /**
     * 微信支付统一下单接口(H5)
     * @param payVO
     * @param request
     * @return
     */
    @PostMapping(value = "pay",produces = "application/json;charset=UTF-8")
    public String unifiedOrder(@RequestBody PayVO payVO, HttpServletRequest request){
        return payService.unifiedOrder(payVO,request);
    }


    /**
     * 微信支付接收通知接口(供微信服务调用)
     * @param xmlData
     * @return
     */
    @PostMapping(value = "pay/notify",produces = "application/json;charset=UTF-8")
    public synchronized String payNotify(@RequestBody String xmlData){

        return payService.payNotifyCallBack(xmlData);
    }


    /**
     * 退款结果通知接口
     * @param xmlData
     * @return
     */
    @PostMapping("/notify/refund")
    public synchronized String parseRefundNotifyResult(@RequestBody String xmlData) {
        return payService.parseRefundNotifyResult(xmlData);
    }


}
package com.dhht.wechat.service;

import com.alibaba.fastjson.JSON;
import com.dhht.wechat.VO.PayVO;
import com.dhht.wechat.service.impservice.OrderRefundResultImplService;
import com.dhht.wechat.service.impservice.SealOrderImplService;
import com.dhht.wechat.service.impservice.SealOrderSealImplService;
import com.dhht.wechat.util.ConstantUtil;
import com.dhht.wechat.util.DateUtil;
import com.dhht.wechat.wxpay.MyX509TrustManager;
import com.dhht.wechat.wxpay.PayRespCodeMsg;
import com.dhht.wechat.wxpay.PayResultVO;
import com.dhht.wechat.wxpay.WechatPayConfigBean;
import com.dhht.wechat.wxpay.config.WxPayProperties;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import com.github.binarywang.wxpay.bean.request.*;
import com.github.binarywang.wxpay.bean.result.WxPayOrderCloseResult;
import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryResult;
import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
import com.github.binarywang.wxpay.service.WxPayService;
import net.sf.json.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.math.BigDecimal;
import java.net.ConnectException;
import java.net.URL;
import java.security.MessageDigest;
import java.text.MessageFormat;
import java.util.*;

/**
 * WxPayService
 */
@Service
public class PayService {

    @Resource
    private WechatPayConfigBean wechatPayConfigBean;

    @Resource
    private WxPayProperties wxPayProperties;// 第三方

    @Resource
    private SealOrderImplService sealOrderImplService;

    @Resource
    private WxPayService wxService;// 第三方sdk

//    @Resource
//    private OrderPayResultImplService orderPayResultImplService;

    @Resource
    private OrderRefundResultImplService orderRefundResultImplService;

    @Value("${spbill_create_ip}")
    private String SPBILL_CREATE_IP;

    @Value("${appSecret}")
    private String appSecret;

    @Resource
    WeiXinService weiXinService;

    @Resource
    SealOrderSealImplService sealOrderSealImplService;

    /**
     * 微信支付统一下单接口(H5)
     *
     * @param payVO
     * @param request
     * @return
     */
    public String unifiedOrder(PayVO payVO, HttpServletRequest request) {
        try {

            String orderId = payVO.getOrderId();
            String code = payVO.getCode();
            if (StringUtils.isEmpty(orderId) || StringUtils.isEmpty(code)) {
                PayResultVO payResultVO = new PayResultVO(-1, "NO", null);
                return JSON.toJSONString(payResultVO);
            }

            WxPayOrderQueryResult payOrderQueryResult = wechatOrderQuery(orderId);// wxService.queryOrder(null, orderId);// 查询订单状态
            String payOrderQuery_return_code = payOrderQueryResult.getReturnCode();// SUCCESS/FAIL
            if (ConstantUtil.PAY_RETURN_CODE_NO.equals(payOrderQuery_return_code)) {// 通信失败:FAIL
                PayResultVO queryPayResultVO = new PayResultVO(-1, payOrderQueryResult.getReturnMsg(), null);
                return JSON.toJSONString(queryPayResultVO);// 订单查询接口通信失败,直接返回
            }

            // 订单查询通信成功:SUCCESS

            // 若业务成功

            /**
             * trade_state状态如下:
             * SUCCESS—支付成功
             * REFUND—转入退款
             * NOTPAY—未支付
             * CLOSED—已关闭
             * REVOKED—已撤销(刷卡支付)
             * USERPAYING--用户支付中
             * PAYERROR--支付失败(其他原因,如银行返回失败)商户订单支付失败需要生成新单号重新发起支付,要对原订单号调用关单,避免重复支付
             */
            String trade_state = payOrderQueryResult.getTradeState();
            if (!ConstantUtil.PAY_TRADE_STATE_NOTPAY.equals(trade_state) && null != trade_state) {// 非未支付状态下(可以为null-代表还未生成订单,故需过滤掉)
                PayResultVO tradePayResultVO = new PayResultVO(-1, ConstantUtil.PAY_STATUS_MAP.get(trade_state), null);
                return JSON.toJSONString(tradePayResultVO);
            }
            // 以下转入订单未支付处理或还没有生成订单(trade_state==null)的处理逻辑

            //String openUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid="+wxPayProperties.getAppId()+"&secret="+appSecret+"&code="+code+"&grant_type=authorization_code";
            String openId = weiXinService.getOpenId(code);//SendMsgUtil.httpRequest(openUrl,"GET","{}").getString("openid");// 获取openid
            // 更新订单openId--2019-09-17
            Map<String, Object> paMap = new HashMap<>();
            paMap.put("orderId", orderId);
            paMap.put("userOpenId", openId);
            sealOrderImplService.updateOrderInfo(paMap);
            // 获取本系统印章订单信息
            Map<String, Object> orderDetails = sealOrderImplService.getOrderMapById(orderId);
            String SUB_MCH_ID = (String) orderDetails.get("SUB_MCH_ID");// 营业网点扩展信息表中的子商户号-20190910
            if (StringUtils.isEmpty(SUB_MCH_ID)) {// 若无配置子商户号退出
                PayResultVO payResultVO = new PayResultVO(-1, "NO-SUB_MCH_ID", null);
                return JSON.toJSONString(payResultVO);
            }
            String siteName = (String) orderDetails.get("siteName");// 营业网点名称(刻章店名称)
            float orderPrice = ((BigDecimal) orderDetails.get("ORDER_AMOUNT")).floatValue();// 订单总金额
            String bodyName = siteName + "-" + ConstantUtil.ADVANCE_PAY_GOODS_NAME;// 商品名称严格按照规范-公众号支付-例如(商家名称-销售商品类目)
            // 设置统一下单请求参数
            // 请求对象,注意一些参数如appid、mchid等不用设置,方法内会自动从配置对象中获取到(前提是对应配置中已经设置)
            WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
            orderRequest.setAppid(wxPayProperties.getAppId());// 服务商appid
            orderRequest.setMchId(wxPayProperties.getMchId());// 商户号
            orderRequest.setSubMchId(SUB_MCH_ID);// 子商户号
            String nonceStr = DateUtil.get32UUIDMilli();
            orderRequest.setNonceStr(nonceStr);// 随机串,32位以内!
            orderRequest.setSignType(wxPayProperties.getSignType());// 签名类型
            orderRequest.setBody(bodyName);
            orderRequest.setOutTradeNo(orderId);
            orderRequest.setTotalFee(BaseWxPayRequest.yuanToFen(orderPrice + ""/*order.getTotalFee()*/));//元转成分
            orderRequest.setSpbillCreateIp(SPBILL_CREATE_IP);// 终端IP
            orderRequest.setNotifyUrl(wxPayProperties.getNotifyUrl());// 支付结果异步回调地址
            orderRequest.setTradeType(wxPayProperties.getTradeType());// 交易类型
            orderRequest.setOpenid(openId);// 设置openid
            WxPayMpOrderResult wxPayUnifiedOrderResult = wxService.createOrder(orderRequest);// 统一下单接口调用结果

            String appId = wxPayUnifiedOrderResult.getAppId();
            String timeStamp = create_timestamp();
            String package_ = wxPayUnifiedOrderResult.getPackageValue();// ConstantUtil.PACKAGE_SUFFIX + wxPayUnifiedOrderResult.getPackageValue();
            String paySign = wxPayUnifiedOrderResult.getPaySign();
            Map<String, Object> resultMapData = new HashMap<>();
            resultMapData.put("appId", appId);
            resultMapData.put("timeStamp", timeStamp);
            resultMapData.put("package", package_);
            resultMapData.put("paySign", paySign);
            resultMapData.put("nonceStr", wxPayUnifiedOrderResult.getNonceStr());
            resultMapData.put("signType", wxPayProperties.getSignType());
            PayResultVO paySucessResultVO = new PayResultVO(0, "OK", resultMapData);
            return JSON.toJSONString(paySucessResultVO);
        } catch (Exception e) {
            Map map = new HashMap();
            map.put("data", e.getMessage());
            PayResultVO payResultVO = new PayResultVO(-1, "NO", map);
            return JSON.toJSONString(payResultVO);
        }
    }

    /**
     * 支付回调
     *
     * @param xmlData
     * @return
     */
    public synchronized String payNotifyCallBack(String xmlData) {
        try {

            WxPayOrderNotifyResult wxPayOrderNotifyResult = wxService.parseOrderNotifyResult(xmlData);// 解析xml字符串
            String return_code = wxPayOrderNotifyResult.getReturnCode();// SUCCESS/FAIL

            if (ConstantUtil.PAY_RETURN_CODE_NO.equals(return_code)) {// 支付通信失败
                return WxPayNotifyResponse.fail("FAIL");
            }
            // 以下通信成功操作
            String out_trade_no = wxPayOrderNotifyResult.getOutTradeNo();// 商户系统内部订单号(即本系统印章订单号)
            // 内部订单支付情况
            Map<String, Object> orderDetails = sealOrderImplService.getOrderMapById(out_trade_no);
            if (null != orderDetails) {
                String paySta = (Integer) orderDetails.get("PAY_STATUS") + "";
                if ((ConstantUtil.ORDER_PAYSTATUS_1_ + "").equals(paySta)) {// 已支付直接返回
                    return WxPayNotifyResponse.success("OK");
                }
            }

            if (ConstantUtil.PAY_RETURN_CODE_OK.equals(return_code)) {// 支付接口通信成功
                String result_code = wxPayOrderNotifyResult.getResultCode();// SUCCESS/FAIL 是否真实支付成功

                if (ConstantUtil.PAY_RETURN_CODE_OK.equals(result_code)) {// 支付成功
                    // 检查本库是否已经插入支付成功记录
                    // orderPayResultImplService.deleteByOrderId(out_trade_no);
                    //orderPayResultImplService.add(wxPayOrderNotifyResult);
                    //orderPayResultImplService.insertSelective(wxPayOrderNotifyResult);
                    sealOrderImplService.updateOrderPaySta(out_trade_no, ConstantUtil.ORDER_PAYSTATUS_1_);// 更新支付状态
                    // 推送微信内容-2019-09-18
                    sealOrderSealImplService.sendWXMsgToSite(out_trade_no);

                }
                if (ConstantUtil.PAY_RETURN_CODE_NO.equals(result_code)) {// 支付失败
                    closePayOrder(out_trade_no);// 支付失败的话,需要关闭订单,才能重新支付
                    sealOrderImplService.upOrderRelation(out_trade_no);// 更新该订单的id,主要用于重新支付
                    sealOrderImplService.updateOrderPaySta(out_trade_no, ConstantUtil.ORDER_PAYSTATUS_2_);// 更新支付状态
                }
                return WxPayNotifyResponse.success("OK");
            } else {// 支付结果通信失败
                return WxPayNotifyResponse.fail("FAIL");
            }

        } catch (Exception e) {
            return WxPayNotifyResponse.fail("FAIL");
        }
    }

    /**
     * 查询订单状态
     *
     * @param orderId
     * @return
     */
    public WxPayOrderQueryResult wechatOrderQuery(String orderId) {
        try {
            if (StringUtils.isEmpty(orderId)) {
                return null;
            }
            Map<String, Object> orderDetails = sealOrderImplService.getOrderMapById(orderId);// 获取本系统订单的相关信息
            String SUB_MCH_ID = (String) orderDetails.get("SUB_MCH_ID");// 营业网点扩展信息表中的子商户号-20190910
            WxPayOrderQueryRequest wxPayOrderQueryRequest = new WxPayOrderQueryRequest();
            wxPayOrderQueryRequest.setAppid(wxPayProperties.getAppId());
            wxPayOrderQueryRequest.setMchId(wxPayProperties.getMchId());
            wxPayOrderQueryRequest.setSubMchId(SUB_MCH_ID);// 子商户好最终通过orderId从本系统获取
            wxPayOrderQueryRequest.setOutTradeNo(orderId);// 微信内部订单号与本系统订单号二选一
            wxPayOrderQueryRequest.setNonceStr(DateUtil.get32UUIDMilli());
            wxPayOrderQueryRequest.setSignType(wxPayProperties.getSignType());
            WxPayOrderQueryResult wxPayOrderQueryResult = wxService.queryOrder(wxPayOrderQueryRequest);
            return wxPayOrderQueryResult;
        } catch (Exception e) {
            WxPayOrderQueryResult wxPayOrderQueryResult = new WxPayOrderQueryResult();
            wxPayOrderQueryResult.setReturnCode(ConstantUtil.PAY_RETURN_CODE_OK);
            wxPayOrderQueryResult.setResultCode(ConstantUtil.PAY_RETURN_CODE_OK);
            wxPayOrderQueryResult.setTradeState(null);
            return wxPayOrderQueryResult;
        }
    }

    /**
     * 关闭订单(关闭订单之后,重新提交支付需要更新订单号!)
     *
     * @param orderId
     * @return
     */
    public WxPayOrderCloseResult closePayOrder(String orderId) {
        if (StringUtils.isEmpty(orderId)) {
            return null;
        }
        try {
            Map<String, Object> orderDetails = sealOrderImplService.getOrderMapById(orderId);// 获取本系统订单的相关信息
            String SUB_MCH_ID = (String) orderDetails.get("SUB_MCH_ID");// 营业网点扩展信息表中的子商户号-20190910
            WxPayOrderCloseRequest wxPayOrderCloseRequest = new WxPayOrderCloseRequest();
            wxPayOrderCloseRequest.setAppid(wxPayProperties.getAppId());
            wxPayOrderCloseRequest.setMchId(wxPayProperties.getMchId());
            wxPayOrderCloseRequest.setSubMchId(SUB_MCH_ID);// 从本系统获取通过orderDetails
            wxPayOrderCloseRequest.setOutTradeNo(orderId);
            wxPayOrderCloseRequest.setNonceStr(DateUtil.get32UUIDMilli());
            wxPayOrderCloseRequest.setSignType(wxPayProperties.getSignType());
            WxPayOrderCloseResult wxPayOrderCloseResult = wxService.closeOrder(wxPayOrderCloseRequest);
            return wxPayOrderCloseResult;
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 订单退款(接口请求并非退款结果)
     *
     * @param orderId
     * @return
     */
    public PayResultVO refundPayOrder(String orderId) {
        try {
            if (StringUtils.isEmpty(orderId)) {
                return null;
            }
            Map<String, Object> orderDetails = sealOrderImplService.getOrderMapById(orderId);// 获取本系统订单的相关信息

            // 查询微信支付订单信息
            WxPayOrderQueryResult wxPayOrderQueryResult = wechatOrderQuery(orderId);
            String order_return_code = wxPayOrderQueryResult.getReturnCode();// 订单查询网络状态
            if (ConstantUtil.PREPAYID_RETURN_CODE_NO.equals(order_return_code)) {
                PayResultVO returnPayResultVO = new PayResultVO(-1, ConstantUtil.PAY_NETWORK_EXCEP, null);
                return returnPayResultVO;
            }
            String order_result_code = wxPayOrderQueryResult.getResultCode();// 订单查询业务状态
            if (ConstantUtil.PREPAYID_RETURN_CODE_NO.equals(order_result_code)) {
                PayResultVO resultPayResultVO = new PayResultVO(-1, ConstantUtil.REFUND_FAIL_MSG, null);
                return resultPayResultVO;
            }
            String order_trade_state = wxPayOrderQueryResult.getTradeState();// 订单状态(已支付、未支付等等)
            if (!ConstantUtil.PAY_TRADE_STATE_SUCCESS.equals(order_trade_state)) {// 未支付成功,直接返回
                PayResultVO tradePayResultVO = new PayResultVO(-1, ConstantUtil.REFUND_FAIL_MSG, null);
            }
            // 以下为订单已支付后续操作(只有order_trade_state为SUCCESS可获取如下参数)
            String transaction_id = wxPayOrderQueryResult.getTransactionId();// 微信内部支付订单号
            int total_fee = wxPayOrderQueryResult.getTotalFee();// 订单总金额
            String sub_mch_id = wxPayOrderQueryResult.getSubMchId();// 订单子商户号
            String out_trade_no = wxPayOrderQueryResult.getOutTradeNo();

            WxPayRefundRequest wxPayRefundRequest = new WxPayRefundRequest();
            wxPayRefundRequest.setAppid(wxPayProperties.getAppId());
            wxPayRefundRequest.setMchId(wxPayProperties.getMchId());
            wxPayRefundRequest.setSubMchId(sub_mch_id);// 从本系统通过orderId获取
            wxPayRefundRequest.setNonceStr(DateUtil.get32UUIDMilli());
            wxPayRefundRequest.setSignType(wxPayProperties.getSignType());
            wxPayRefundRequest.setTransactionId(transaction_id);
            wxPayRefundRequest.setOutTradeNo(out_trade_no);// 商户内部订单号
            String refundNo = DateUtil.get32UUIDMilli();// 生成商户内部退款单号
            wxPayRefundRequest.setOutRefundNo(refundNo);// 商户内部退款单号!!!
            wxPayRefundRequest.setTotalFee(total_fee);
            wxPayRefundRequest.setRefundFee(total_fee);// !!!申请退款金额????
            wxPayRefundRequest.setNotifyUrl(wxPayProperties.getRefundNotifyUrl());// 退款结果通知url
            WxPayRefundResult wxPayRefundResult = wxService.refund(wxPayRefundRequest);// 订单退款接口
            String refund_return_code = wxPayRefundResult.getReturnCode();// 退款接口网络状态
            if (ConstantUtil.PREPAYID_RETURN_CODE_NO.equals(refund_return_code)) {
                PayResultVO refundExPayVO = new PayResultVO(-1, ConstantUtil.REFUND_FAIL_MSG, null);
                return refundExPayVO;
            }
            String refund_result_code = wxPayRefundResult.getResultCode();// 退款接口结果状态
            if (ConstantUtil.PREPAYID_RETURN_CODE_NO.equals(refund_result_code)) {
                PayResultVO refundFailPayVO = new PayResultVO(-1, ConstantUtil.REFUND_FAIL_MSG, null);
                return refundFailPayVO;
            }

            // 以下为退款成功操作
            PayResultVO refundSuceesResultVO = new PayResultVO(0, "OK", wxPayRefundResult);
            Map<String, Object> paramMap = new HashMap<>();
            paramMap.put("refundNo", refundNo);// 内部退款单号
            sealOrderImplService.updateOrderInfo(paramMap);
            return refundSuceesResultVO;
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 退款回调通知地址
     *
     * @param xmlData
     * @return
     */
    public synchronized String parseRefundNotifyResult(String xmlData) {
        try {
            WxPayRefundNotifyResult result = wxService.parseRefundNotifyResult(xmlData);
            String return_code = result.getReturnCode();
            if (ConstantUtil.PREPAYID_RETURN_CODE_NO.equals(return_code)) {// 通信失败
                return WxPayNotifyResponse.fail("FAIL");
            }
            // 以下为通信成功返回的字段信息
            WxPayRefundNotifyResult.ReqInfo reqInfo = result.getReqInfo();// 获取结果中的加密信息

            /**
             * SUCCESS-退款成功
             * CHANGE-退款异常
             * REFUNDCLOSE—退款关闭
             */
            String refund_status = reqInfo.getRefundStatus();// 退款状态

            if (ConstantUtil.REFUND_STATUS_0.equals(refund_status)) {// 成功
                refund_status = ConstantUtil.ORDER_PAYSTATUS_3_ + "";
            }
            if (ConstantUtil.REFUND_STATUS_1.equals(refund_status)) {// 异常
                refund_status = ConstantUtil.ORDER_PAYSTATUS_4_ + "";
            }
            if (ConstantUtil.REFUND_STATUS_2.equals(refund_status)) {// 关闭
                refund_status = ConstantUtil.ORDER_PAYSTATUS_4_ + "";
            }
            String out_trade_no = reqInfo.getOutTradeNo();// 内部订单号
            Map<String, Object> paramMap = new HashMap<>();
            paramMap.put("refundNo", out_trade_no);// 内部退款单号
            paramMap.put("payStatus", refund_status);// 更新支付状态
            sealOrderImplService.updateOrderInfo(paramMap);
            orderRefundResultImplService.deleteByOrderdId(out_trade_no);// 删除订单
            orderRefundResultImplService.addRefundInfo(result);// 添加退款 记录
            return WxPayNotifyResponse.success("OK");
        } catch (Exception e) {
            return WxPayNotifyResponse.fail("FAIL");
        }
    }

    //******************************************************************************************************************

    /**
     * 获取微信签名信息(预支付订单信息)
     *
     * @param payVO
     * @param request
     * @return
     */
    public synchronized String getWxPaySign(PayVO payVO, HttpServletRequest request) {
        try {
            if (null == payVO) {
                return null;
            }
            String orderId = payVO.getOrderId();
            String wxCode = payVO.getCode();
            if (StringUtils.isEmpty(orderId) || StringUtils.isEmpty(wxCode)) {
                return null;
            }
            // 获取openId
            JSONObject openIdJson = getAccess_tokenByCode(wxCode);
            int errcode_openId = openIdJson.getInt("errcode");
            if (errcode_openId != 0) {// 调用获取openId接口不成功
                PayRespCodeMsg payRespCodeMsg = new PayRespCodeMsg(errcode_openId, openIdJson.getString("errmsg"));
                PayResultVO payResultVO = new PayResultVO(payRespCodeMsg, null);
                return JSON.toJSONString(payResultVO);
            }
            String openid = openIdJson.getString("openid");// 用户唯一标识
            String session_key = openIdJson.getString("session_key");// 会话秘钥

            // 获取本地订单相关信息
            Map<String, Object> orderDetails = sealOrderImplService.getOrderMapById(orderId);
            String siteName = (String) orderDetails.get("siteName");// 营业网点名称(刻章店名称)
            int orderPrice = ((BigDecimal) orderDetails.get("ORDER_AMOUNT")).intValue() * 100;
            String bodyName = siteName + "-" + ConstantUtil.ADVANCE_PAY_GOODS_NAME;// 商品名称严格按照规范-公众号支付-例如(商家名称-销售商品类目)
            String orderno = orderId;// "1234567890";
            Integer total_fee = orderPrice;// "8.88";// 订单总费用,不能有小数点,以分为单位
            String nonce_str = create_nonce_str();
            String timestamp = create_timestamp();

            // 获取预支付订单prepayId
            SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
            String prepayIdResult = getPrepayId(request, bodyName, orderno, total_fee, openid);// 获取预支付订单id方法,返回的xml字符串结果
            Map<String, String> prepayIdResultMap = doXMLParse(prepayIdResult);// xml字符串转map
            String prepayId_return_code = prepayIdResultMap.get("return_code");// SUCCESS/FAIL,此字段是通信标识,非交易标识,交易是否成功需要查看result_code来判断
            if (ConstantUtil.PREPAYID_RETURN_CODE_NO.equals(prepayId_return_code)) {// 获取prepayId接口通信异常
                PayRespCodeMsg preRespCodeMsg = new PayRespCodeMsg(-1, ConstantUtil.WECHAT_INTERFACE_EX_MSG);//
                PayResultVO preResultVO = new PayResultVO(preRespCodeMsg, null);
                return JSON.toJSONString(preResultVO);
            }
            // 获取prepayId的接口调用通信成功后
            String prepayId_result_code = prepayIdResultMap.get("result_code");// SUCCESS/FAIL,业务结果
            if (ConstantUtil.PAY_RETURN_CODE_NO.equals(prepayId_result_code)) {// 获取prepayId失败
                PayRespCodeMsg preNo = new PayRespCodeMsg(-1, "NO");
                PayResultVO preNoVO = new PayResultVO(preNo, null);
                return JSON.toJSONString(preNoVO);
            }

            // 微信预支付接口通信成功且业务结果成功
            // 重新生成签名
            parameters.put("appId", wechatPayConfigBean.getAppId());
            parameters.put("timeStamp", timestamp);
            parameters.put("nonceStr", nonce_str);
            parameters.put("package", "prepay_id=" + prepayIdResultMap.get("prepay_id"));
            parameters.put("signType", "MD5");
            String sign = createSign("UTF-8", parameters);
            parameters.put("prepay_id", "prepay_id=" + prepayIdResultMap.get("prepay_id"));
            parameters.put("paySign", sign);

            PayResultVO okResult = new PayResultVO(0, "OK", parameters);
            return JSON.toJSONString(okResult);


        } catch (Exception e) {
            PayResultVO resultVO = new PayResultVO(-1, "FALSE", null);
            return JSON.toJSONString(resultVO);
        }
    }

    public SortedMap<Object, Object> WapSignSignatureAction (HttpServletRequest request)throws Exception {
        SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
        String code = request.getParameter("code");
        System.out.println("code-------------" + code);
        // code作为换取access_token的票据,每次用户授权带上的code将不一样,code只能使用一次,5分钟未被使用自动过期。
        // 通过code换取网页授权access_token
        Map<String, String> data = getAccess_tokenByCode(code);
        String openid = data.get("openid");
        String tName = "名称";
        String orderno = "1234567890";
        String total_fee = "8.88";
        String nonce_str = create_nonce_str();
        String timestamp = create_timestamp();
        // 获取prepayId
        try {
            String result = getPrepayId(request, tName, orderno, Integer.parseInt(total_fee), openid);
            Map<String, String> map = doXMLParse(result);
            // 重新生成签名
            parameters.put("appId", wechatPayConfigBean.getAppId()
            );
            parameters.put("timeStamp", timestamp);
            parameters.put("nonceStr", nonce_str);
            parameters.put("package", "prepay_id=" + map.get("prepay_id"));
            parameters.put("signType", "MD5");
            String sign = createSign("UTF-8", parameters);
            parameters.put("prepay_id", "prepay_id=" + map.get("prepay_id"));
            parameters.put("paySign", sign);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return parameters;
    }

    /**
     * 根据用户授权code获取access_token
     */
    private JSONObject getAccess_tokenByCode(String code) {
        Map<String, String> data = new HashMap<String, String>();
        //String requestUrlMessageFormat = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={0}&secret={1}&code={2}&grant_type=authorization_code";
        String requestUrlMessageFormat = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={0}&secret={1}&code={2}&grant_type=authorization_code";
        String requestUrl = MessageFormat.format(requestUrlMessageFormat, wxPayProperties.getAppId()

                , appSecret

                , code);
        String requestMethod = "GET";
        String outputStr = "";
        JSONObject json = httpRequest(requestUrl, requestMethod, outputStr);
        //String access_token = (String) json.get("access_token");// 此参数最新接口文档没发现的
        String openid = (String) json.get("openid");// 用户唯一标识
        String session_key = json.getString("session_key");// 会话秘钥
        String unionid = json.getString("unionid");// 用户在开放平台的唯一标识符,在满足 UnionID 下发条件的情况下会返回
        int errcode = json.getInt("errcode");// 错误码
        String errmsg = json.getString("errmsg");// 错误信息
        //data.put("access_token", access_token);
        data.put("openid", openid);
        data.put("session_key", session_key);
        data.put("unionid", unionid);
        data.put("errcode", errcode + "");
        data.put("errmsg", errmsg);
        return json;
    }


    /**
     * 发起https请求并获取结果
     *
     * @param requestUrl    请求地址
     * @param requestMethod 请求方式(GET、POST)
     * @param outputStr     提交的数据
     * @return JSONObject(通过JSONObject.get ( key)的方式获取json对象的属性值)
     */
    public static JSONObject httpRequest(String requestUrl, String requestMethod, String outputStr) {
        JSONObject jsonObject = null;
        StringBuffer buffer = new StringBuffer();
        try {
            // 创建SSLContext对象,并使用我们指定的信任管理器初始化
            TrustManager[] tm = {new MyX509TrustManager()};
            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
            sslContext.init(null, tm, new java.security.SecureRandom());
            // 从上述SSLContext对象中得到SSLSocketFactory对象
            SSLSocketFactory ssf = sslContext.getSocketFactory();

            URL url = new URL(requestUrl);
            HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
            httpUrlConn.setSSLSocketFactory(ssf);

            httpUrlConn.setDoOutput(true);
            httpUrlConn.setDoInput(true);
            httpUrlConn.setUseCaches(false);
            // 设置请求方式(GET/POST)
            httpUrlConn.setRequestMethod(requestMethod);

            if ("GET".equalsIgnoreCase(requestMethod))
                httpUrlConn.connect();

            // 当有数据需要提交时
            if (null != outputStr) {
                OutputStream outputStream = httpUrlConn.getOutputStream();
                // 注意编码格式,防止中文乱码
                outputStream.write(outputStr.getBytes("UTF-8"));
                outputStream.close();
            }

            // 将返回的输入流转换成字符串
            InputStream inputStream = httpUrlConn.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);

            String str = null;
            while ((str = bufferedReader.readLine()) != null) {
                buffer.append(str);
            }
            bufferedReader.close();
            inputStreamReader.close();
            // 释放资源
            inputStream.close();
            inputStream = null;
            httpUrlConn.disconnect();
            jsonObject = JSONObject.fromObject(buffer.toString());
        } catch (ConnectException ce) {
            System.err.println("Weixin server connection timed out.");
        } catch (Exception e) {
            System.err.println("https request error");
        }
        return jsonObject;
    }


    /**
     * 获取预支付订单id
     *
     * @param request
     * @param name
     * @param orderno
     * @param total_fee
     * @param openid
     * @return
     * @throws Exception
     */
    public String getPrepayId(HttpServletRequest request, String name, String orderno, Integer total_fee,
                              String openid) throws Exception {
        SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
        parameters.put("appid", wechatPayConfigBean.getAppId()

        );// 服务商id
        parameters.put("mch_id", wechatPayConfigBean.getMchId()

        );// 商户号
        parameters.put("nonce_str", CreateNoncestr());// 随机字符串
        parameters.put("body", name);// 商品描述
        parameters.put("out_trade_no", orderno);// 商户系统内部订单号,要求32个字符内,只能是数字、大小写字母_-|*且在同一个商户号下唯一
        parameters.put("total_fee", total_fee);// 支付金额单位:分
        parameters.put("spbill_create_ip", getIp2(request));// 支持IPV4和IPV6两种格式的IP地址。调用微信支付API的机器IP
        parameters.put("notify_url", wechatPayConfigBean.getPayResultNotifyUrl());// 接收微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数
        parameters.put("trade_type", "JSAPI");// 交易类型,小程序取值如下:JSAPI,详细说明见
        parameters.put("openid", openid);// 商户标识
        parameters.put("time_expire", DateUtil.getTimeStamp());// (非必填)交易结束时间,需要动态传入,格式为yyyyMMddHHmmss-20190719114936
        String sign = createSign("UTF-8", parameters);
        parameters.put("sign", sign);
        String requestXML = getRequestXml(parameters);
        // 调用统一下单接口
        String result = httpsRequest("https://api.mch.weixin.qq.com/pay/unifiedorder", "POST", requestXML);
        System.out.println(result);
        return result;
    }

    public static String CreateNoncestr() {
        String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        String res = "";
        for (int i = 0; i < 16; i++) {
            Random rd = new Random();
            res += chars.charAt(rd.nextInt(chars.length() - 1));
        }
        return res;
    }

    public static String getIp2(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (!org.apache.commons.lang3.StringUtils.isEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)) {
            // 多次反向代理后会有多个ip值,第一个ip才是真实ip
            int index = ip.indexOf(",");
            if (index != -1) {
                return ip.substring(0, index);
            } else {
                return ip;
            }
        }
        ip = request.getHeader("X-Real-IP");
        if (!org.apache.commons.lang3.StringUtils.isEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)) {
            return ip;
        }
        return request.getRemoteAddr();
    }

    @SuppressWarnings("rawtypes")
    public String createSign(String characterEncoding, SortedMap<Object, Object> 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=" + wechatPayConfigBean.getApiKey()
        );
        String sign = MD5Encode(sb.toString(), characterEncoding).toUpperCase();
        return sign;
    }

    public static String MD5Encode(String origin, String charsetname) {
        String resultString = null;
        try {
            resultString = new String(origin);
            MessageDigest md = MessageDigest.getInstance("MD5");
            if (charsetname == null || "".equals(charsetname))
                resultString = byteArrayToHexString(md.digest(resultString.getBytes()));
            else
                resultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetname)));
        } catch (Exception exception) {
        }
        return resultString;
    }

    private static String byteArrayToHexString(byte b[]) {
        StringBuffer resultSb = new StringBuffer();
        for (int i = 0; i < b.length; i++)
            resultSb.append(byteToHexString(b[i]));
        return resultSb.toString();
    }

    private static String byteToHexString(byte b) {
        int n = b;
        if (n < 0)
            n += 256;
        int d1 = n / 16;
        int d2 = n % 16;
        return hexDigits[d1] + hexDigits[d2];
    }

    private static final String hexDigits[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d",
            "e", "f"};

    @SuppressWarnings("rawtypes")
    public static String getRequestXml(SortedMap<Object, Object> 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 k = (String) entry.getKey();
            String v = (String) entry.getValue();
            if ("attach".equalsIgnoreCase(k) || "body".equalsIgnoreCase(k) || "sign".equalsIgnoreCase(k)) {
                sb.append("<" + k + ">" + "<![CDATA[" + v + "]]></" + k + ">");
            } else {
                sb.append("<" + k + ">" + v + "</" + k + ">");
            }
        }
        sb.append("</xml>");
        return sb.toString();
    }


    /**
     * * 发送https请求
     *
     * @param requestUrl    请求地址
     * @param requestMethod 请求方式(GET、POST)
     * @param outputStr     提交的数据
     * @return 返回微信服务器响应的信息
     */
    public static String httpsRequest(String requestUrl, String requestMethod, String outputStr) {
        try {
            // 创建SSLContext对象,并使用我们指定的信任管理器初始化
            TrustManager[] tm = {new MyX509TrustManager()};
            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
            sslContext.init(null, tm, new java.security.SecureRandom());
            // 从上述SSLContext对象中得到SSLSocketFactory对象
            SSLSocketFactory ssf = sslContext.getSocketFactory();
            URL url = new URL(requestUrl);
            HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
            conn.setSSLSocketFactory(ssf);
            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) {
            System.out.println("连接超时");
        } catch (Exception e) {
            System.out.println("请求异常");
        }
        return null;
    }

    public static String create_nonce_str() {
        return UUID.randomUUID().toString().replace("-", "");
    }

    public static String create_timestamp() {
        return Long.toString(System.currentTimeMillis() / 1000);
    }

    /**
     * 解析xml
     *
     * @param strxml
     * @return
     * @throws Exception
     */
    @SuppressWarnings({"rawtypes", "unchecked"})
    public static Map doXMLParse(String strxml) throws Exception {
        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;
    }

    /**
     * 获取子结点的xml
     *
     * @param children
     * @return
     */
    @SuppressWarnings("rawtypes")
    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();
    }


}