| package cc.mrbird.febs.pay.controller; | 
|   | 
| import cc.mrbird.febs.common.entity.FebsResponse; | 
| import cc.mrbird.febs.common.enumerates.*; | 
| import cc.mrbird.febs.common.properties.XcxProperties; | 
| import cc.mrbird.febs.common.utils.RedisUtils; | 
| import cc.mrbird.febs.common.utils.SpringContextHolder; | 
| import cc.mrbird.febs.mall.dto.RechargeWalletMessageSendDto; | 
| import cc.mrbird.febs.mall.entity.*; | 
| import cc.mrbird.febs.mall.mapper.*; | 
| import cc.mrbird.febs.mall.service.IApiMallMemberService; | 
| import cc.mrbird.febs.mall.service.IApiMallMemberWalletService; | 
| import cc.mrbird.febs.mall.service.IMallMoneyFlowService; | 
| import cc.mrbird.febs.pay.model.NotifyData; | 
| import cc.mrbird.febs.pay.service.IXcxPayService; | 
| import cc.mrbird.febs.pay.service.WxFaPiaoService; | 
| import cc.mrbird.febs.pay.util.Signature; | 
| import cc.mrbird.febs.pay.util.Util; | 
| import cc.mrbird.febs.pay.util.WechatConfigure; | 
| import cc.mrbird.febs.rabbit.producter.AgentProducer; | 
| import cn.hutool.core.date.DateUtil; | 
| import cn.hutool.core.util.ObjectUtil; | 
| import cn.hutool.json.JSONObject; | 
| import cn.hutool.json.JSONUtil; | 
| import com.wechat.pay.contrib.apache.httpclient.notification.NotificationRequest; | 
| import lombok.extern.slf4j.Slf4j; | 
| import org.springframework.beans.BeanUtils; | 
| import org.springframework.beans.factory.annotation.Autowired; | 
| import org.springframework.transaction.annotation.Transactional; | 
| import org.springframework.web.bind.annotation.RequestBody; | 
| import org.springframework.web.bind.annotation.RequestMapping; | 
| import org.springframework.web.bind.annotation.RestController; | 
|   | 
| import javax.servlet.ServletOutputStream; | 
| import javax.servlet.http.HttpServletRequest; | 
| import javax.servlet.http.HttpServletResponse; | 
| import java.io.BufferedReader; | 
| import java.io.IOException; | 
| import java.math.BigDecimal; | 
| import java.math.RoundingMode; | 
| import java.nio.charset.StandardCharsets; | 
| import java.security.InvalidKeyException; | 
| import java.security.NoSuchAlgorithmException; | 
| import java.security.SignatureException; | 
| import java.text.ParseException; | 
| import java.util.Date; | 
| import java.util.HashMap; | 
| import java.util.Map; | 
|   | 
| @Slf4j | 
| @RestController | 
| @RequestMapping(value = "/api/xcxPay") | 
| public class XcxPayController { | 
|   | 
|     @Autowired | 
|     MallOrderInfoMapper mallOrderInfoMapper; | 
|     @Autowired | 
|     MallMoneyFlowMapper mallMoneyFlowMapper; | 
|     @Autowired | 
|     MallMemberWalletMapper mallMemberWalletMapper; | 
|     @Autowired | 
|     MallMemberMapper mallMemberMapper; | 
|     @Autowired | 
|     DataDictionaryCustomMapper dataDictionaryCustomMapper; | 
|     @Autowired | 
|     IMallMoneyFlowService mallMoneyFlowService; | 
|     @Autowired | 
|     RedisUtils redisUtils; | 
|     @Autowired | 
|     private IApiMallMemberWalletService memberWalletService; | 
|     @Autowired | 
|     private IApiMallMemberService mallMemberService; | 
|     @Autowired | 
|     private MallAgentRecordMapper mallAgentRecordMapper; | 
|     @Autowired | 
|     private AgentProducer agentProducer; | 
|   | 
|     @Autowired | 
|     private IXcxPayService iXcxPayService; | 
|   | 
|     @Autowired | 
|     private WxFaPiaoService wxFaPiaoService; | 
|   | 
|     private final XcxProperties xcxProperties = SpringContextHolder.getBean(XcxProperties.class); | 
|     /** | 
|      * 微信充值回调接口 | 
|      */ | 
|     @Transactional(rollbackFor = Exception.class) | 
|     @RequestMapping(value = "/rechargeCallBack") | 
|     public void rechargeCallBack(HttpServletResponse response, HttpServletRequest request) throws IOException { | 
|         log.info("微信充值回调start...."); | 
|   | 
|         // 获取输入参数 | 
|         String inputLine; | 
|         StringBuffer notityXml = new StringBuffer(); | 
|         String resXml = ""; | 
|   | 
| //        String attrStr = "{'rechargeNo':"+rechargeNo+",'memberId':"+mallMember.getId()+"}"; | 
|         String attrStr = ""; | 
|   | 
|         FebsResponse threadResult = new FebsResponse(); | 
|         try { | 
|             while ((inputLine = request.getReader().readLine()) != null) { | 
|                 notityXml.append(inputLine); | 
|             } | 
|             request.getReader().close(); | 
|             log.info("notityXml ---- :{} ", notityXml); | 
|   | 
|   | 
|             // XMl转对象 | 
|             Object bb = Util.getObjectFromXML(notityXml.toString(), NotifyData.class); | 
|             NotifyData data = new NotifyData(); | 
|             BeanUtils.copyProperties(bb,data); | 
|             log.info("----return_code = {}", data.getReturn_code()); | 
|             // 返回状态码 SUCCESS/FAIL | 
|             if (WechatConfigure.CODE_SUCCESS.equals(data.getReturn_code())) { | 
|                 attrStr = data.getAttach(); | 
|                 JSONObject jsonObject = JSONUtil.parseObj(attrStr); | 
|                 String rechargeNo = (String) jsonObject.get("rechargeNo"); | 
|                 Integer type = (Integer) jsonObject.get("type"); | 
|                 Long memberId = Long.parseLong(jsonObject.get("memberId").toString()); | 
|                 Long agentApplyId = Long.parseLong(jsonObject.get("agentApplyId").toString()); | 
|                 // 检验订单状态 | 
|                 MallMoneyFlow mallMoneyFlow = mallMoneyFlowMapper.selectOneByOrderNoAndMemberId(rechargeNo,memberId); | 
|                 // 校验签名 | 
| //                String paySecret = WechatConfigure.WECHARPAY_SECRET; | 
|                 String paySecret = xcxProperties.getWecharpaySecret(); | 
|                 if (Signature.checkIsSignValidFromResponseString(notityXml.toString(),paySecret)) { | 
|                     // 校验业务结果 | 
|                     if (WechatConfigure.CODE_SUCCESS.equals(data.getResult_code())) { | 
|                         // 返回SUCCESS报文 | 
|                         resXml = WechatConfigure.RESULT_XML_SUCCESS; | 
|                         // 支付费用 | 
|                         Double total_fee = Double.parseDouble(data.getTotal_fee()); | 
|                         // 商户订单号 | 
|                         String payNum = data.getOut_trade_no(); | 
|   | 
|                         log.info("支付回调关键信息---total_fee:{},payNum:{},rechargeNo:{}", total_fee, payNum, rechargeNo); | 
|                         // 订单ID | 
|                         BigDecimal payMoney = new BigDecimal(total_fee).divide(new BigDecimal(100), 2, | 
|                                 RoundingMode.HALF_UP); | 
|   | 
|                         if (ObjectUtil.isNotEmpty(mallMoneyFlow)) { | 
|                             log.debug("检查支付金额payMoney={},mallMoneyFlow.getPayMoney()={}", payMoney, mallMoneyFlow.getAmount()); | 
|                             //合伙人申请的充值,要更新会员状态为FIRST_LEVEL | 
|                             if(2 == type){ | 
|                                 log.info("微信充值回调" + agentApplyId); | 
|                                 MallAgentRecord mallAgentRecord = mallAgentRecordMapper.selectById(agentApplyId); | 
|                                 mallMemberService.updateMemberAgent(agentApplyId,mallAgentRecord.getAgentLevel()); | 
|                             } | 
|                             memberWalletService.addBalance(payMoney,memberId); | 
|                             mallMoneyFlow.setStatus(2); | 
|                             mallMoneyFlowMapper.updateById(mallMoneyFlow); | 
|   | 
|                             /** | 
|                              * 充值赠送金额 | 
|                              */ | 
|                             DataDictionaryCustom giveStateDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode( | 
|                                     DataDictionaryEnum.GIVE_STATE.getType(), | 
|                                     DataDictionaryEnum.GIVE_STATE.getCode()); | 
|   | 
|                             DataDictionaryCustom giveAmountDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode( | 
|                                     DataDictionaryEnum.GIVE_AMOUNT.getType(), | 
|                                     DataDictionaryEnum.GIVE_AMOUNT.getCode()); | 
|   | 
|                             DataDictionaryCustom chargeAmountDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode( | 
|                                     DataDictionaryEnum.CHARGE_AMOUNT.getType(), | 
|                                     DataDictionaryEnum.CHARGE_AMOUNT.getCode()); | 
|                             /** | 
|                              * 普通充值 | 
|                              * 开启了充值赠送 | 
|                              * 系统设置的赠送金额和充值金额不为空 | 
|                              * 充值金额大于等于系统设置的充值金额 | 
|                              */ | 
|                             if(1 == type | 
|                                     && ObjectUtil.isNotEmpty(giveStateDic) | 
|                                     && "1".equals(giveStateDic.getValue()) | 
|                                     && ObjectUtil.isNotEmpty(giveAmountDic) | 
|                                     && ObjectUtil.isNotEmpty(chargeAmountDic)){ | 
|                                 BigDecimal giveAmount = ObjectUtil.isEmpty(giveAmountDic.getValue()) ? | 
|                                         BigDecimal.ZERO : | 
|                                         new BigDecimal(giveAmountDic.getValue()).abs().setScale(2,BigDecimal.ROUND_DOWN); | 
|                                 BigDecimal chargeAmount = ObjectUtil.isEmpty(chargeAmountDic.getValue()) ? | 
|                                         BigDecimal.ZERO : | 
|                                         new BigDecimal(chargeAmountDic.getValue()).abs().setScale(2,BigDecimal.ROUND_DOWN); | 
|                                 if(payMoney.compareTo(chargeAmount) >= 0){ | 
|                                     mallMoneyFlowService.addMoneyFlow( | 
|                                             memberId, | 
|                                             giveAmount, | 
|                                             MoneyFlowTypeEnum.RECHARGE_SEND.getValue(), | 
|                                             rechargeNo+"ZS", | 
|                                             FlowTypeEnum.BALANCE.getValue(), | 
|                                             "充值赠送金额", | 
|                                             2); | 
|   | 
|                                     memberWalletService.addBalance(giveAmount,memberId); | 
|                                 } | 
|                             } | 
|   | 
|                             RechargeWalletMessageSendDto rechargeWalletMessageSendDto = new RechargeWalletMessageSendDto(); | 
|                             rechargeWalletMessageSendDto.setRechargeNo(rechargeNo); | 
|                             rechargeWalletMessageSendDto.setRechargeAmount(payMoney.toString()); | 
|   | 
|                             MallMemberWallet mallMemberWallet = mallMemberWalletMapper.selectWalletByMemberId(memberId); | 
|                             rechargeWalletMessageSendDto.setBalance(mallMemberWallet.getBalance().toString()); | 
|                             rechargeWalletMessageSendDto.setCreateTime(DateUtil.now()); | 
|                             rechargeWalletMessageSendDto.setOpenId(mallMemberMapper.selectById(memberId).getOpenId()); | 
|                             DataDictionaryCustom dataDictionaryCustom = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(DataDictionaryEnum.WX_TEMPLATE_ID_TWO.getType(), DataDictionaryEnum.WX_TEMPLATE_ID_TWO.getCode()); | 
|                             rechargeWalletMessageSendDto.setTemplateId(dataDictionaryCustom.getValue()); | 
|                             iXcxPayService.rechargeWalletMessageSend(rechargeWalletMessageSendDto); | 
|                             threadResult.success().message("充值成功"); | 
|                         } else { | 
|                             log.info("充值失败", attrStr); | 
|                         } | 
|                     } else { | 
|                         log.info("微信标识业务是失败"); | 
|                         threadResult.fail().message("查询支付信息失败,请联系客服或者刷新支付信息(错误码:001)"); | 
| //                        resXml = AppConstance.RESULT_XML_FAIL.replace(ERRORMSG, "微信标识业务是失败"); | 
|                     } | 
|                 } else { | 
|                     log.info("无效签名"); | 
|                     threadResult.fail().message("查询支付信息失败,请联系客服或者刷新支付信息(错误码:002)"); | 
| //                    resXml = AppConstance.RESULT_XML_FAIL.replace(ERRORMSG, "微信标识业务是失败"); | 
|                 } | 
|             } else { | 
|                 log.info("通信标识失败"); | 
|                 threadResult.fail().message("查询支付信息失败,请联系客服或者刷新支付信息(错误码:003)"); | 
| //                resXml = AppConstance.RESULT_XML_FAIL.replace(ERRORMSG, "通信标识失败"); | 
|             } | 
|         } catch (Exception e) { | 
|             log.error("支付回调签名错误", e); | 
|             threadResult.fail().message("查询支付信息失败,请联系客服或者刷新支付信息(错误码:004)"); | 
| //            resXml = AppConstance.RESULT_XML_FAIL.replace(ERRORMSG, "支付回调签名错误"); | 
|         } finally { | 
|             // 通知线程消息 | 
| //            PayThreadPool.notifyThread(Integer.valueOf(orderId), threadResult); | 
|             sendResultBack(response, resXml); | 
|         } | 
|         return; | 
|   | 
|     } | 
|   | 
| //    public static void main(String[] args) { | 
| //        String attach="{'rechargeNo':CZ_2022083117160259880,'memberId':47}"; | 
| //        JSONObject jsonObject = JSONUtil.parseObj(attach); | 
| //        String rechargeNo = (String) jsonObject.get("rechargeNo"); | 
| //        Long memberId = Long.parseLong(jsonObject.get("memberId").toString()); | 
| //        System.out.println(memberId); | 
| //        System.out.println(rechargeNo); | 
| //    } | 
|     /** | 
|      * 微信电子发票回调接口 | 
|      * POST方式回调 | 
|      * @return | 
|      */ | 
|     @Transactional(rollbackFor = Exception.class) | 
|     @RequestMapping(value = "/fapiaoCallBack") | 
|     public Map<String, Object> fapiaoCallBack(HttpServletRequest request, @RequestBody Map<String, Object> requestBody) { | 
|         return wxFaPiaoService.fapiaoCallBack(request,requestBody); | 
|   | 
|     } | 
|   | 
|     /** | 
|      * 微信支付回调接口 | 
|      */ | 
|     @Transactional(rollbackFor = Exception.class) | 
|     @RequestMapping(value = "/wxpayCallback") | 
|     public void payCallBack(HttpServletResponse response, HttpServletRequest request) throws IOException { | 
|         log.info("微信支付回调start...."); | 
|   | 
|         // 获取输入参数 | 
|         String inputLine; | 
|         StringBuffer notityXml = new StringBuffer(); | 
|         String resXml = ""; | 
|         String orderId = ""; | 
|   | 
|         FebsResponse threadResult = new FebsResponse(); | 
|         try { | 
|             while ((inputLine = request.getReader().readLine()) != null) { | 
|                 notityXml.append(inputLine); | 
|             } | 
|             request.getReader().close(); | 
|             log.info("notityXml ---- :{} ", notityXml); | 
|   | 
|   | 
|             // XMl转对象 | 
|             Object bb = Util.getObjectFromXML(notityXml.toString(), NotifyData.class); | 
|             NotifyData data = new NotifyData(); | 
|             BeanUtils.copyProperties(bb,data); | 
|             log.info("----return_code = {}", data.getReturn_code()); | 
|   | 
|             // 返回状态码 SUCCESS/FAIL | 
|             if (WechatConfigure.CODE_SUCCESS.equals(data.getReturn_code())) { | 
|   | 
|                 orderId = data.getAttach(); | 
|                 // 检验订单状态 | 
|                 MallOrderInfo order = mallOrderInfoMapper.selectById(Long.valueOf(orderId)); | 
|   | 
|                 // 校验签名 | 
| //                String paySecret = WechatConfigure.WECHARPAY_SECRET; | 
|                 String paySecret = xcxProperties.getWecharpaySecret(); | 
|                 if (Signature.checkIsSignValidFromResponseString(notityXml.toString(),paySecret)) { | 
|                     // 校验业务结果 | 
|                     if (WechatConfigure.CODE_SUCCESS.equals(data.getResult_code())) { | 
|                         // 返回SUCCESS报文 | 
|                         resXml = WechatConfigure.RESULT_XML_SUCCESS; | 
|                         // 支付费用 | 
|                         Double total_fee = Double.parseDouble(data.getTotal_fee()); | 
|                         //微信支付订单号 | 
|                         String transaction_id = data.getTransaction_id(); | 
|                         // 商户订单号 | 
|                         String payNum = data.getOut_trade_no(); | 
|   | 
|                         log.info("支付回调关键信息---total_fee:{},payNum:{},orderId:{}", total_fee, payNum, orderId); | 
|                         // 订单ID | 
|                         BigDecimal payMoney = new BigDecimal(total_fee).divide(new BigDecimal(100), 2, | 
|                                 RoundingMode.HALF_UP); | 
|   | 
|   | 
|                         if (order != null && OrderStatusEnum.WAIT_PAY.getValue() == order.getStatus()) { | 
|                             log.debug("检查支付金额payMoney={},order.getPayMoney()={}", payMoney, order.getAmount()); | 
|                             order.setStatus(OrderStatusEnum.WAIT_SHIPPING.getValue()); | 
|                             order.setPayResult("1"); | 
|                             order.setPayTime(new Date()); | 
|                             order.setDeliveryState(OrderDeliveryStateEnum.DELIVERY_WAIT.getValue()); | 
|                             order.setPayOrderNo(transaction_id); | 
|                             mallOrderInfoMapper.updateById(order); | 
|   | 
|                             agentProducer.sendOrderCoupon(order.getId()); | 
| //                            agentProducer.sendGetScoreMsg(order.getId()); | 
|   | 
|                             mallMoneyFlowService.addMoneyFlow( | 
|                                     order.getMemberId(), | 
|                                     order.getAmount().negate(), | 
|                                     MoneyFlowTypeEnum.WECHAT_PAY.getValue(), | 
|                                     order.getOrderNo(), | 
|                                     FlowTypeEnum.WECHAT.getValue(), | 
|                                     "微信支付", | 
|                                     2); | 
|                             threadResult.success().message("支付成功"); | 
|                         } else { | 
|                             log.info("订单状态不为待付款,order status=", order.getStatus()); | 
|                         } | 
|                     } else { | 
|                         log.info("微信标识业务是失败"); | 
|                         threadResult.fail().message("查询支付信息失败,请联系客服或者刷新支付信息(错误码:001)"); | 
| //                        resXml = AppConstance.RESULT_XML_FAIL.replace(ERRORMSG, "微信标识业务是失败"); | 
|                     } | 
|                 } else { | 
|                     log.info("无效签名"); | 
|                     threadResult.fail().message("查询支付信息失败,请联系客服或者刷新支付信息(错误码:002)"); | 
| //                    resXml = AppConstance.RESULT_XML_FAIL.replace(ERRORMSG, "微信标识业务是失败"); | 
|                 } | 
|             } else { | 
|                 log.info("通信标识失败"); | 
|                 threadResult.fail().message("查询支付信息失败,请联系客服或者刷新支付信息(错误码:003)"); | 
| //                resXml = AppConstance.RESULT_XML_FAIL.replace(ERRORMSG, "通信标识失败"); | 
|             } | 
|         } catch (Exception e) { | 
|             log.error("支付回调签名错误", e); | 
|             threadResult.fail().message("查询支付信息失败,请联系客服或者刷新支付信息(错误码:004)"); | 
| //            resXml = AppConstance.RESULT_XML_FAIL.replace(ERRORMSG, "支付回调签名错误"); | 
|         } finally { | 
|             // 通知线程消息 | 
| //            PayThreadPool.notifyThread(Integer.valueOf(orderId), threadResult); | 
|             sendResultBack(response, resXml); | 
|         } | 
|         return; | 
|   | 
|     } | 
|   | 
|     private void sendResultBack(HttpServletResponse response, String resXml) throws IOException { | 
|         log.info("返回微信数据={}", resXml); | 
|         ServletOutputStream out = response.getOutputStream(); | 
|         out.write(resXml.getBytes()); | 
|         out.flush(); | 
|         out.close(); | 
|     } | 
|   | 
| } |