| package com.xzx.gc.pay.service;  | 
|   | 
|   | 
| import cn.hutool.core.bean.BeanUtil;  | 
| import cn.hutool.core.convert.Convert;  | 
| import cn.hutool.core.date.DateUtil;  | 
| import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;  | 
| import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;  | 
| import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;  | 
| import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult;  | 
| import com.github.binarywang.wxpay.service.WxPayService;  | 
| import com.xzx.gc.common.Result;  | 
| import com.xzx.gc.common.constant.Constants;  | 
| import com.xzx.gc.common.constant.PayEnum;  | 
| import com.xzx.gc.common.dto.log.PayInfoLog;  | 
| import com.xzx.gc.common.exception.wx.WxPayNotifyResponseException;  | 
| import com.xzx.gc.common.utils.BusinessUtil;  | 
| import com.xzx.gc.common.utils.ExceptionUtils;  | 
| import com.xzx.gc.common.utils.RedisUtil;  | 
| import com.xzx.gc.common.utils.wxpay.WXPayUtil;  | 
| import com.xzx.gc.entity.AccountInfo;  | 
| import com.xzx.gc.entity.PayInfo;  | 
| import com.xzx.gc.entity.PayWxRecord;  | 
| import com.xzx.gc.pay.dto.PayParamDTO;  | 
| import com.xzx.gc.pay.dto.PayResultDTO;  | 
| import com.xzx.gc.pay.mapper.PayInfoMapper;  | 
| import com.xzx.gc.pay.mapper.PayWxRecordMapper;  | 
| import lombok.extern.slf4j.Slf4j;  | 
| import org.springframework.beans.BeanUtils;  | 
| import org.springframework.beans.factory.annotation.Autowired;  | 
| import org.springframework.stereotype.Service;  | 
| import org.springframework.transaction.annotation.Transactional;  | 
|   | 
| import javax.servlet.http.HttpServletRequest;  | 
| import java.util.HashMap;  | 
| import java.util.Map;  | 
|   | 
| @Service  | 
| @Transactional  | 
| @Slf4j  | 
| public class WeiXinService {  | 
|     @Autowired  | 
|     private WxPayService wxPayService;  | 
|   | 
|   | 
|     @Autowired  | 
|     private PayService payService;  | 
|   | 
|     @Autowired  | 
|     private PayInfoMapper payInfoMapper;  | 
|   | 
|     @Autowired  | 
|     private HttpServletRequest request;  | 
|   | 
|     @Autowired  | 
|     private RedisUtil redisUtil;  | 
|   | 
|     @Autowired  | 
|     private PayWxRecordMapper payWxRecordMapper;  | 
|   | 
|     @Autowired  | 
|     private PayInfoLogService payInfoLogService;  | 
|   | 
|     @Autowired  | 
|     private BusinessUtil businessUtil;  | 
|   | 
|     @Autowired  | 
|     private AccountService accountService;  | 
|   | 
|     /**  | 
|      * 生成小程序支付签名  | 
|      * @param payResultDTO  | 
|      * @return  | 
|      * @throws Exception  | 
|      */  | 
|     private String geWebSign(PayResultDTO payResultDTO) throws Exception {  | 
|         Map<String, String> packageParams = new HashMap<String, String>();  | 
|         packageParams.put("appId", wxPayService.getConfig().getAppId());  | 
|         packageParams.put("timeStamp", payResultDTO.getTimeStamp());  | 
|         packageParams.put("nonceStr", payResultDTO.getNonce());  | 
|         packageParams.put("package", payResultDTO.getPrepayId());  | 
|         packageParams.put("signType", "MD5");  | 
|         String packageSign = WXPayUtil.generateSignature(packageParams, wxPayService.getConfig().getMchKey());  | 
|         return  packageSign;  | 
|     }  | 
|   | 
|     /**  | 
|      * 生成安卓APP签名  | 
|      * @param payResultDTO  | 
|      * @return  | 
|      * @throws Exception  | 
|      */  | 
|     private String geAnroidSign(PayResultDTO payResultDTO) throws Exception {  | 
|         Map<String, String> packageParams = new HashMap<String, String>();  | 
|         packageParams.put("appid", wxPayService.getConfig().getAppId());  | 
|         packageParams.put("partnerid", wxPayService.getConfig().getMchId());  | 
|         packageParams.put("prepayid", payResultDTO.getPrepayId());  | 
|         packageParams.put("package", payResultDTO.getExtra());  | 
|         packageParams.put("noncestr", payResultDTO.getNonce());  | 
|         packageParams.put("timestamp", payResultDTO.getTimeStamp());  | 
|         String packageSign = WXPayUtil.generateSignature(packageParams, wxPayService.getConfig().getMchKey());  | 
|         return  packageSign;  | 
|     }  | 
|   | 
|     /**  | 
|      * 微信预支付  | 
|      *  | 
|      * @param wxPayUnifiedOrderRequest  | 
|      * @param payParamDTO  | 
|      * @return  | 
|      */  | 
|     public Result<PayResultDTO> pay(WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest, PayParamDTO payParamDTO) {  | 
|         Result<PayResultDTO> res=new Result<>();  | 
|         PayResultDTO payResultDTO = new PayResultDTO();  | 
|         try {  | 
|             String userId = request.getHeader("userId");  | 
|   | 
|             WxPayUnifiedOrderResult result = wxPayService.unifiedOrder(wxPayUnifiedOrderRequest);  | 
|             PayInfo payInfo = new PayInfo();  | 
|             payInfo.setOrderId(result.getPrepayId());  | 
|             payInfo.setCreateUserId(userId);  | 
|   | 
|             if(businessUtil.isApp(request.getHeader("clientType"))){  | 
|                 //需要服务费  | 
|                 payInfo.setMoney(businessUtil.changeMoney(payParamDTO.getMoney()));  | 
|                 payInfo.setFee(businessUtil.changeMoney(payParamDTO.getFee()));  | 
|             }else {  | 
|                 payInfo.setMoney(payParamDTO.getTotalFee().toString());  | 
|             }  | 
|   | 
|             AccountInfo accountInfo1 =accountService.findByUserId(userId);  | 
|   | 
|             if (accountInfo1 == null) {  | 
|                 return Result.error(-1, "账户不存在");  | 
|             }  | 
|   | 
|             payInfo.setAccountId(accountInfo1.getAccountId());  | 
|             payInfo.setPayType(PayEnum.待支付.getValue());  | 
|             payInfo.setOpenId(payParamDTO.getOpenid());  | 
|             payInfo.setStatus(PayEnum.充值.getValue());  | 
|             payInfo.setPayOrderId(payParamDTO.getOutTradeNo());  | 
|             payService.addPay(payInfo);  | 
|   | 
|             PayInfoLog payInfoLog=new PayInfoLog();  | 
|             BeanUtil.copyProperties(payInfo,payInfoLog);  | 
|             payInfoLog.setAccount(accountInfo1.getAccountName());  | 
|             payInfoLog.setAccountClass(PayEnum.微信.getValue());  | 
|             payInfoLog.setPayType(PayEnum.充值交易.getValue());  | 
|             payInfoLogService.add(payInfoLog);  | 
|   | 
|             payResultDTO.setNonce(payParamDTO.getNonceStr());  | 
|             payResultDTO.setTimeStamp(Convert.toStr(DateUtil.currentSeconds()));  | 
|             payResultDTO.setMchId(wxPayService.getConfig().getMchId());  | 
|   | 
|             if(businessUtil.isWeb(payParamDTO.getClientType())){  | 
|                 payResultDTO.setPrepayId("prepay_id="+result.getPrepayId());  | 
|                 payResultDTO.setSign(geWebSign(payResultDTO));  | 
|             }else if(businessUtil.isApp(payParamDTO.getClientType())){  | 
|                 payResultDTO.setPrepayId(result.getPrepayId());  | 
|                 payResultDTO.setExtra("Sign=WXPay");  | 
|                 payResultDTO.setSign(geAnroidSign(payResultDTO));  | 
|             }  | 
|             payResultDTO.setAppId(wxPayService.getConfig().getAppId());  | 
|             payResultDTO.setPayOrderId(payInfo.getPayOrderId());  | 
|             res.setData(payResultDTO);  | 
|             return res;  | 
|         } catch (Exception e) {  | 
|             ExceptionUtils.err("微信预支付失败",e);  | 
|         }  | 
|         return res;  | 
|     }  | 
|   | 
|     /**  | 
|      * 微信回调  | 
|      *  | 
|      */  | 
|     public String payBack(String xmlResult) {  | 
|         String payOrderId="";  | 
|         boolean lock=false;  | 
|         try {  | 
|             //记录微信回调日志  | 
|             record(xmlResult);  | 
|             WxPayOrderNotifyResult result = wxPayService.parseOrderNotifyResult(xmlResult);  | 
|             payOrderId = result.getOutTradeNo();  | 
|             // 锁+去重  | 
|             if(redisUtil.setnx(Constants.REDIS_PAY_KEY+"wx:payback:"+payOrderId,payOrderId)) {  | 
|                 lock=true;  | 
|                 PayInfo payInfo = payInfoMapper.selectByPrimaryKey(payOrderId);  | 
|                 if (payInfo != null) {  | 
|                     if (payInfo.getStatus().equals(PayEnum.已支付.getValue())) {  | 
|                         return WxPayNotifyResponse.success("处理成功!");  | 
|                     }else{  | 
|                         Map map = new HashMap();  | 
|                         map.put("userId", payInfo.getCreateUserId());  | 
|                         map.put("money", payInfo.getMoney());  | 
|                         map.put("status", PayEnum.已支付.getValue());  | 
|                         map.put("payOrderId", payInfo.getPayOrderId());  | 
|                         map.put("fee",payInfo.getFee());  | 
|                         payService.webChatRechargeCallback(map);  | 
|                     }  | 
|                 }  | 
|             }  | 
|             return WxPayNotifyResponse.success("处理成功!");  | 
|         } catch (Exception e) {  | 
|             log.error("微信回调失败,订单:"+payOrderId, e);  | 
|             throw new WxPayNotifyResponseException(WxPayNotifyResponse.fail(e.getMessage()));  | 
|         }finally {  | 
|             if(lock) {  | 
|                 redisUtil.del(Constants.REDIS_PAY_KEY+"wx:payback:"+payOrderId);  | 
|             }  | 
|         }  | 
|     }  | 
|   | 
|   | 
|     private void record(String xmlResult){  | 
|         WxPayOrderNotifyResult res= WxPayOrderNotifyResult.fromXML(xmlResult);  | 
|         PayWxRecord payWxRecord=new PayWxRecord();  | 
|         BeanUtils.copyProperties(res,payWxRecord);  | 
|         payWxRecord.setCreateTime(DateUtil.now());  | 
|         payWxRecordMapper.insertSelective(payWxRecord);  | 
|     }  | 
|   | 
|   | 
| //    @Scheduled(cron = "${wx.pay.cron}")  | 
| //    @Async  | 
| //    public void syncPay(){  | 
| //        log.trace("********定时修复支付订单开始【每1分钟执行1次】*********");  | 
| //        Example example=new Example(PayInfo.class);  | 
| //        Example.Criteria criteria = example.createCriteria();  | 
| //        criteria.andEqualTo("payType",PayEnum.充值.getValue());  | 
| //        criteria.andEqualTo("status",PayEnum.待支付.getValue());  | 
| //        criteria.andCondition("IFNULL(check_num,0)<2");  | 
| //        criteria.andCondition("to_days(create_time) = to_days(now())");  | 
| //        List<PayInfo> payInfos = payInfoMapper.selectByExample(example);  | 
| //  | 
| //        if(CollUtil.isNotEmpty(payInfos)){  | 
| //            for (PayInfo payInfo : payInfos) {  | 
| //                String createTime = payInfo.getCreateTime();  | 
| //                String date=DateUtil.now();  | 
| //                long between = DateUtil.between(DateUtil.parse(createTime,DateUtils.DATE_FORMAT_YMDHMS), DateUtil.parse(date,DateUtils.DATE_FORMAT_YMDHMS), DateUnit.MINUTE);  | 
| //                //3分钟后进行查询  | 
| //                if(between<3){  | 
| //                    continue;  | 
| //                }  | 
| //                String payOrderId = payInfo.getPayOrderId();  | 
| //                Integer checkNum = payInfo.getCheckNum();  | 
| //                if(checkNum==null){  | 
| //                    checkNum=0;  | 
| //                }  | 
| //                WxPayOrderQueryResult wxPayOrderQueryResult = null;  | 
| //                boolean lock=false;  | 
| //                try {  | 
| //                    wxPayOrderQueryResult = wxPayService.queryOrder(null, payOrderId);  | 
| //                    String returnCode = wxPayOrderQueryResult.getReturnCode();  | 
| //                    String resultCode = wxPayOrderQueryResult.getResultCode();  | 
| //                    if("SUCCESS".equals(returnCode)&&"SUCCESS".equals(resultCode)){  | 
| //                        //SUCCESS—支付成功,REFUND—转入退款,NOTPAY—未支付,CLOSED—已关闭,REVOKED—已撤销(刷卡支付),USERPAYING--用户支付中,PAYERROR--支付失败(其他原因,如银行返回失败)  | 
| //                        String tradeState = wxPayOrderQueryResult.getTradeState();  | 
| //                        log.trace("充值交易流水号:{},交易状态:{}",payOrderId,tradeState);  | 
| //                        if("SUCCESS".equals(tradeState)){  | 
| //                            // 锁+去重  | 
| //                            if(redisUtil.setnx(Constants.REDIS_PAY_KEY+"wx:payback:"+payOrderId,payOrderId)) {  | 
| //                                lock=true;  | 
| //                                PayInfo payInfo2 = payInfoMapper.selectByPrimaryKey(payOrderId);  | 
| //                                if (payInfo2 != null) {  | 
| //                                    if (payInfo2.getStatus().equals(PayEnum.已支付.getValue())) {  | 
| //                                        continue;  | 
| //                                    }else{  | 
| //                                        Map map = new HashMap();  | 
| //                                        map.put("userId", payInfo2.getCreateUserId());  | 
| //                                        map.put("money", payInfo2.getMoney());  | 
| //                                        map.put("status", PayEnum.已支付.getValue());  | 
| //                                        map.put("payOrderId", payInfo2.getPayOrderId());  | 
| //                                        map.put("fee", payInfo2.getFee());  | 
| //                                        payService.webChatRechargeCallback(map);  | 
| //                                        log.info("支付订单:{}已自动修复成功",payOrderId);  | 
| //                                    }  | 
| //                                }  | 
| //                            }  | 
| //                        }else{  | 
| //                            PayInfo payInfo2=new PayInfo();  | 
| //                            payInfo2.setPayOrderId(payInfo.getPayOrderId());  | 
| //                            checkNum=2;  | 
| //                            payInfo2.setCheckNum(checkNum);  | 
| //                            payInfoMapper.updateByPrimaryKeySelective(payInfo2);  | 
| //                        }  | 
| //                    }  | 
| //                } catch (WxPayException e) {  | 
| //                    log.warn("主动调用微信支付查询出现异常");  | 
| //                    PayInfo payInfo2=new PayInfo();  | 
| //                    payInfo2.setPayOrderId(payInfo.getPayOrderId());  | 
| //                    checkNum=2;  | 
| //                    payInfo2.setCheckNum(checkNum);  | 
| //                    payInfoMapper.updateByPrimaryKeySelective(payInfo2);  | 
| //                }finally {  | 
| //                    if(lock) {  | 
| //                        redisUtil.del(Constants.REDIS_PAY_KEY+"wx:payback:"+payOrderId);  | 
| //                    }  | 
| //                }  | 
| //            }  | 
| //        }  | 
| //        log.trace("********定时修复支付订单完成【每3分钟执行1次】*********");  | 
| //  | 
| //    }  | 
|   | 
|     /**  | 
|      * 修复支付  | 
|      * @param payOrderId  | 
|      */  | 
|     public Result payFix(String payOrderId) {  | 
|         PayInfo payInfo2 = payInfoMapper.selectByPrimaryKey(payOrderId);  | 
|         if (payInfo2 != null) {  | 
|             if (payInfo2.getStatus().equals(PayEnum.已支付.getValue())) {  | 
|                 return Result.error("当前支付订单已支付成功");  | 
|             }else{  | 
|                 Map map = new HashMap();  | 
|                 map.put("userId", payInfo2.getCreateUserId());  | 
|                 map.put("money", payInfo2.getMoney());  | 
|                 map.put("status", PayEnum.已支付.getValue());  | 
|                 map.put("payOrderId", payInfo2.getPayOrderId());  | 
|                 map.put("fee", payInfo2.getFee());  | 
|                 payService.webChatRechargeCallback(map);  | 
|                 return Result.success();  | 
|             }  | 
|         }  | 
|         return Result.error("当前支付订单号不存在");  | 
|   | 
|     }  | 
| }  |