微信退款

1. package com.ds.tech.common.util.weixinpay;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.KeyStore;
import java.security.MessageDigest;
import java.security.Security;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.net.ssl.SSLContext;

import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpResponse;
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.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import com.ds.tech.common.constant.ApiStaticConstant;
import com.ds.tech.common.enums.WxCallBackBusiness;
import com.ds.tech.common.util.XMLUtil;
import com.ds.tech.entity.base.BaseMapEntity;
import com.ds.tech.utility.common.ConfigUtil;
import com.ds.tech.utility.log4j.LogWriter;

public class WeixinPayUtils {
    
    private static Logger logger = LogManager.getLogger(WeixinPayUtils.class);
    
    private static final String[] hexDigits = new String[]{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};
    
    private static String appId = null;
    private static String mchId = null;
    private static String wxRefundUrl = null;
    static {
        appId = ConfigUtil.getSettings("wx_appid").trim();
        mchId = ConfigUtil.getSettings("wx_mch_id").trim();
        wxRefundUrl = ConfigUtil.getSettings("wx_refund_url").trim();
    }
   
    /**
     * 所有参数全部必传
     * @param orderNo   商户订单号
     * @param outRefundNo  outRefundNo 支持单笔多次退款,每次不一样
     * @param totalFee     //总金额   -- 单位元
     * @param refundFee     //退款金额  -- 单位元
     * @param refundDesc    //退款原因
     * @param refundAccount   //必传 //REFUND_SOURCE_UNSETTLED_FUNDS---未结算资金退款(默认使用未结算资金退款)REFUND_SOURCE_RECHARGE_FUNDS---可用余额退款
     * @param business   //业务类型,拼接到商户订单号后面,回调解析取出,根据类型处理不同业务
     * @return
     */
    public static Map<String, String> wxRefund(
            String orderNo,
            String outRefundNo,
            String totalFee,
            String refundFee,
            String refundDesc,
            String refundAccount,
            WxCallBackBusiness business) {
        logger.info("微信支付退款入参:orderNo:" + orderNo + ",outRefundNo:" + outRefundNo + 
                                ",totalFee:" + totalFee + ",refundFee:" + refundFee + 
                                ",refundDesc:" + refundDesc + ",refundAccount:" + refundAccount);
        
        if (StringUtils.isBlank(orderNo)
                || StringUtils.isBlank(outRefundNo)
                || StringUtils.isBlank(totalFee)
                || StringUtils.isBlank(refundFee)
                || StringUtils.isBlank(refundDesc)
                || StringUtils.isBlank(refundAccount)
                || null == business) {
            logger.info("微信支付退款失败,必传参数为空!");
            return null;
        }
        
        //非必传参数处理
        BaseMapEntity parameters = new BaseMapEntity();
        parameters.put("feeType", "CNY");
        parameters.put("refundDesc", refundDesc);
        parameters.put("refundAccount", refundAccount);
        
        //微信回调统一地址
        String wxRefundCallbackUrl = ConfigUtil.getSettings("pament_domain")+"/api/pay/WeChatCallback/" + business.getNumber() + "/wxRefundCallback.do";
        logger.info("微信支付退款:wxRefundCallbackUrl = " + wxRefundCallbackUrl);
        parameters.put("notifyUrl", wxRefundCallbackUrl);
        
        
        //微信接收的金额单位为分,所以讲入参转换
        String totalCent = (new BigDecimal(totalFee).multiply(new BigDecimal("100"))).intValue() + "" ;
        String refundCent = (new BigDecimal(refundFee).multiply(new BigDecimal("100"))).intValue() + "";
        
        //请求参数转换成微信支持的xml格式
        Map<String, String> map = requestWxRefundParams(orderNo,outRefundNo,totalCent,refundCent,parameters);
        String xml = mapToXML(map);
        logger.info("xml:" + xml);
        
        try {
            //读取本机存放的PKCS12证书文件
            String path = ApiStaticConstant.getStaticValue("apiWebClassPath") + "keys" + File.separator + "apiclient_cert.p12";
            KeyStore keyStore  = KeyStore.getInstance("PKCS12");
            FileInputStream instream = new FileInputStream(new File(path));
            
            try {
                指定PKCS12的密码(商户ID)
                keyStore.load(instream, mchId.toCharArray());
            } finally  {
                instream.close();
            }
            
            //指定TLS版本
            SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, mchId.toCharArray()).build();
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext,new String[] { "TLSv1" },null,SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
            CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
            
            //发送请求
            HttpPost httpost= new HttpPost(wxRefundUrl);
            httpost.setEntity(new StringEntity(xml,"UTF-8"));
            HttpResponse wxResponse = httpclient.execute(httpost);
            
            //退款结果处理
            String jsonStr = EntityUtils.toString(wxResponse.getEntity(), "UTF-8");
            logger.info("jsonStr:" + jsonStr);
            
            return XMLUtil.doXMLParse(jsonStr);
        } catch (Exception e ) {
            logger.info("微信支付退款失败!");
        }
        return null;
    }
    
    
    
    /**
     * 
     * @param orderNo   商户订单号
     * @param totalFee   交易总金额
     * @param refundFee   退款金额
     * @param parameters   扩展的非必传参数
     * @return
     */
    private static Map<String, String> requestWxRefundParams(
            String orderNo,
            String outRefundNo,
            String totalFee,
            String refundFee,
            BaseMapEntity parameters){
        Map<String, String> map = new HashMap<>();
        map.put("appid", appId);
        map.put("mch_id", mchId);//微信支付分配的商户号
        map.put("nonce_str", UUID.randomUUID().toString().replaceAll("-", ""));
        map.put("sign_type", "MD5");
        map.put("out_trade_no", orderNo);
        map.put("out_refund_no", outRefundNo);
        map.put("total_fee", totalFee);
        map.put("refund_fee", refundFee);
        map.put("refund_fee_type", parameters.getString("feeType"));
        map.put("refund_desc", parameters.getString("refundDesc"));
        map.put("refund_account",parameters.getString("refundAccount"));
        map.put("notify_url",parameters.getString("notifyUrl"));
        map.put("sign", getSign(map));
        return map;
    }
    
    
    /**
     * 微信小程序支付
     * @param orderName   商品描述
     * @param orderDesc   商品详情
     * @param attach      附加数据
     * @param orderNo     订单号
     * @param price       金额
     * @param notifyUrl   回调地址
     * @param limitCreditCard  是否限制信用卡
     * @param openid      用户标识
     * @return
     */
    public static Map<String, Object> getWeixinMinPayParam(String orderName, String orderDesc,String attach, String orderNo, BigDecimal price,String notifyUrl,boolean  limitCreditCard,String openid) {

        //是否限制信用卡
        String limitPay = "";
        if(limitCreditCard){
            limitPay = "no_credit";
        }
        int totalPrice = (price.multiply(new BigDecimal("100"))).intValue();
        Map<String, Object> wxMap = new HashMap();
        Map<String, String> map = requestParam(ConfigUtil.getSettings("wx_appid").trim(),orderName, orderDesc, attach, orderNo, totalPrice, notifyUrl, "JSAPI", limitPay, openid);
        Long timestamp = Long.valueOf(System.currentTimeMillis() / 1000L);
        wxMap.put("wx_appid",ConfigUtil.getSettings("wx_appid"));
        wxMap.put("timestamp", timestamp.toString());
        wxMap.put("noncestr", UUID.randomUUID().toString().replaceAll("-", ""));
        wxMap.put("package", getWXprepayID(map));
        wxMap.put("signType", "MD5");
        wxMap.put("paySign", getPaySign(wxMap));
        return wxMap;
    }

    /**
     * 微信支付
     * @Param appid
     * @param orderName  商品描述
     * @param orderDesc  商品详情
     * @param attach     附加数据
     * @param orderNo    订单号
     * @param totalPrice 标价金额
     * @param notifyUrl  回调地址
     * @param tradeType  交易类型 JSAPI--公众号支付、NATIVE--原生扫码支付、APP--app支付
     * @param limitPay   指定支付方式 上传此参数no_credit--可限制用户不能使用信用卡支付
     * @param openid     用户标识 trade_type=JSAPI,此参数必传,用户在商户appid下的唯一标识
     * @return
     */
    private static Map<String, String> requestParam(String appid,String orderName,String orderDesc,String attach, String orderNo, int totalPrice, String notifyUrl,String tradeType,String limitPay,String openid) {
        Map<String, String> map = new HashMap();
        Date date = new Date();
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        String startTime = (new SimpleDateFormat("yyyyMMddHHmmss")).format(date);
        calendar.add(5, 1);
        date = calendar.getTime();
        String endTime = (new SimpleDateFormat("yyyyMMddHHmmss")).format(date);
        map.put("appid", appid);
        map.put("mch_id", ConfigUtil.getSettings("wx_mch_id").trim());//微信支付分配的商户号
        map.put("device_info", "WEB");//设备号
        map.put("nonce_str", UUID.randomUUID().toString().replaceAll("-", ""));//随机字符串
        map.put("sign_type", "MD5");//签名类型
        map.put("body", orderName);//商品描述
        map.put("detail", orderDesc);//商品详情
        map.put("attach", attach);//附加数据
        map.put("out_trade_no", orderNo);//商户订单号
        map.put("fee_type", "CNY");//币种
        map.put("total_fee",String.valueOf(totalPrice));//标价金额
        map.put("spbill_create_ip", ConfigUtil.getSettings("wx_spbill_create_ip"));//终端IP
        map.put("time_start", startTime);//交易起始时间
        map.put("time_expire", endTime);//交易结束时间
        map.put("notify_url", notifyUrl);//回调地址
        map.put("trade_type", tradeType);//交易类型  JSAPI--公众号支付、NATIVE--原生扫码支付、APP--app支付
        map.put("limit_pay", limitPay);//指定支付方式  上传此参数no_credit--可限制用户不能使用信用卡支付
        map.put("openid",openid);//trade_type=JSAPI,此参数必传,用户在商户appid下的唯一标识
        map.put("sign", getSign(map));
        return map;
    }

    private static String getSign(Map<String, String> data){
        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 (k.equals("sign")) {
                continue;
            }
            
            if (StringUtils.isBlank(data.get(k))) {
                continue;
            }
            
            // 参数值为空,则不参与签名
            sb.append(k).append("=").append(data.get(k).trim()).append("&");
        }
        sb.append("key=").append(ConfigUtil.getSettings("wx_key").trim());
        String a = "";
        try {
            a = MD5(sb.toString()).toUpperCase();
        }catch (Exception e){
            e.printStackTrace();
        }
        return a;
    }

    /**
     * 生成 MD5
     *
     * @param data 待处理数据
     * @return MD5结果
     */
    public static String MD5(String data) throws Exception {
        java.security.MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] array = md.digest(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();
    }

    private 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(charsetname)));
            } else {
                resultString = byteArrayToHexString(md.digest(resultString.getBytes()));
            }
        } catch (Exception var4) {
            ;
        }

        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(b < 0) {
            n = b + 256;
        }

        int d1 = n / 16;
        int d2 = n % 16;
        return hexDigits[d1] + hexDigits[d2];
    }

    private static String getWXprepayID(Map<String, String> map) {
        String prepayId = null;
        String xml = mapToXML(map);
        System.out.println(xml);
        String uri = ConfigUtil.getSettings("wx_pay_url");

        try {
            URL url = new URL(uri);
            HttpURLConnection http = (HttpURLConnection)url.openConnection();
            http.setRequestMethod("POST");
            http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            http.setDoOutput(true);
            http.setDoInput(true);
            http.connect();
            OutputStream os = http.getOutputStream();
            os.write(xml.getBytes("UTF-8"));
            os.flush();
            os.close();
            InputStream is = http.getInputStream();
            int size = is.available();
            byte[] jsonBytes = new byte[size];
            is.read(jsonBytes);
            String message = new String(jsonBytes, "UTF-8");
            LogWriter.writeAccessLog("get prepayID message:" + message);
            System.out.println("get prepayID message:"+message);
            logger.info("get prepayID message:"+message);
            Document doc = DocumentHelper.parseText(message);
            Element rootElement = doc.getRootElement();
            List<Element> elements = rootElement.elements();

            for(int i = 0; i < elements.size(); ++i) {
                Element element = (Element)elements.get(i);
                String elementName = element.getName();
                if("prepay_id".equals(elementName)) {
                    prepayId = element.getText();
                }
            }
        } catch (MalformedURLException var17) {
            var17.printStackTrace();
        } catch (IOException var18) {
            var18.printStackTrace();
        } catch (DocumentException var19) {
            var19.printStackTrace();
        }

        return prepayId;
    }

    private static String mapToXML(Map<String, String> map) {
        StringBuffer sb = new StringBuffer();
        sb.append("<xml>");
        for(Map.Entry<String,String> entry:map.entrySet()){
            if(entry.getValue()!=""){
                sb.append("<"+entry.getKey()+">"+entry.getValue()+"</"+entry.getKey()+">");
            }
        }
        sb.append("</xml>");
        return sb.toString();
    }

    private static String getPaySign(Map<String, Object> map) {
        StringBuffer sb = new StringBuffer();
        sb.append("appId=" + ConfigUtil.getSettings("wx_appid"));
        sb.append("&nonceStr=" + map.get("noncestr"));
        sb.append("&package=prepay_id=" + map.get("package"));
        sb.append("&signType=" + map.get("signType"));
        sb.append("&timeStamp=" + map.get("timestamp"));
        String a = sb.toString();
        String stringSignTemp = a + "&key=" + ConfigUtil.getSettings("wx_key").trim();
        String sign = MD5Encode(stringSignTemp, "UTF-8").toUpperCase();
        return sign;
    }
    

    /**
     * 
     * @param reqInfoSecret
     * @param key
     * @return
     */
     @SuppressWarnings("restriction")
    public static String getRefundDecrypt(String reqInfoSecret, String key) {
         String result = "";
         try {
             Security.addProvider(new BouncyCastleProvider());
             sun.misc.BASE64Decoder decoder = new sun.misc.BASE64Decoder();
             byte[] bt = decoder.decodeBuffer(reqInfoSecret);
             String b = new String(bt);
             String md5key = MD5(key).toLowerCase();
             SecretKey secretKey = new SecretKeySpec(md5key.getBytes(), "AES");
             Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC");
             cipher.init(Cipher.DECRYPT_MODE, secretKey);
             byte[] resultbt = cipher.doFinal(bt);
             result = new String(resultbt,"UTF-8");
         } catch (Exception e) {
             e.printStackTrace();
         }
         return result;
     }
     
     public static String setXML(String return_code, String return_msg) {
         return "<xml><return_code><![CDATA[" + return_code
                 + "]]></return_code><return_msg><![CDATA[" + return_msg
                 + "]]></return_msg></xml>";
  
     }
    
}

 

2. package com.ds.tech.controller.zenith.callback;

import com.ds.tech.controller.base.BaseAPIController;
import com.ds.tech.service.zenith.pay.WeChatCallbackService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Controller
@RequestMapping("/api/pay/WeChatCallback")
@Scope("prototype")
public class WeChatCallbackController extends BaseAPIController {
    @Autowired
    private WeChatCallbackService weChatCallbackService;


    /**
     * 2018年11月29日
     * @param request
     * @param respone
     */
    @RequestMapping(value = "/{cbbNumber}/wxRefundCallback", method = RequestMethod.POST)
    public void wxRefundCallback(@PathVariable("cbbNumber") String cbbNumber,HttpServletRequest request, HttpServletResponse respone) {
        weChatCallbackService.wxRefundCallback(cbbNumber,request,respone);
    }

}
3. 

package com.ds.tech.service.zenith.pay;

import java.io.IOException;
import java.util.Date;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.jdom.JDOMException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONObject;
import com.ds.tech.common.enums.WxCallBackBusiness;
import com.ds.tech.common.model.WxRefundResponse;
import com.ds.tech.common.util.ResponseHandler;
import com.ds.tech.common.util.XMLUtil;
import com.ds.tech.common.util.weixinpay.WeixinPayUtils;
import com.ds.tech.dao.account.UserPurseWaterDao;
import com.ds.tech.dao.account.UserPurseWaterHistoryDao;
import com.ds.tech.dao.order.VehicleOrderDao;
import com.ds.tech.entity.base.BaseMapEntity;
import com.ds.tech.service.base.BaseAPIService;
import com.ds.tech.service.wxmini.order.OrderWxService;
import com.ds.tech.utility.common.ConfigUtil;
import com.ds.tech.utility.log4j.LogWriter;
import com.ds.tech.utility.model.ResultObject;


@Service
public class WeChatCallbackService extends BaseAPIService {

    @Autowired
    private OrderWxService orderWxService;
    

    @Autowired
    private VehicleOrderDao vehicleOrderMapper;
    

    @Autowired
    private UserPurseWaterDao userPurseWaterMapper;
    

    @Autowired
    private UserPurseWaterHistoryDao userPurseWaterHisMapper;
    
    /**
     * 2018年11月29日
     * @param request
     * @param response
     */
    public void wxRefundCallback(String cbbNumber,HttpServletRequest request, HttpServletResponse response) {
        LogWriter.writeAccessLog("-----微信退款回调开始--------");
        String inputLine;
        String notityXml = "";
        
        try {
            while ((inputLine = request.getReader().readLine()) != null) {
                notityXml += inputLine;
            }
            LogWriter.writeAccessLog("接收到的报文:" + notityXml);
            
            // 创建支付应答对象
            ResponseHandler resHandler = new ResponseHandler(request, response);
            resHandler.setKey(ConfigUtil.getSettings("wx_key").trim());
            
            Map<String, String> map = XMLUtil.doXMLParse(notityXml);
            if ("SUCCESS".equals(map.get("return_code"))) {
                String reqInfo = map.get("req_info").toString();
                
                //加密内容解密
                String reqInfoDecrypt = WeixinPayUtils.getRefundDecrypt(reqInfo, ConfigUtil.getSettings("wx_key").trim());
                LogWriter.writeAccessLog("解密内容的报文:" + reqInfoDecrypt);
                
                //解密内容为空,返回调用失败信息给微信方
                if (StringUtils.isBlank(reqInfoDecrypt)) {
                    LogWriter.writeAccessLog("-----微信退款返回失败:解析内容失败--------");
                    String retWXMsg = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[FAIL]]></return_msg></xml>";
                    resHandler.sendToCFT(retWXMsg);
                    return;
                }
                
                Map<String, String> refundMap = XMLUtil.doXMLParse(reqInfoDecrypt);
                WxRefundResponse resp = new WxRefundResponse();
                resp.setReturnCode(map.get("return_code"));
                resp.setReturnMsg(map.get("req_info"));
                resp.setAppId(map.get("appid"));
                resp.setMchId(map.get("mch_id"));
                resp.setNonceStr(map.get("nonce_str"));
                resp.setTransactionId(refundMap.get("transaction_id"));
                resp.setOutTradeNo(refundMap.get("out_trade_no"));
                resp.setRefundId(refundMap.get("refund_id"));
                resp.setOutRefundNo(refundMap.get("out_refund_no"));
                resp.setTotalFee(refundMap.get("total_fee"));
                resp.setSettlementTotalFee(refundMap.get("settlement_total_fee"));
                resp.setRefundFee(refundMap.get("refund_fee"));
                resp.setSettlementRefundFee(refundMap.get("settlement_refund_fee"));
                resp.setRefundStatus(refundMap.get("refund_status"));
                resp.setSuccessTime(refundMap.get("success_time"));
                resp.setRefundRecvAccout(refundMap.get("refund_recv_accout"));
                resp.setRefundAccount(refundMap.get("refund_account"));
                resp.setRefundRequestSource(refundMap.get("refund_request_source"));
                
                //订单编号处理 outTradeNo = orderNo + number(WxCallBackBusiness)
                String orderNo = resp.getOutTradeNo();
                LogWriter.writeAccessLog("------orderNo:" + orderNo + ",cbbNumber:" + cbbNumber + "-------");
                
                //检查订单信息
                BaseMapEntity orderParamMap = new BaseMapEntity();
                orderParamMap.put("orderNo",orderNo);
                BaseMapEntity vehicleOrder = vehicleOrderMapper.queryVehicleOrderInfo(orderParamMap);
                if (null == vehicleOrder) {
                    LogWriter.writeAccessLog("-----微信退款返回失败:订单编号找不到--------");
                    String retWXMsg = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[FAIL]]></return_msg></xml>";
                    resHandler.sendToCFT(retWXMsg);
                    return;
                }
                
                 //查询订单支付时的流水,每个订单只有一笔支付记录
                BaseMapEntity waterParam = new BaseMapEntity();
                waterParam.put("orderNo",orderNo);
                BaseMapEntity queryWater = userPurseWaterMapper.selectPayedPurseWaterByOrderNo(waterParam);
                if(null == queryWater){
                    LogWriter.writeAccessLog("-----微信退款返回失败:订单编号找不到交易流水--------");
                    String retWXMsg = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[FAIL]]></return_msg></xml>";
                    resHandler.sendToCFT(retWXMsg);
                    return;
                }
                
                //交易流水表
                Date curDate = new Date();
                BaseMapEntity waterMap = new BaseMapEntity();
                waterMap.put("userId", vehicleOrder.getInt("userId"));
                waterMap.put("orderNo", orderNo);
                waterMap.put("thirdTradeNo", resp.getOutRefundNo());
                waterMap.put("purseChannel", 3);
                waterMap.put("depositTime", curDate);
                waterMap.put("profitType", 2);
                waterMap.put("incomeTime", curDate);
                waterMap.put("state", 2);
                waterMap.put("tradeStartAccount", "微信");
                waterMap.put("tradeReceiveAccount", queryWater.getString("tradeStartAccount"));
                waterMap.put("tradeAmount", resp.getSettlementRefundFee());
                waterMap.put("tradeResult", resp.getRefundStatus());
                waterMap.put("waterRemark", null != WxCallBackBusiness.getEnum(cbbNumber) ? WxCallBackBusiness.getEnum(cbbNumber).getName() : null);
                waterMap.put("createUser", "weixinCallBack");
                waterMap.put("updateUser", "weixinCallBack");
                waterMap.put("payUserId", null);
                vehicleOrderMapper.insertPurseWater(waterMap);
                
                //通信成功,且解密转对象成功,添加流水历史记录表
                BaseMapEntity waterHisMap = new BaseMapEntity();
                waterHisMap.put("className", "com.ds.tech.service.zenith.pay.WeChatCallbackService");
                waterHisMap.put("methodName", "wxRefundCallback");
                waterHisMap.put("tradeType", "3");   //交易方式:1.银行卡 2.支付宝 3.微信
                waterHisMap.put("tradeInput", JSONObject.toJSON(resp).toString());
                waterHisMap.put("tradeOutput", null);
                waterHisMap.put("tradeTime", new Date());
                userPurseWaterHisMapper.insertUserPurseWaterHistory(waterHisMap);
                
                String retWXMsg = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
                resHandler.sendToCFT(retWXMsg);
                LogWriter.writeAccessLog("-----保存数据成功,微信回调完毕--------");
                return;
            }
            
            String retWXMsg = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[FAIL]]></return_msg></xml>";
            resHandler.sendToCFT(retWXMsg);
            LogWriter.writeAccessLog("-----微信退款回调失败--------");
            return;
        } catch (Exception e) {
            LogWriter.writeErrorLog("微信退款回调失败,:wxRefundCallback");
        }
        LogWriter.writeAccessLog("-----微信退款回调结束--------");
    }
    
    /***
     * 微信支付异步通知
     */
    public void weChatCallbackForOrderPay(HttpServletRequest request, HttpServletResponse response) {
        LogWriter.writeAccessLog("-----支付回调开始--------");
        String inputLine;
        String notityXml = "";
        try {
            LogWriter.writeAccessLog("-----支付回调开始--------");
            while ((inputLine = request.getReader().readLine()) != null) {
                notityXml += inputLine;
            }
            request.getReader().close();

            LogWriter.writeAccessLog("接收到的报文--------" + notityXml);
            System.out.println("接收到的报文:" + notityXml);
            Map<String, String> map = XMLUtil.doXMLParse(notityXml);
            // 密钥
            // 创建支付应答对象
            ResponseHandler resHandler = new ResponseHandler(request, response);
            resHandler.setKey(ConfigUtil.getSettings("wx_key").trim());

            if (resHandler.isTenpaySign(map)) {
                LogWriter.writeAccessLog("-----验证成功--------");
                // 获取返回参数
                String rescode = map.get("result_code");
                // 商户订单号
                String out_trade_no = map.get("out_trade_no");
                // 微信支付订单号
                String transaction_id = map.get("transaction_id");
                // 支付完成时间
                String time_end = map.get("time_end");

                String total = map.get("total_fee");

                if ("SUCCESS".equals(rescode)) {// 返回成功
                    BaseMapEntity orderParams = new BaseMapEntity();
                    orderParams.put("orderNo",out_trade_no);//订单编号
                    orderParams.put("payPrice",total);//支付金额
                    orderParams.put("thirdTradeNo",transaction_id);//交易流水号
                    ResultObject resultObject = orderWxService.updateOrderAfterTenantPay(orderParams);
                    if (resultObject.getErrcode() == 0) {
                        String retWXMsg = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
                        resHandler.sendToCFT(retWXMsg);
                        LogWriter.writeAccessLog("-----保存数据成功,通知微信完毕--------");
                        return;
                    }
                } else {
                    LogWriter.writeAccessLog("-----微信返回失败--------");
                    String retWXMsg = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[FAIL]]></return_msg></xml>";
                    resHandler.sendToCFT(retWXMsg);
                    return;
                }

            }
            LogWriter.writeAccessLog("-----微信返回失败--------");
            String retWXMsg = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[FAIL]]></return_msg></xml>";
            resHandler.sendToCFT(retWXMsg);
            LogWriter.writeAccessLog("-----验证请求失败--------");
        } catch (NumberFormatException e) {
            LogWriter.writeErrorLog("微信回调接口失败,原因:", e);
        } catch (JDOMException e) {
            LogWriter.writeErrorLog("微信回调接口失败,原因:", e);
        } catch (IOException e) {
            LogWriter.writeErrorLog("微信回调接口失败,原因:", e);
        }
//        catch (ParseException e) {
//            LogWriter.writeErrorLog("微信回调接口失败,原因:", e);
//        }
        LogWriter.writeAccessLog("-----支付回调结束--------");
    }

    /***
     * 微信支付欠款订单回回调函数
     * @param request
     * @param response
     */
    public void weChatCallbackForPayDebtOrder(HttpServletRequest request, HttpServletResponse response) {
        logger.info("-----支付欠款回调开始--------");
        String inputLine;
        String notityXml = "";
        try {
            while ((inputLine = request.getReader().readLine()) != null) {
                notityXml += inputLine;
            }
            request.getReader().close();

            logger.info("接收到的报文--------" + notityXml);
            Map<String, String> map = XMLUtil.doXMLParse(notityXml);
            // 密钥
            // 创建支付应答对象
            ResponseHandler resHandler = new ResponseHandler(request, response);
            resHandler.setKey(ConfigUtil.getSettings("wx_key").trim());

            if (resHandler.isTenpaySign(map)) {
                logger.info("-----验证成功--------");
                // 获取返回参数
                String rescode = map.get("result_code");
                // 商户订单号
                String out_trade_no = map.get("out_trade_no");
                // 微信支付订单号
                String transaction_id = map.get("transaction_id");
                // 支付完成时间
                String time_end = map.get("time_end");

                String total = map.get("total_fee");

                if ("SUCCESS".equals(rescode)) {// 返回成功
                    BaseMapEntity orderParams = new BaseMapEntity();
                    orderParams.put("orderNo",out_trade_no);//订单编号
                    orderParams.put("payPrice",total);//支付金额
                    orderParams.put("thirdTradeNo",transaction_id);//交易流水号
                    ResultObject resultObject = orderWxService.updateAfterTenantPayDebtOrder(orderParams);
                    if (resultObject.getErrcode() == 0) {
                        String retWXMsg = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
                        resHandler.sendToCFT(retWXMsg);
                        return;
                    }
                } else {
                    logger.info("-----微信返回失败--------");
                    String retWXMsg = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[FAIL]]></return_msg></xml>";
                    resHandler.sendToCFT(retWXMsg);
                    return;
                }

            }
            String retWXMsg = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[FAIL]]></return_msg></xml>";
            resHandler.sendToCFT(retWXMsg);
        } catch (NumberFormatException e) {
            logger.error("微信回调接口失败,原因:", e);
        } catch (JDOMException e) {
            logger.error("微信回调接口失败,原因:", e);
        } catch (IOException e) {
            logger.error("微信回调接口失败,原因:", e);
        }
        logger.info("-----支付欠款回调结束--------");
    }
}
 

 

 


 

转载于:https://my.oschina.net/u/2611678/blog/2967052

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值