Merge branches 'master' and 'master' of https://gitee.com/xiaochen991015/xizang
New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <project xmlns="http://maven.apache.org/POM/4.0.0" |
| | | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
| | | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
| | | <modelVersion>4.0.0</modelVersion> |
| | | <parent> |
| | | <groupId>com.ruoyi</groupId> |
| | | <artifactId>ruoyi</artifactId> |
| | | <version>3.8.6</version> |
| | | </parent> |
| | | <description> |
| | | 银行接口模块 |
| | | </description> |
| | | <groupId>org.taxi591</groupId> |
| | | <artifactId>bankapi</artifactId> |
| | | <version>1.0.0-SNAPSHOT</version> |
| | | <properties> |
| | | <httpclient_version>4.5.2</httpclient_version> |
| | | </properties> |
| | | <dependencies> |
| | | <dependency> |
| | | <groupId>com.ruoyi</groupId> |
| | | <artifactId>ruoyi-framework</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.ruoyi</groupId> |
| | | <artifactId>ruoyi-common</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.apache.httpcomponents</groupId> |
| | | <artifactId>httpclient</artifactId> |
| | | <version>${httpclient_version}</version> |
| | | </dependency> |
| | | </dependencies> |
| | | <build> |
| | | <plugins> |
| | | <plugin> |
| | | <groupId>org.springframework.boot</groupId> |
| | | <artifactId>spring-boot-maven-plugin</artifactId> |
| | | <version>2.5.15</version> |
| | | <configuration> |
| | | <fork>true</fork> <!-- 如果没有该配置,devtools不会生效 --> |
| | | </configuration> |
| | | <executions> |
| | | <execution> |
| | | <goals> |
| | | <goal>repackage</goal> |
| | | </goals> |
| | | </execution> |
| | | </executions> |
| | | </plugin> |
| | | <plugin> |
| | | <groupId>org.apache.maven.plugins</groupId> |
| | | <artifactId>maven-war-plugin</artifactId> |
| | | <version>3.1.0</version> |
| | | <configuration> |
| | | <failOnMissingWebXml>false</failOnMissingWebXml> |
| | | <warName>${project.artifactId}</warName> |
| | | </configuration> |
| | | </plugin> |
| | | </plugins> |
| | | <finalName>${project.artifactId}</finalName> |
| | | </build> |
| | | </project> |
New file |
| | |
| | | package com.taxi591.bankapi; |
| | | |
| | | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
| | | import org.springframework.boot.context.properties.EnableConfigurationProperties; |
| | | import org.springframework.context.annotation.ComponentScan; |
| | | import org.springframework.context.annotation.Configuration; |
| | | |
| | | @Configuration |
| | | @EnableConfigurationProperties({BankProperties.class}) |
| | | @ConditionalOnProperty(value = BankProperties.ENBALE_PREFIX, matchIfMissing = true) |
| | | @ComponentScan("com.taxi591.bankapi.service") |
| | | public class BankConfig { |
| | | |
| | | |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package com.taxi591.bankapi; |
| | | |
| | | import lombok.Data; |
| | | import org.springframework.boot.context.properties.ConfigurationProperties; |
| | | |
| | | import static com.taxi591.bankapi.BankProperties.PREFIX; |
| | | |
| | | @Data |
| | | @ConfigurationProperties(prefix = PREFIX) |
| | | public class BankProperties { |
| | | |
| | | public static final String PREFIX = "com.taxi591.bank"; |
| | | |
| | | public static final String ENBALE_PREFIX = PREFIX+".enable"; |
| | | |
| | | private Boolean enable = true; |
| | | |
| | | |
| | | private String baseUrl="http://hello.enjoy.abchina.com"; |
| | | |
| | | /** |
| | | * 证书路径 |
| | | */ |
| | | private String pfxPath; |
| | | /** |
| | | * 密码 |
| | | */ |
| | | private String keystorePassword; |
| | | |
| | | /** |
| | | * 公钥路径 |
| | | */ |
| | | private String cerPath; |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package com.taxi591.bankapi.dto; |
| | | |
| | | import com.alibaba.fastjson2.JSON; |
| | | import lombok.Data; |
| | | |
| | | import java.io.Serializable; |
| | | |
| | | /** |
| | | * 直连商户平台缴费销账输入对象,需要转换成json串发送给第三方系统 |
| | | * @author DELL |
| | | * |
| | | */ |
| | | @Data |
| | | public class ChargeBillRequest implements Serializable { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** 格式 */ |
| | | private String format; |
| | | |
| | | /** 消息 */ |
| | | private Message message; |
| | | |
| | | @Override |
| | | public String toString() { |
| | | return "ChargeBillRequest[format=" + format + ",message=" + message.toString() + "]"; |
| | | } |
| | | |
| | | /** |
| | | * |
| | | * 账单查询内部消息对象实体message内部类 |
| | | * |
| | | */ |
| | | @Data |
| | | public class Message implements Serializable { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** 消息头部 */ |
| | | private Head head; |
| | | |
| | | /** 消息体 */ |
| | | private Info info; |
| | | |
| | | @Override |
| | | public String toString() { |
| | | return JSON.toJSONString(this); |
| | | } |
| | | |
| | | /** |
| | | * message子对象head消息头内部类 |
| | | */ |
| | | @Data |
| | | public class Head implements Serializable { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** 渠道编码 */ |
| | | private String channel; |
| | | |
| | | /** 交易码 */ |
| | | private String transCode; |
| | | |
| | | /** 交易上行下送标志位 */ |
| | | private String transFlag; |
| | | |
| | | /** 缴费中心交易序列号 */ |
| | | private String transSeqNum; |
| | | |
| | | /** 时间戳 */ |
| | | private String timeStamp; |
| | | |
| | | /** 4为分行iGoal码 */ |
| | | private String branchCode; |
| | | |
| | | @Override |
| | | public String toString() { |
| | | return JSON.toJSONString(this); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * message子对象info消息实体内部类 |
| | | */ |
| | | @Data |
| | | public class Info implements Serializable { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** 缴费项目编号*/ |
| | | private String epayCode; |
| | | |
| | | /** 第三方商户编号*/ |
| | | private String merchantId; |
| | | |
| | | /** 缴费中心流水号*/ |
| | | private String traceNo; |
| | | |
| | | /** 输入要素1*/ |
| | | private String input1; |
| | | |
| | | /** 输入要素2*/ |
| | | private String input2; |
| | | |
| | | /** 输入要素3*/ |
| | | private String input3; |
| | | |
| | | /** 输入要素4*/ |
| | | private String input4; |
| | | |
| | | /** 输入要素5*/ |
| | | private String input5; |
| | | |
| | | /** 农行16位客户号*/ |
| | | private String userId; |
| | | |
| | | /** 缴费金额计算规则*/ |
| | | private String amtRule; |
| | | |
| | | /** 合并支付的子账单数*/ |
| | | private String payBillCount; |
| | | |
| | | /** 合并支付的子账单累加总金额*/ |
| | | private String payBillAmt; |
| | | |
| | | /** 合并支付的子账单*/ |
| | | private String payBillNo; |
| | | |
| | | /** 套餐名称*/ |
| | | private String optionName; |
| | | |
| | | /** 套餐编码*/ |
| | | private String optionCode; |
| | | |
| | | /** 套餐金额*/ |
| | | private String optionAmt; |
| | | |
| | | /** 支付方式交易码*/ |
| | | private String payType; |
| | | |
| | | /** 缴费支付账号*/ |
| | | private String payAcc; |
| | | |
| | | /** 支付系统流水号*/ |
| | | private String transPaySeq; |
| | | |
| | | /** 支付系统日期*/ |
| | | private String transDate; |
| | | |
| | | /** 支付系统时间*/ |
| | | private String transTime; |
| | | |
| | | /** 会计日期*/ |
| | | private String settleDate; |
| | | |
| | | /** 清算模式*/ |
| | | private String clearType; |
| | | |
| | | /** 缓存域信息*/ |
| | | private String cacheMem; |
| | | |
| | | /** 销账报文重发次数,通过此字段识别销账报文是否为重发的,0表示首次、1表示重发一次,2表示重发2次,最多重发3次*/ |
| | | private String resendTimes; |
| | | |
| | | /** 第三方支付平台商户订单号 第三方平台例如微信支付宝的支付订单号 add 2020-01-13*/ |
| | | private String numOpenMerchantOrder; |
| | | |
| | | |
| | | @Override |
| | | public String toString() { |
| | | return JSON.toJSONString(this); |
| | | } |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | package com.taxi591.bankapi.dto; |
| | | |
| | | import com.alibaba.fastjson2.JSON; |
| | | import lombok.Data; |
| | | |
| | | import java.io.Serializable; |
| | | |
| | | /** |
| | | * 直连商户平台账单销账返回对象 |
| | | * @author DELL |
| | | * |
| | | */ |
| | | @Data |
| | | public class ChargeBillResponse implements Serializable { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** 格式 */ |
| | | private String format; |
| | | |
| | | /** 消息体 */ |
| | | private Message message; |
| | | |
| | | |
| | | public ChargeBillResponse(){ |
| | | |
| | | } |
| | | |
| | | /** |
| | | * 构造函数,通过输入对象,构造返回对象数据信息 |
| | | * @param request |
| | | */ |
| | | public ChargeBillResponse(ChargeBillRequest request) { |
| | | this.setFormat(request.getFormat()); |
| | | this.setMessage(new Message(request.getMessage())); |
| | | } |
| | | |
| | | @Override |
| | | public String toString() { |
| | | return JSON.toJSONString(this); |
| | | } |
| | | /** |
| | | * |
| | | * 账单查询内部消息对象返回实体message内部类 |
| | | * |
| | | */ |
| | | @Data |
| | | public class Message implements Serializable { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** 消息头部 */ |
| | | private Head head; |
| | | |
| | | /** 消息实体 */ |
| | | private Info info; |
| | | |
| | | public Message() { |
| | | this.head = new Head(); |
| | | this.info = new Info(); |
| | | } |
| | | |
| | | public Message(ChargeBillRequest.Message requestMessage){ |
| | | this.setHead(new Head(requestMessage.getHead())); |
| | | this.setInfo(new Info(requestMessage.getInfo())); |
| | | } |
| | | |
| | | @Override |
| | | public String toString() { |
| | | return JSON.toJSONString(this); |
| | | } |
| | | |
| | | /** |
| | | * |
| | | * 账单销账内部消息对象返回实体Head内部类 |
| | | * |
| | | */ |
| | | @Data |
| | | public class Head implements Serializable { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** 渠道 */ |
| | | private String channel; |
| | | |
| | | /** 交易码 */ |
| | | private String transCode; |
| | | |
| | | /** 交易上行下送标志 */ |
| | | private String transFlag; |
| | | |
| | | /** 缴费中心交易序列号 */ |
| | | private String transSeqNum; |
| | | |
| | | /** 时间戳 */ |
| | | private String timeStamp; |
| | | |
| | | /** 查询返回码 */ |
| | | private String returnCode ; |
| | | |
| | | /** 返回提示信息 */ |
| | | private String returnMessage; |
| | | |
| | | public Head() { |
| | | |
| | | } |
| | | |
| | | public Head(ChargeBillRequest.Message.Head reqMessHead) { |
| | | this.setChannel(reqMessHead.getChannel()); |
| | | this.setTransSeqNum(reqMessHead.getTransSeqNum()); |
| | | this.setTransCode(reqMessHead.getTransCode()); |
| | | } |
| | | |
| | | @Override |
| | | public String toString() { |
| | | return JSON.toJSONString(this); |
| | | } |
| | | |
| | | } |
| | | |
| | | /** |
| | | * |
| | | * 账单查询内部消息对象返回实体Info内部类 |
| | | * |
| | | */ |
| | | @Data |
| | | public class Info implements Serializable { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** 缴费项目唯一标识号*/ |
| | | private String epayCode; |
| | | |
| | | /** 缴费中心流水号*/ |
| | | private String traceNo; |
| | | |
| | | /** 退款标志位*/ |
| | | private String refundFlag; |
| | | |
| | | /** 第三方支付平台商户订单号 第三方平台例如微信支付宝的支付订单号 add 2020-01-13*/ |
| | | private String numOpenMerchantOrder; |
| | | |
| | | public Info() { |
| | | |
| | | } |
| | | |
| | | public Info(ChargeBillRequest.Message.Info reqMessInfo) { |
| | | this.setEpayCode(reqMessInfo.getEpayCode()); |
| | | this.setTraceNo(reqMessInfo.getTraceNo()); |
| | | } |
| | | |
| | | @Override |
| | | public String toString() { |
| | | return JSON.toJSONString(this); |
| | | } |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | package com.taxi591.bankapi.dto; |
| | | |
| | | import lombok.Data; |
| | | |
| | | import java.io.Serializable; |
| | | |
| | | @Data |
| | | public class CovertPayBackResult implements Serializable { |
| | | /** |
| | | * 解析结果 |
| | | */ |
| | | private ChargeBillRequest result; |
| | | /** |
| | | * 返回银行应答内容 |
| | | */ |
| | | private String back; |
| | | |
| | | } |
New file |
| | |
| | | package com.taxi591.bankapi.service; |
| | | |
| | | import com.alibaba.fastjson2.JSON; |
| | | import com.alibaba.fastjson2.TypeReference; |
| | | import com.ruoyi.common.exception.ServiceException; |
| | | import com.ruoyi.common.utils.DateUtils; |
| | | import com.taxi591.bankapi.dto.ChargeBillRequest; |
| | | import com.taxi591.bankapi.dto.ChargeBillResponse; |
| | | import com.taxi591.bankapi.dto.CovertPayBackResult; |
| | | import com.taxi591.bankapi.utils.Base64; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import java.io.UnsupportedEncodingException; |
| | | import java.util.function.Function; |
| | | import java.util.regex.Matcher; |
| | | import java.util.regex.Pattern; |
| | | |
| | | @Service |
| | | @Slf4j |
| | | public class BankService { |
| | | |
| | | @Autowired |
| | | SignatureAndVerification signatureAndVerification; |
| | | |
| | | static final String TIMESTAMP_PATTERN = "yyyyMMddHHmmssSSS"; |
| | | |
| | | /** |
| | | * 创建银行应答 |
| | | * @param request 银行请求对象 |
| | | * @param dealResult 是否处理成功 |
| | | * @return |
| | | */ |
| | | public String createResponse(ChargeBillRequest request,Boolean dealResult){ |
| | | ChargeBillResponse response = new ChargeBillResponse(request); |
| | | response.getMessage().getHead().setReturnCode(dealResult?"0000":"1111"); |
| | | response.getMessage().getHead().setReturnMessage(dealResult?"处理成功":"处理失败"); |
| | | response.getMessage().getInfo().setRefundFlag("false"); |
| | | response.getMessage().getHead().setTimeStamp(DateUtils.dateTimeNow(TIMESTAMP_PATTERN)); |
| | | if (!dealResult){ |
| | | if (Integer.parseInt(request.getMessage().getInfo().getResendTimes())==3){ |
| | | response.getMessage().getInfo().setRefundFlag("true"); |
| | | }else{ |
| | | response.getMessage().getInfo().setRefundFlag("false"); |
| | | } |
| | | } |
| | | String respJSON = JSON.toJSONString(response); |
| | | String sign = signatureAndVerification.signWhithsha1withrsa(respJSON); |
| | | String respStr = null; |
| | | try { |
| | | respStr = sign + "||" + new String(org.apache.commons.codec.binary.Base64.encodeBase64(respJSON.getBytes("utf-8"))); |
| | | } catch (UnsupportedEncodingException e) { |
| | | } |
| | | return respStr; |
| | | } |
| | | |
| | | /** |
| | | * 处理支付回调数据 |
| | | * @param httpRequest http请求对象 |
| | | * @param consumer 处理函数 |
| | | * @return |
| | | */ |
| | | public CovertPayBackResult covertPayCallBack(HttpServletRequest httpRequest, Function<ChargeBillRequest,Boolean> consumer) { |
| | | CovertPayBackResult result = new CovertPayBackResult(); |
| | | String requestContent = ""; |
| | | try { |
| | | // 接收报文 |
| | | requestContent = SignatureAndVerification.getRequestBody(httpRequest).trim(); |
| | | String sign = requestContent.substring(0, |
| | | requestContent.indexOf("||"));; |
| | | String requestBody = requestContent.substring(sign |
| | | .length() + 2);; |
| | | Pattern p=Pattern.compile("\""); |
| | | Matcher m=p.matcher(requestBody); |
| | | while(m.find()){ |
| | | requestBody=requestBody.replace(m.group(), ""); |
| | | } |
| | | String request = new String(Base64.decodeFast(requestBody)); |
| | | log.info("-----ChargeBillController------------解析完成后的requestBody-------{}" + request); |
| | | ChargeBillRequest chargeBillRequest = JSON.parseObject(request, |
| | | new TypeReference<ChargeBillRequest>() { |
| | | }); |
| | | if (chargeBillRequest==null){ |
| | | log.error("支付回调解析失败:{}",requestContent); |
| | | throw new ServiceException("支付回调解析失败"); |
| | | } |
| | | boolean isok = signatureAndVerification.read_cer_and_verify_sign(requestBody,sign); |
| | | if (!isok){ |
| | | throw new ServiceException("支付回调验签失败"); |
| | | } |
| | | Boolean dealBack = true; |
| | | if (consumer!=null){ |
| | | dealBack = consumer.apply(chargeBillRequest); |
| | | } |
| | | result.setResult(chargeBillRequest); |
| | | result.setBack(createResponse(chargeBillRequest,dealBack)); |
| | | }catch (ServiceException e){ |
| | | result.setBack(e.getMessage()); |
| | | throw e; |
| | | }catch (Exception e){ |
| | | log.error("解析异常:{}",requestContent,e); |
| | | throw new ServiceException("支付回调解析异常"); |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | |
| | | public void covertBillTo(){ |
| | | |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package com.taxi591.bankapi.service; |
| | | |
| | | import com.taxi591.bankapi.BankProperties; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.commons.codec.binary.Base64; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import java.io.*; |
| | | import java.security.KeyStore; |
| | | import java.security.PrivateKey; |
| | | import java.security.PublicKey; |
| | | import java.security.Signature; |
| | | import java.security.cert.CertificateFactory; |
| | | import java.security.cert.X509Certificate; |
| | | import java.util.Enumeration; |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * 验签和加签工具类 |
| | | * @author yzz |
| | | * |
| | | */ |
| | | @Component |
| | | @Slf4j |
| | | public class SignatureAndVerification { |
| | | |
| | | @Autowired |
| | | BankProperties bankProperties; |
| | | |
| | | |
| | | |
| | | public static String getRequestBody(HttpServletRequest request) |
| | | throws IOException { |
| | | /** 读取httpbody内容 */ |
| | | StringBuilder httpBody = new StringBuilder(); |
| | | BufferedReader br = null; |
| | | try { |
| | | br = new BufferedReader(new InputStreamReader( |
| | | request.getInputStream())); |
| | | String line = null; |
| | | while ((line = br.readLine()) != null) { |
| | | httpBody.append(line); |
| | | } |
| | | } catch (IOException ex) { |
| | | throw ex; |
| | | } finally { |
| | | if (br != null) { |
| | | try { |
| | | br.close(); |
| | | } catch (IOException ex) { |
| | | ex.printStackTrace(); |
| | | } |
| | | } |
| | | } |
| | | return httpBody.toString(); |
| | | } |
| | | /** |
| | | * 加签名 |
| | | * @param dataString |
| | | * @return |
| | | */ |
| | | public String signWhithsha1withrsa(String dataString) { |
| | | String signatureString = null; |
| | | String filePath=bankProperties.getPfxPath(); |
| | | try { |
| | | KeyStore ks = KeyStore.getInstance("PKCS12"); |
| | | FileInputStream fis = new FileInputStream(filePath); |
| | | char[] nPassword = null; |
| | | if ((bankProperties.getKeystorePassword() == null) |
| | | || bankProperties.getKeystorePassword().trim().equals("")) { |
| | | nPassword = null; |
| | | } else { |
| | | nPassword = bankProperties.getKeystorePassword().toCharArray(); |
| | | } |
| | | ks.load(fis, nPassword); |
| | | fis.close(); |
| | | |
| | | Enumeration<String> enums = ks.aliases(); |
| | | String keyAlias = null; |
| | | if (enums.hasMoreElements()) |
| | | { |
| | | keyAlias = (String) enums.nextElement(); |
| | | } |
| | | System.out.println("is key entry=" + ks.isKeyEntry(keyAlias)); |
| | | PrivateKey prikey = (PrivateKey) ks.getKey(keyAlias, nPassword); |
| | | java.security.cert.Certificate cert = ks.getCertificate(keyAlias); |
| | | // SHA1withRSA算法进行签名 |
| | | Signature sign = Signature.getInstance("SHA1withRSA"); |
| | | sign.initSign(prikey); |
| | | byte[] data = dataString.getBytes("utf-8"); |
| | | byte[] dataBase= Base64.encodeBase64(data); |
| | | // 更新用于签名的数据 |
| | | sign.update(dataBase); |
| | | byte[] signature = sign.sign(); |
| | | signatureString = new String(Base64.encodeBase64(signature)); |
| | | System.out.println("加密完成,signature is : " + signatureString); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | return signatureString; |
| | | } |
| | | |
| | | /** |
| | | * 读取cer并验证公钥签名 |
| | | * @return |
| | | */ |
| | | public boolean read_cer_and_verify_sign(String requestBody, String signature) { |
| | | String filePath=bankProperties.getCerPath(); |
| | | X509Certificate cert = null; |
| | | boolean flag = false; |
| | | try { |
| | | CertificateFactory cf = CertificateFactory.getInstance("X.509"); |
| | | cert = (X509Certificate) cf |
| | | .generateCertificate(new FileInputStream(new File( |
| | | filePath))); |
| | | PublicKey publicKey = cert.getPublicKey(); |
| | | String publicKeyString = new String(Base64.encodeBase64(publicKey |
| | | .getEncoded())); |
| | | System.out.println("-----------------公钥--------------------"); |
| | | System.out.println(publicKeyString); |
| | | System.out.println("-----------------公钥--------------------"); |
| | | Signature verifySign = Signature.getInstance("SHA1withRSA"); |
| | | verifySign.initVerify(publicKey); |
| | | // 用于验签的数据 |
| | | verifySign.update(requestBody.getBytes("utf-8")); |
| | | flag = verifySign.verify(Base64 |
| | | .decodeBase64(signature)); |
| | | } catch (Exception e) { |
| | | log.error("验签失败,发生异常:{},{}",requestBody,signature,e); |
| | | flag = false; |
| | | } |
| | | return flag; |
| | | } |
| | | |
| | | /** |
| | | * 接收报文返回requestBody和使用base64解析后的requestBody以及缴费中心传送的签名 |
| | | */ |
| | | |
| | | public Map<String,String> requestBodyOfBase64(HttpServletRequest request){ |
| | | Map<String,String> requestMap=new HashMap<String,String>(); |
| | | // 接收报文 |
| | | String requestContent=null; |
| | | try { |
| | | requestContent = getRequestBody(request) |
| | | .trim(); |
| | | } catch (IOException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | String signatureString = null; |
| | | String requestBody = null; |
| | | if (requestContent.contains("||")) { |
| | | signatureString = requestContent.substring(0, |
| | | requestContent.indexOf("||")); |
| | | requestBody = requestContent.substring(signatureString |
| | | .length() + 2); |
| | | }else { |
| | | try { |
| | | requestBody = new String(requestContent.getBytes("GB2312")); |
| | | |
| | | log.info("转码后的报文:{}",requestBody); |
| | | |
| | | } catch (UnsupportedEncodingException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | log.info("截取报文的requestBody解密前:{}", requestBody); |
| | | |
| | | String requestBodyOfDecoded = new String( |
| | | Base64.decodeBase64(requestBody)); |
| | | |
| | | /*if (requestBodyOfDecoded.contains("</Message>")) { |
| | | requestBody = requestBodyOfDecoded.substring( |
| | | requestContent.indexOf("</Message>"),requestContent.indexOf("</Message>")+10); |
| | | |
| | | signatureString = requestBodyOfDecoded.substring( |
| | | requestContent.indexOf("<Signature>")+11,requestContent.indexOf("</Signature>")); |
| | | }*/ |
| | | |
| | | log.info("截取报文的signatureString:{}", signatureString); |
| | | |
| | | |
| | | System.out.println("-----解析完成后的requestBody-------" + requestBodyOfDecoded); |
| | | |
| | | //使用base64解析完成后的requestBody |
| | | requestMap.put("requestBodyOfDecoded",requestBodyOfDecoded); |
| | | //解析前的requestBody |
| | | requestMap.put("requestBody",requestBody); |
| | | //获取缴费中心传送过来的签名 |
| | | requestMap.put("signatureString",signatureString); |
| | | return requestMap; |
| | | |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | |
| | | package com.taxi591.bankapi.utils; |
| | | |
| | | import java.util.Arrays; |
| | | |
| | | /** |
| | | * |
| | | * @version 2.2 |
| | | * @author Mikael Grev Date: 2004-aug-02 Time: 11:31:11 |
| | | */ |
| | | public class Base64 { |
| | | |
| | | public static final char[] CA = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray(); |
| | | public static final int[] IA = new int[256]; |
| | | static { |
| | | Arrays.fill(IA, -1); |
| | | for (int i = 0, iS = CA.length; i < iS; i++) |
| | | IA[CA[i]] = i; |
| | | IA['='] = 0; |
| | | } |
| | | |
| | | /** |
| | | * Decodes a BASE64 encoded char array that is known to be resonably well formatted. The method is about twice as |
| | | * fast as #decode(char[]). The preconditions are:<br> |
| | | * + The array must have a line length of 76 chars OR no line separators at all (one line).<br> |
| | | * + Line separator must be "\r\n", as specified in RFC 2045 + The array must not contain illegal characters within |
| | | * the encoded string<br> |
| | | * + The array CAN have illegal characters at the beginning and end, those will be dealt with appropriately.<br> |
| | | * |
| | | * @param chars The source array. Length 0 will return an empty array. <code>null</code> will throw an exception. |
| | | * @return The decoded array of bytes. May be of length 0. |
| | | */ |
| | | public static byte[] decodeFast(char[] chars, int offset, int charsLen) { |
| | | // Check special case |
| | | if (charsLen == 0) { |
| | | return new byte[0]; |
| | | } |
| | | |
| | | int sIx = offset, eIx = offset + charsLen - 1; // Start and end index after trimming. |
| | | |
| | | // Trim illegal chars from start |
| | | while (sIx < eIx && IA[chars[sIx]] < 0) |
| | | sIx++; |
| | | |
| | | // Trim illegal chars from end |
| | | while (eIx > 0 && IA[chars[eIx]] < 0) |
| | | eIx--; |
| | | |
| | | // get the padding count (=) (0, 1 or 2) |
| | | int pad = chars[eIx] == '=' ? (chars[eIx - 1] == '=' ? 2 : 1) : 0; // Count '=' at end. |
| | | int cCnt = eIx - sIx + 1; // Content count including possible separators |
| | | int sepCnt = charsLen > 76 ? (chars[76] == '\r' ? cCnt / 78 : 0) << 1 : 0; |
| | | |
| | | int len = ((cCnt - sepCnt) * 6 >> 3) - pad; // The number of decoded bytes |
| | | byte[] bytes = new byte[len]; // Preallocate byte[] of exact length |
| | | |
| | | // Decode all but the last 0 - 2 bytes. |
| | | int d = 0; |
| | | for (int cc = 0, eLen = (len / 3) * 3; d < eLen;) { |
| | | // Assemble three bytes into an int from four "valid" characters. |
| | | int i = IA[chars[sIx++]] << 18 | IA[chars[sIx++]] << 12 | IA[chars[sIx++]] << 6 | IA[chars[sIx++]]; |
| | | |
| | | // Add the bytes |
| | | bytes[d++] = (byte) (i >> 16); |
| | | bytes[d++] = (byte) (i >> 8); |
| | | bytes[d++] = (byte) i; |
| | | |
| | | // If line separator, jump over it. |
| | | if (sepCnt > 0 && ++cc == 19) { |
| | | sIx += 2; |
| | | cc = 0; |
| | | } |
| | | } |
| | | |
| | | if (d < len) { |
| | | // Decode last 1-3 bytes (incl '=') into 1-3 bytes |
| | | int i = 0; |
| | | for (int j = 0; sIx <= eIx - pad; j++) |
| | | i |= IA[chars[sIx++]] << (18 - j * 6); |
| | | |
| | | for (int r = 16; d < len; r -= 8) |
| | | bytes[d++] = (byte) (i >> r); |
| | | } |
| | | |
| | | return bytes; |
| | | } |
| | | |
| | | public static byte[] decodeFast(String chars, int offset, int charsLen) { |
| | | // Check special case |
| | | if (charsLen == 0) { |
| | | return new byte[0]; |
| | | } |
| | | |
| | | int sIx = offset, eIx = offset + charsLen - 1; // Start and end index after trimming. |
| | | |
| | | // Trim illegal chars from start |
| | | while (sIx < eIx && IA[chars.charAt(sIx)] < 0) |
| | | sIx++; |
| | | |
| | | // Trim illegal chars from end |
| | | while (eIx > 0 && IA[chars.charAt(eIx)] < 0) |
| | | eIx--; |
| | | |
| | | // get the padding count (=) (0, 1 or 2) |
| | | int pad = chars.charAt(eIx) == '=' ? (chars.charAt(eIx - 1) == '=' ? 2 : 1) : 0; // Count '=' at end. |
| | | int cCnt = eIx - sIx + 1; // Content count including possible separators |
| | | int sepCnt = charsLen > 76 ? (chars.charAt(76) == '\r' ? cCnt / 78 : 0) << 1 : 0; |
| | | |
| | | int len = ((cCnt - sepCnt) * 6 >> 3) - pad; // The number of decoded bytes |
| | | byte[] bytes = new byte[len]; // Preallocate byte[] of exact length |
| | | |
| | | // Decode all but the last 0 - 2 bytes. |
| | | int d = 0; |
| | | for (int cc = 0, eLen = (len / 3) * 3; d < eLen;) { |
| | | // Assemble three bytes into an int from four "valid" characters. |
| | | int i = IA[chars.charAt(sIx++)] << 18 | IA[chars.charAt(sIx++)] << 12 | IA[chars.charAt(sIx++)] << 6 | IA[chars.charAt(sIx++)]; |
| | | |
| | | // Add the bytes |
| | | bytes[d++] = (byte) (i >> 16); |
| | | bytes[d++] = (byte) (i >> 8); |
| | | bytes[d++] = (byte) i; |
| | | |
| | | // If line separator, jump over it. |
| | | if (sepCnt > 0 && ++cc == 19) { |
| | | sIx += 2; |
| | | cc = 0; |
| | | } |
| | | } |
| | | |
| | | if (d < len) { |
| | | // Decode last 1-3 bytes (incl '=') into 1-3 bytes |
| | | int i = 0; |
| | | for (int j = 0; sIx <= eIx - pad; j++) |
| | | i |= IA[chars.charAt(sIx++)] << (18 - j * 6); |
| | | |
| | | for (int r = 16; d < len; r -= 8) |
| | | bytes[d++] = (byte) (i >> r); |
| | | } |
| | | |
| | | return bytes; |
| | | } |
| | | |
| | | /** |
| | | * Decodes a BASE64 encoded string that is known to be resonably well formatted. The method is about twice as fast |
| | | * as decode(String). The preconditions are:<br> |
| | | * + The array must have a line length of 76 chars OR no line separators at all (one line).<br> |
| | | * + Line separator must be "\r\n", as specified in RFC 2045 + The array must not contain illegal characters within |
| | | * the encoded string<br> |
| | | * + The array CAN have illegal characters at the beginning and end, those will be dealt with appropriately.<br> |
| | | * |
| | | * @param s The source string. Length 0 will return an empty array. <code>null</code> will throw an exception. |
| | | * @return The decoded array of bytes. May be of length 0. |
| | | */ |
| | | public static byte[] decodeFast(String s) { |
| | | // Check special case |
| | | int sLen = s.length(); |
| | | if (sLen == 0) { |
| | | return new byte[0]; |
| | | } |
| | | |
| | | int sIx = 0, eIx = sLen - 1; // Start and end index after trimming. |
| | | |
| | | // Trim illegal chars from start |
| | | while (sIx < eIx && IA[s.charAt(sIx) & 0xff] < 0) |
| | | sIx++; |
| | | |
| | | // Trim illegal chars from end |
| | | while (eIx > 0 && IA[s.charAt(eIx) & 0xff] < 0) |
| | | eIx--; |
| | | |
| | | // get the padding count (=) (0, 1 or 2) |
| | | int pad = s.charAt(eIx) == '=' ? (s.charAt(eIx - 1) == '=' ? 2 : 1) : 0; // Count '=' at end. |
| | | int cCnt = eIx - sIx + 1; // Content count including possible separators |
| | | int sepCnt = sLen > 76 ? (s.charAt(76) == '\r' ? cCnt / 78 : 0) << 1 : 0; |
| | | |
| | | int len = ((cCnt - sepCnt) * 6 >> 3) - pad; // The number of decoded bytes |
| | | byte[] dArr = new byte[len]; // Preallocate byte[] of exact length |
| | | |
| | | // Decode all but the last 0 - 2 bytes. |
| | | int d = 0; |
| | | for (int cc = 0, eLen = (len / 3) * 3; d < eLen;) { |
| | | // Assemble three bytes into an int from four "valid" characters. |
| | | int i = IA[s.charAt(sIx++)] << 18 | IA[s.charAt(sIx++)] << 12 | IA[s.charAt(sIx++)] << 6 |
| | | | IA[s.charAt(sIx++)]; |
| | | |
| | | // Add the bytes |
| | | dArr[d++] = (byte) (i >> 16); |
| | | dArr[d++] = (byte) (i >> 8); |
| | | dArr[d++] = (byte) i; |
| | | |
| | | // If line separator, jump over it. |
| | | if (sepCnt > 0 && ++cc == 19) { |
| | | sIx += 2; |
| | | cc = 0; |
| | | } |
| | | } |
| | | |
| | | if (d < len) { |
| | | // Decode last 1-3 bytes (incl '=') into 1-3 bytes |
| | | int i = 0; |
| | | for (int j = 0; sIx <= eIx - pad; j++) |
| | | i |= IA[s.charAt(sIx++)] << (18 - j * 6); |
| | | |
| | | for (int r = 16; d < len; r -= 8) |
| | | dArr[d++] = (byte) (i >> r); |
| | | } |
| | | |
| | | return dArr; |
| | | } |
| | | } |
New file |
| | |
| | | package com.taxi591.bankapi.utils; |
| | | |
| | | import org.apache.commons.codec.binary.Base64; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | |
| | | import java.io.UnsupportedEncodingException; |
| | | |
| | | /** |
| | | * 将String进行base64编码解码,使用utf-8 |
| | | * yuan |
| | | */ |
| | | public class Base64Util { |
| | | |
| | | private static final Logger LOGGER = LoggerFactory.getLogger(Base64Util.class); |
| | | private static final String UTF_8 = "UTF-8"; |
| | | |
| | | /** |
| | | * 对给定的字符串进行base64解码操作 |
| | | */ |
| | | public static String decodeData(String inputData) { |
| | | try { |
| | | if (null == inputData) { |
| | | return null; |
| | | } |
| | | return new String(Base64.decodeBase64(inputData.getBytes(UTF_8)), UTF_8); |
| | | } catch (UnsupportedEncodingException e) { |
| | | LOGGER.error(inputData, e); |
| | | } |
| | | |
| | | return null; |
| | | } |
| | | |
| | | /** |
| | | * 对给定的字符串进行base64加密操作 |
| | | */ |
| | | public static String encodeData(String inputData) { |
| | | try { |
| | | if (null == inputData) { |
| | | return null; |
| | | } |
| | | return new String(Base64.encodeBase64(inputData.getBytes(UTF_8)), UTF_8); |
| | | } catch (UnsupportedEncodingException e) { |
| | | LOGGER.error(inputData, e); |
| | | } |
| | | |
| | | return null; |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.taxi591.bankapi.utils; |
| | | |
| | | import org.apache.http.Header; |
| | | import org.apache.http.HttpEntity; |
| | | import org.apache.http.HttpResponse; |
| | | import org.apache.http.NameValuePair; |
| | | import org.apache.http.client.ClientProtocolException; |
| | | import org.apache.http.client.config.RequestConfig; |
| | | import org.apache.http.client.entity.UrlEncodedFormEntity; |
| | | import org.apache.http.client.methods.CloseableHttpResponse; |
| | | import org.apache.http.client.methods.HttpGet; |
| | | import org.apache.http.client.methods.HttpPost; |
| | | import org.apache.http.entity.StringEntity; |
| | | import org.apache.http.impl.client.CloseableHttpClient; |
| | | import org.apache.http.impl.client.HttpClientBuilder; |
| | | import org.apache.http.impl.client.HttpClients; |
| | | import org.apache.http.message.BasicNameValuePair; |
| | | import org.apache.http.util.EntityUtils; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | |
| | | import javax.servlet.ServletOutputStream; |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import java.io.BufferedReader; |
| | | import java.io.IOException; |
| | | import java.io.InputStreamReader; |
| | | import java.util.*; |
| | | import java.util.Map.Entry; |
| | | |
| | | /** |
| | | *httpClient操作远程url工具类 |
| | | */ |
| | | public class HttpClientUtils { |
| | | private static Logger logger = LoggerFactory.getLogger(HttpClientUtils.class); |
| | | /** |
| | | * 发送str格式的post请求 |
| | | * @param url |
| | | * @param jsonStr |
| | | * @return |
| | | */ |
| | | public static String doPostStr(String url, String str) { |
| | | // 建立HttpPost对象 |
| | | HttpPost httppost = new HttpPost(url); |
| | | HttpClientBuilder httpClientBuilder = HttpClientBuilder.create(); |
| | | CloseableHttpClient client = httpClientBuilder.build(); |
| | | // int statusCode = 0; |
| | | String responseBody = null; |
| | | try { |
| | | // 设置发送内容、编码等 |
| | | StringEntity stringEntity = new StringEntity(str, "utf-8"); |
| | | stringEntity.setContentType("text/plain"); |
| | | httppost.setEntity(stringEntity); |
| | | // 发送Post,并返回一个HttpResponse对象 |
| | | HttpResponse response = client.execute(httppost); |
| | | // // 获取返回码 |
| | | // statusCode = response.getStatusLine().getStatusCode(); |
| | | // 获取返回报文 |
| | | responseBody = EntityUtils.toString(response.getEntity()); |
| | | return responseBody; |
| | | }catch (Exception e) { |
| | | e.printStackTrace(); |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 下载文件 |
| | | * @param url |
| | | * @param jsonStr |
| | | * @param 前台的返回流 |
| | | * @return |
| | | */ |
| | | public static void doPostFile(String url, String str,HttpServletResponse httpResponse) { |
| | | ServletOutputStream out = null; |
| | | // 建立HttpPost对象 |
| | | HttpPost httppost = new HttpPost(url); |
| | | HttpClientBuilder httpClientBuilder = HttpClientBuilder.create(); |
| | | CloseableHttpClient client = httpClientBuilder.build(); |
| | | try { |
| | | // 设置发送内容、编码等 |
| | | StringEntity stringEntity = new StringEntity(str, "utf-8"); |
| | | stringEntity.setContentType("text/plain"); |
| | | httppost.setEntity(stringEntity); |
| | | // 发送Post,并返回一个HttpResponse对象 |
| | | HttpResponse response = client.execute(httppost); |
| | | // 获取返回报文 |
| | | String responseStr = EntityUtils.toString(response.getEntity()); |
| | | |
| | | //如果系统返回未加密异常则会返回"{"+json+"}" |
| | | if (responseStr.startsWith("{")){ |
| | | //设置响应头信息为页面形式 |
| | | httpResponse.setCharacterEncoding("UTF-8"); |
| | | httpResponse.setContentType("text/html;charset=utf-8"); |
| | | httpResponse.sendRedirect("downloadTraceFail.jsp"); |
| | | |
| | | //如果返回内容为异常信息则返回内容为"签名||base64加密"形式 |
| | | }else if (responseStr.contains("||")) { |
| | | //截取签名信息 |
| | | String headSub = responseStr.substring(0, responseStr.indexOf("||")); |
| | | logger.warn("获取签名的前半部分:"+headSub); |
| | | //截取加密的json信息,进行解密 |
| | | String tailSub = responseStr.substring(responseStr.indexOf("||")+2); |
| | | logger.warn("获取签名的后半部分:"+tailSub); |
| | | //将获取到的json报文进行解析,获取报文体信息 |
| | | responseStr = Base64Util.decodeData(tailSub); |
| | | logger.warn("获取签名解密后:"+responseStr); |
| | | |
| | | //设置响应头信息为页面形式 |
| | | httpResponse.setCharacterEncoding("UTF-8"); |
| | | httpResponse.setContentType("text/html;charset=utf-8"); |
| | | httpResponse.sendRedirect("downloadTraceFail.jsp"); |
| | | |
| | | //返回内容为正常内容,将response消息头读取直接写入httpResponse中 |
| | | }else{ |
| | | Header[] encode = response.getAllHeaders(); |
| | | for (Header header : encode) { |
| | | httpResponse.setHeader(header.getName(), header.getValue()); |
| | | } |
| | | } |
| | | //将获取到的信息封装到httpEntity中,反映到页面中去 |
| | | logger.warn("最终获取到的信息:"+responseStr); |
| | | HttpEntity entity = new StringEntity(responseStr,"UTF-8"); |
| | | //通过输出流将结果反映到页面上 |
| | | out = httpResponse.getOutputStream(); |
| | | entity.writeTo(out); |
| | | out.flush(); |
| | | }catch (Exception e) { |
| | | e.printStackTrace(); |
| | | }finally{ |
| | | if(out != null){ |
| | | try { |
| | | out.close(); |
| | | } catch (IOException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * get 请求方法 |
| | | * @param url |
| | | * @return |
| | | */ |
| | | public static String doGet(String url) { |
| | | CloseableHttpClient httpClient = null; |
| | | CloseableHttpResponse response = null; |
| | | String result = ""; |
| | | |
| | | try { |
| | | //通过址默认配置创建一个httpClient实例 |
| | | httpClient = HttpClients.createDefault(); |
| | | //创建httpGet远程连接实例 |
| | | HttpGet httpGet = new HttpGet(url); |
| | | //设置配置请求参数 |
| | | RequestConfig requestConfig = RequestConfig.custom() |
| | | .setConnectTimeout(35000)//连接主机服务超时时间 |
| | | .setConnectionRequestTimeout(35000)//请求超时时间 |
| | | .setSocketTimeout(60000)//数据读取超时时间 |
| | | .build(); |
| | | //为httpGet实例设置配置 |
| | | httpGet.setConfig(requestConfig); |
| | | //执行get请求得到返回对象 |
| | | response = httpClient.execute(httpGet); |
| | | //通过返回对象获取返回数据 |
| | | HttpEntity entity = response.getEntity(); |
| | | //通过EntityUtils中的toString方法将结果转换为字符串 |
| | | result = EntityUtils.toString(entity); |
| | | |
| | | } catch (ClientProtocolException e) { |
| | | e.printStackTrace(); |
| | | } catch (IOException e) { |
| | | e.printStackTrace(); |
| | | } finally { |
| | | //关闭资源 |
| | | if(null != response) { |
| | | try { |
| | | response.close(); |
| | | } catch (IOException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | |
| | | if(null != httpClient) { |
| | | try { |
| | | httpClient.close(); |
| | | } catch (IOException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | return result; |
| | | } |
| | | |
| | | /** |
| | | * post请求 |
| | | * @param url |
| | | * @param paramMap |
| | | * @return |
| | | */ |
| | | public static String doPost(String url, Map<String,Object> paramMap) { |
| | | CloseableHttpClient httpClient = null; |
| | | CloseableHttpResponse response = null; |
| | | String result = ""; |
| | | |
| | | try { |
| | | //创建httpClient实例 |
| | | httpClient = HttpClients.createDefault(); |
| | | //创建httpPost远程连接实例 |
| | | HttpPost httpPost = new HttpPost(url); |
| | | //配置请求参数实例 |
| | | RequestConfig requestConfig = RequestConfig.custom() |
| | | .setConnectTimeout(35000)//设置连接主机服务超时时间 |
| | | .setConnectionRequestTimeout(35000)//设置连接请求超时时间 |
| | | .setSocketTimeout(60000)//设置读取数据连接超时时间 |
| | | .build(); |
| | | //为httpPost实例设置配置 |
| | | httpPost.setConfig(requestConfig); |
| | | |
| | | //封装post请求参数 |
| | | if(null != paramMap && paramMap.size() > 0) { |
| | | List<NameValuePair> nvps = new ArrayList<NameValuePair>(); |
| | | //通过map集成entrySet方法获取entity |
| | | Set<Entry<String, Object>> entrySet = paramMap.entrySet(); |
| | | //循环遍历,获取迭代器 |
| | | Iterator<Entry<String, Object>> iterator = entrySet.iterator(); |
| | | while (iterator.hasNext()) { |
| | | Entry<String, Object> mapEntry = iterator.next(); |
| | | nvps.add(new BasicNameValuePair(mapEntry.getKey(), mapEntry.getValue().toString())); |
| | | } |
| | | |
| | | //为httpPost设置封装好的请求参数 |
| | | httpPost.setEntity(new UrlEncodedFormEntity(nvps, "UTF-8")); |
| | | } |
| | | |
| | | //执行post请求得到返回对象 |
| | | response = httpClient.execute(httpPost); |
| | | //通过返回对象获取数据 |
| | | HttpEntity entity = response.getEntity(); |
| | | //将返回的数据转换为字符串 |
| | | result = EntityUtils.toString(entity); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } finally { |
| | | //关闭资源 |
| | | if(null != response) { |
| | | try { |
| | | response.close(); |
| | | } catch (IOException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | |
| | | if(null != httpClient) { |
| | | try { |
| | | httpClient.close(); |
| | | } catch (IOException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * |
| | | * @param request |
| | | * @return |
| | | * @throws IOException |
| | | */ |
| | | public static String getRequestBody(HttpServletRequest request) |
| | | throws IOException { |
| | | /** 读取httpbody内容 */ |
| | | StringBuilder httpBody = new StringBuilder(); |
| | | BufferedReader br = null; |
| | | try { |
| | | br = new BufferedReader(new InputStreamReader( |
| | | request.getInputStream())); |
| | | String line = null; |
| | | while ((line = br.readLine()) != null) { |
| | | httpBody.append(line); |
| | | } |
| | | } catch (IOException ex) { |
| | | throw ex; |
| | | } finally { |
| | | if (br != null) { |
| | | try { |
| | | br.close(); |
| | | } catch (IOException ex) { |
| | | ex.printStackTrace(); |
| | | } |
| | | } |
| | | } |
| | | return httpBody.toString(); |
| | | } |
| | | |
| | | |
| | | |
| | | } |
New file |
| | |
| | | org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ |
| | | com.taxi591.bankapi.BankConfig |
| | |
| | | // strategy.setTablePrefix(pc.getModuleName() + ""); |
| | | // strategy.setLikeTable(new LikeTable("room")); |
| | | //strategy.setLikeTable(new LikeTable("member")); |
| | | strategy.setLikeTable(new LikeTable("t_"));// 生成表名 |
| | | strategy.setLikeTable(new LikeTable("t_bank_flow"));// 生成表名 |
| | | // strategy.setLikeTable(new LikeTable("t_hotel"));// 生成表名 |
| | | // strategy.setLikeTable(new LikeTable("t_scan_message"));// 生成表名 |
| | | // strategy.setNotLikeTable(new LikeTable("hotel_info"));// 不生成表名 |
| | |
| | | <module>ruoyi-generator</module> |
| | | <module>ruoyi-common</module> |
| | | <module>ruoyi-applet</module> |
| | | <module>bankapi</module> |
| | | </modules> |
| | | <packaging>pom</packaging> |
| | | |
| | |
| | | </description> |
| | | |
| | | <dependencies> |
| | | |
| | | <dependency> |
| | | <groupId>org.taxi591</groupId> |
| | | <artifactId>bankapi</artifactId> |
| | | <version>1.0.0-SNAPSHOT</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.aliyun.oss</groupId> |
| | | <artifactId>aliyun-sdk-oss</artifactId> |
New file |
| | |
| | | package com.ruoyi.web.controller.api; |
| | | |
| | | import com.ruoyi.system.service.TBillService; |
| | | import com.taxi591.bankapi.dto.CovertPayBackResult; |
| | | import com.taxi591.bankapi.service.BankService; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.web.bind.annotation.PostMapping; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.ResponseBody; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | import javax.servlet.http.HttpServletRequest; |
| | | |
| | | @RestController |
| | | @RequestMapping("open/bank") |
| | | public class BankOutController { |
| | | |
| | | @Autowired |
| | | BankService bankService; |
| | | |
| | | @Autowired |
| | | TBillService tBillService; |
| | | @PostMapping(value = "payCallback") |
| | | public @ResponseBody String payCallback(HttpServletRequest request){ |
| | | CovertPayBackResult result = bankService.covertPayCallBack(request, (billRequest) -> { |
| | | String orderno = billRequest.getMessage().getInfo().getInput1(); |
| | | |
| | | return true; |
| | | }); |
| | | return result.getBack(); |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package com.ruoyi.web.controller.api; |
| | | |
| | | |
| | | import com.ruoyi.common.basic.PageInfo; |
| | | import com.ruoyi.common.core.domain.R; |
| | | import com.ruoyi.system.model.TBankFlow; |
| | | import com.ruoyi.system.model.TFlowManagement; |
| | | import com.ruoyi.system.query.TBankFlowQuery; |
| | | import com.ruoyi.system.query.TFlowManagementQuery; |
| | | import com.ruoyi.system.service.TBankFlowService; |
| | | import com.ruoyi.system.service.TFlowManagementService; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.security.access.prepost.PreAuthorize; |
| | | 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; |
| | | |
| | | /** |
| | | * <p> |
| | | * 流水管理 前端控制器 |
| | | * </p> |
| | | * |
| | | * @author xiaochen |
| | | * @since 2025-02-07 |
| | | */ |
| | | @RestController |
| | | @RequestMapping("/t-bank-flow") |
| | | public class TBankFlowController { |
| | | @Autowired |
| | | private TBankFlowService flowService; |
| | | /** |
| | | * 获取流水列表 |
| | | */ |
| | | @PreAuthorize("@ss.hasPermi('system:bankFlow:list')") |
| | | @ApiOperation(value = "获取银行流水列表") |
| | | @PostMapping("/list") |
| | | public R<PageInfo<TBankFlow>> list(@RequestBody TBankFlowQuery query) { |
| | | return R.ok(flowService.pageList(query)); |
| | | } |
| | | } |
| | | |
New file |
| | |
| | | package com.ruoyi.web.controller.api; |
| | | |
| | | |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | /** |
| | | * <p> |
| | | * 账单线下缴费关联表 前端控制器 |
| | | * </p> |
| | | * |
| | | * @author xiaochen |
| | | * @since 2025-02-10 |
| | | */ |
| | | @RestController |
| | | @RequestMapping("/t-bill-confirm") |
| | | public class TBillConfirmController { |
| | | |
| | | } |
| | | |
| | |
| | | package com.ruoyi.web.controller.api; |
| | | |
| | | |
| | | import com.ruoyi.common.basic.PageInfo; |
| | | import com.ruoyi.common.core.domain.R; |
| | | import com.ruoyi.system.dto.TBillDto; |
| | | import com.ruoyi.system.model.TBill; |
| | | import com.ruoyi.system.query.TBillQuery; |
| | | import com.ruoyi.system.service.TBillService; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | 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; |
| | | |
| | |
| | | @RequestMapping("/t-bill") |
| | | public class TBillController { |
| | | |
| | | @Autowired |
| | | TBillService tBillService; |
| | | |
| | | @PostMapping("list") |
| | | public R<PageInfo<TBillDto>> list(@RequestBody TBillQuery query){ |
| | | PageInfo<TBillDto> pageInfo = tBillService.queryPage(query); |
| | | return R.ok(pageInfo); |
| | | } |
| | | |
| | | |
| | | } |
| | | |
New file |
| | |
| | | package com.ruoyi.web.controller.api; |
| | | |
| | | |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | /** |
| | | * <p> |
| | | * 账单水电费子表 前端控制器 |
| | | * </p> |
| | | * |
| | | * @author xiaochen |
| | | * @since 2025-02-10 |
| | | */ |
| | | @RestController |
| | | @RequestMapping("/t-bill-detail") |
| | | public class TBillDetailController { |
| | | |
| | | } |
| | | |
| | |
| | | package com.ruoyi.web.controller.api; |
| | | |
| | | |
| | | import com.ruoyi.common.basic.PageInfo; |
| | | import com.ruoyi.common.core.domain.R; |
| | | import com.ruoyi.system.model.TFlowManagement; |
| | | import com.ruoyi.system.query.TFlowManagementQuery; |
| | | import com.ruoyi.system.service.TFlowManagementService; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.security.access.prepost.PreAuthorize; |
| | | 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; |
| | |
| | | @RestController |
| | | @RequestMapping("/t-flow-management") |
| | | public class TFlowManagementController { |
| | | @Autowired |
| | | private TFlowManagementService flowService; |
| | | /** |
| | | * 获取流水列表 |
| | | */ |
| | | @PreAuthorize("@ss.hasPermi('system:flow:list')") |
| | | @ApiOperation(value = "获取流水列表") |
| | | @PostMapping("/list") |
| | | public R<PageInfo<TFlowManagement>> list(@RequestBody TFlowManagementQuery query) { |
| | | return R.ok(flowService.pageList(query)); |
| | | } |
| | | |
| | | |
| | | } |
| | | |
| | |
| | | package com.ruoyi.web.controller.api; |
| | | |
| | | |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | import com.ruoyi.common.annotation.Log; |
| | | import com.ruoyi.common.basic.PageInfo; |
| | | import com.ruoyi.common.core.domain.R; |
| | | import com.ruoyi.common.enums.BusinessType; |
| | | import com.ruoyi.system.model.TInvoice; |
| | | import com.ruoyi.system.query.TInvoiceQuery; |
| | | import com.ruoyi.system.service.TInvoiceService; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.security.access.prepost.PreAuthorize; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | /** |
| | | * <p> |
| | |
| | | @RestController |
| | | @RequestMapping("/t-invoice") |
| | | public class TInvoiceController { |
| | | @Autowired |
| | | private TInvoiceService invoiceService; |
| | | @PreAuthorize("@ss.hasPermi('system:invoice:list')") |
| | | @ApiOperation(value = "获取开票列表") |
| | | @PostMapping("/list") |
| | | public R<PageInfo<TInvoice>> list(@RequestBody TInvoiceQuery query) { |
| | | return R.ok(invoiceService.pageList(query)); |
| | | } |
| | | |
| | | @PreAuthorize("@ss.hasPermi('system:invoice:delete')") |
| | | @Log(title = "开票信息-删除开票", businessType = BusinessType.DELETE) |
| | | @ApiOperation(value = "删除开票") |
| | | @DeleteMapping(value = "/deleteById") |
| | | public R<Boolean> deleteById(@RequestParam String id) { |
| | | return R.ok(invoiceService.removeById(id)); |
| | | } |
| | | |
| | | } |
| | | |
New file |
| | |
| | | package com.ruoyi.web.controller.api; |
| | | |
| | | |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | /** |
| | | * <p> |
| | | * 账单开票中间表 前端控制器 |
| | | * </p> |
| | | * |
| | | * @author xiaochen |
| | | * @since 2025-02-10 |
| | | */ |
| | | @RestController |
| | | @RequestMapping("/t-invoice-to-bill") |
| | | public class TInvoiceToBillController { |
| | | |
| | | } |
| | | |
New file |
| | |
| | | package com.ruoyi.web.task; |
| | | |
| | | import com.ruoyi.common.basic.PageInfo; |
| | | import com.ruoyi.system.dto.TBillDto; |
| | | import com.ruoyi.system.model.TBill; |
| | | import com.ruoyi.system.model.TContract; |
| | | import com.ruoyi.system.query.TBillQuery; |
| | | import com.ruoyi.system.query.TContractQuery; |
| | | import com.ruoyi.system.service.TBillService; |
| | | import com.ruoyi.system.service.TContractService; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | import java.util.Calendar; |
| | | import java.util.Collections; |
| | | import java.util.Date; |
| | | |
| | | @Slf4j |
| | | @Component("billTask") |
| | | public class TbillTask { |
| | | |
| | | @Autowired |
| | | TBillService tBillService; |
| | | |
| | | @Autowired |
| | | TContractService tContractService; |
| | | |
| | | /** |
| | | * 判断账单是否到期 |
| | | */ |
| | | public void checkBillOverdue(){ |
| | | try { |
| | | int index = 1; |
| | | int rows = 20; |
| | | long pages = 0; |
| | | TBillQuery query = new TBillQuery(); |
| | | query.setPageSize(rows); |
| | | //查询未缴费的 |
| | | query.setPayFeesStatus(1); |
| | | Calendar c = Calendar.getInstance(); |
| | | Date time = c.getTime(); |
| | | do { |
| | | query.setPageNum(index); |
| | | PageInfo<TBillDto> pageinfo = tBillService.queryPage(query); |
| | | if (pages==0){ |
| | | pages = pageinfo.getPages(); |
| | | } |
| | | if (pageinfo.getRecords()!=null && pageinfo.getRecords().size()>0){ |
| | | pageinfo.getRecords().forEach(tBill -> { |
| | | |
| | | //todo 生成账单 |
| | | |
| | | }); |
| | | |
| | | } |
| | | index++; |
| | | }while (index<=pages); |
| | | }catch (Exception e){ |
| | | log.error(""); |
| | | } |
| | | |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 计算违约金 |
| | | */ |
| | | public void caculatePenaltyFee(){ |
| | | try { |
| | | int index = 1; |
| | | int rows = 20; |
| | | long pages = 0; |
| | | TBillQuery query = new TBillQuery(); |
| | | query.setPageSize(rows); |
| | | //查询已逾期的 |
| | | query.setPayFeesStatus(4); |
| | | Calendar c = Calendar.getInstance(); |
| | | Date time = c.getTime(); |
| | | do { |
| | | query.setPageNum(index); |
| | | PageInfo<TBillDto> pageinfo = tBillService.queryPage(query); |
| | | if (pages==0){ |
| | | pages = pageinfo.getPages(); |
| | | } |
| | | if (pageinfo.getRecords()!=null && pageinfo.getRecords().size()>0){ |
| | | pageinfo.getRecords().forEach(tContract -> { |
| | | |
| | | //todo 生成账单 |
| | | |
| | | }); |
| | | |
| | | } |
| | | index++; |
| | | }while (index<=pages); |
| | | }catch (Exception e){ |
| | | log.error(""); |
| | | } |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | } |
| | |
| | | port: 8081 |
| | | servlet: |
| | | # 应用的访问路径 |
| | | context-path: / |
| | | context-path: /admin |
| | | tomcat: |
| | | # tomcat的URI编码 |
| | | uri-encoding: UTF-8 |
| | |
| | | port: 8081 |
| | | servlet: |
| | | # 应用的访问路径 |
| | | context-path: / |
| | | context-path: /admin |
| | | tomcat: |
| | | # tomcat的URI编码 |
| | | uri-encoding: UTF-8 |
| | |
| | | </description> |
| | | |
| | | <dependencies> |
| | | |
| | | <dependency> |
| | | <groupId>org.taxi591</groupId> |
| | | <artifactId>bankapi</artifactId> |
| | | <version>1.0.0-SNAPSHOT</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.aliyun.oss</groupId> |
| | | <artifactId>aliyun-sdk-oss</artifactId> |
New file |
| | |
| | | package com.ruoyi.web.controller.api; |
| | | |
| | | import com.ruoyi.common.core.domain.AjaxResult; |
| | | import com.ruoyi.common.core.domain.R; |
| | | import com.ruoyi.system.dto.MakeOrderDto; |
| | | import com.ruoyi.system.dto.MakeOrderResp; |
| | | import com.ruoyi.system.service.TPayOrderService; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.validation.annotation.Validated; |
| | | 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; |
| | | |
| | | @RestController |
| | | @RequestMapping("/t-pay") |
| | | public class PayController { |
| | | |
| | | |
| | | |
| | | @Autowired |
| | | TPayOrderService tPayOrderService; |
| | | |
| | | @ApiOperation(value = "创建支付订单") |
| | | @PostMapping("makeOrder") |
| | | public R<MakeOrderResp> makeOrder(@Validated @RequestBody MakeOrderDto dto){ |
| | | MakeOrderResp resp = tPayOrderService.makeOrder(dto); |
| | | return R.ok(resp); |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package com.ruoyi.web.controller.api; |
| | | |
| | | |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | /** |
| | | * <p> |
| | | * 账单线下缴费关联表 前端控制器 |
| | | * </p> |
| | | * |
| | | * @author xiaochen |
| | | * @since 2025-02-10 |
| | | */ |
| | | @RestController |
| | | @RequestMapping("/t-bill-confirm") |
| | | public class TBillConfirmController { |
| | | |
| | | } |
| | | |
| | |
| | | package com.ruoyi.web.controller.api; |
| | | |
| | | |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import com.ruoyi.common.basic.PageInfo; |
| | | import com.ruoyi.common.constant.DictConstants; |
| | | import com.ruoyi.common.core.domain.R; |
| | | import com.ruoyi.common.exception.ServiceException; |
| | | import com.ruoyi.common.utils.DictUtils; |
| | | import com.ruoyi.common.utils.StringUtils; |
| | | import com.ruoyi.system.dto.TBillDto; |
| | | import com.ruoyi.system.dto.TInvoiceDTO; |
| | | import com.ruoyi.system.model.*; |
| | | import com.ruoyi.system.query.TBillQuery; |
| | | import com.ruoyi.system.query.TTenantQuery; |
| | | import com.ruoyi.system.service.TBillDetailService; |
| | | import com.ruoyi.system.service.TBillService; |
| | | import com.ruoyi.system.service.TInvoiceService; |
| | | import com.ruoyi.system.service.TInvoiceToBillService; |
| | | import com.ruoyi.system.vo.TBillVO; |
| | | import com.ruoyi.system.vo.TenantVO; |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import org.springframework.beans.BeanUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.security.access.prepost.PreAuthorize; |
| | | 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 org.springframework.web.bind.annotation.*; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * <p> |
| | |
| | | * @author xiaochen |
| | | * @since 2025-01-17 |
| | | */ |
| | | @Api(tags = "租金账单管理") |
| | | @Api(tags = "缴费账单") |
| | | @RestController |
| | | @RequestMapping("/t-bill") |
| | | public class TBillController { |
| | | |
| | | private final TBillService billService; |
| | | |
| | | @Autowired |
| | | public TBillController(TBillService billService) { |
| | | this.billService = billService; |
| | | TBillService tBillService; |
| | | @Autowired |
| | | TBillDetailService billDetailService; |
| | | @Autowired |
| | | TInvoiceService invoiceService; |
| | | @Autowired |
| | | TInvoiceToBillService invoiceToBillService; |
| | | |
| | | @ApiOperation(value = "缴费账单查询分页列表") |
| | | @PostMapping("list") |
| | | public R<PageInfo<TBillDto>> list(@RequestBody TBillQuery query){ |
| | | if (StringUtils.isEmpty(query.getUserId())){ |
| | | throw new ServiceException("用户ID不能为空"); |
| | | } |
| | | PageInfo<TBillDto> pageInfo = tBillService.queryPage(query); |
| | | return R.ok(pageInfo); |
| | | } |
| | | |
| | | /** |
| | | * 获取账单列表 |
| | | */ |
| | | @ApiOperation(value = "获取账单列表") |
| | | @PostMapping(value = "/pageList") |
| | | public R<PageInfo<TBillVO>> pageList(@RequestBody TBillQuery query) { |
| | | return R.ok(billService.pageList(query)); |
| | | @ApiOperation(value = "查看缴费账单详情") |
| | | @GetMapping(value = "/getDetailById") |
| | | public R<TBillVO> getDetailById(@RequestParam String id) { |
| | | TBill bill = tBillService.getById(id); |
| | | TBillVO billVO = new TBillVO(); |
| | | BeanUtils.copyProperties(bill, billVO); |
| | | // 查询水电费列表 |
| | | if("3".equals(bill.getBillType())){ |
| | | List<TBillDetail> list = billDetailService.list(Wrappers.lambdaQuery(TBillDetail.class) |
| | | .eq(TBillDetail::getBillId, id)); |
| | | billVO.setBillDetailList(list); |
| | | } |
| | | billVO.setBillType(DictUtils.getDictLabel(DictConstants.DICT_TYPE_BILL_TYPE,billVO.getBillType())); |
| | | billVO.setPayFeesStatus(DictUtils.getDictLabel(DictConstants.DICT_TYPE_PAY_FEES_STATUS,billVO.getPayFeesStatus())); |
| | | return R.ok(billVO); |
| | | } |
| | | |
| | | @ApiOperation(value = "缴费账单开票") |
| | | @PostMapping(value = "/invoice") |
| | | public R<String> invoice(@RequestBody TInvoiceDTO dto) { |
| | | // 添加开票信息 |
| | | invoiceService.save(dto); |
| | | |
| | | // 添加开票信息中间表信息 |
| | | List<String> billIds = dto.getBillIds(); |
| | | List<TInvoiceToBill> sysInvoiceToBills = new ArrayList<>(); |
| | | for (String billId : billIds) { |
| | | TInvoiceToBill tInvoiceToBill = new TInvoiceToBill(); |
| | | tInvoiceToBill.setInvoiceId(dto.getId()); |
| | | tInvoiceToBill.setBillId(billId); |
| | | sysInvoiceToBills.add(tInvoiceToBill); |
| | | } |
| | | invoiceToBillService.saveBatch(sysInvoiceToBills); |
| | | return R.ok(); |
| | | } |
| | | |
| | | } |
| | | |
| | |
| | | package com.ruoyi.web.controller.api; |
| | | |
| | | |
| | | import com.ruoyi.common.basic.PageInfo; |
| | | import com.ruoyi.common.core.domain.R; |
| | | import com.ruoyi.system.model.TInformation; |
| | | import com.ruoyi.system.query.TInformationQuery; |
| | | import com.ruoyi.system.service.TInformationService; |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.security.access.prepost.PreAuthorize; |
| | | 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; |
| | |
| | | * @author xiaochen |
| | | * @since 2025-01-17 |
| | | */ |
| | | @Api(tags = "资讯管理") |
| | | @RestController |
| | | @RequestMapping("/t-information") |
| | | public class TInformationController { |
| | | |
| | | private final TInformationService informationService; |
| | | @Autowired |
| | | public TInformationController(TInformationService informationService) { |
| | | this.informationService = informationService; |
| | | } |
| | | |
| | | /** |
| | | * 获取资讯管理管理列表 |
| | | */ |
| | | @ApiOperation(value = "获取资讯管理分页列表") |
| | | @PostMapping(value = "/pageList") |
| | | public R<PageInfo<TInformation>> pageList(@RequestBody TInformationQuery query) { |
| | | return R.ok(informationService.pageList(query)); |
| | | } |
| | | |
| | | } |
| | | |
| | |
| | | @PostMapping("/list") |
| | | public AjaxResult list(@RequestBody SysRoleQuery query) |
| | | { |
| | | PageInfo<SysRole> list = roleService.selectList(query); |
| | | PageInfo<SysRole> list = roleService.selectPageList(query); |
| | | return AjaxResult.success(list); |
| | | } |
| | | |
New file |
| | |
| | | package com.ruoyi.common.constant; |
| | | |
| | | import java.math.BigDecimal; |
| | | |
| | | public class AmountConstant { |
| | | |
| | | public static final BigDecimal b100 = new BigDecimal("100"); |
| | | |
| | | public static final BigDecimal b1000 = new BigDecimal("1000"); |
| | | |
| | | public static final BigDecimal b001 = new BigDecimal("0.01"); |
| | | |
| | | |
| | | |
| | | } |
| | |
| | | * 缴费状态 1=未缴费 2=待确认 3=已缴费 4=已逾期 5=已失效 |
| | | */ |
| | | public static final String DICT_TYPE_PAY_FEES_STATUS = "t_pay_fees_status"; |
| | | /** |
| | | * 账单类型 1=租金 2=押金 3=生活费用 |
| | | */ |
| | | public static final String DICT_TYPE_BILL_TYPE = "t_bill_type"; |
| | | } |
| | |
| | | * 高德地图坐标转换 |
| | | */ |
| | | public static final String ADDRESS_CONVERT_TO_COORDINATE = "https://restapi.amap.com/v3/geocode/geo?key=KEY&address=ADDRESS"; |
| | | |
| | | |
| | | |
| | | } |
| | |
| | | package com.ruoyi.common.core.redis; |
| | | |
| | | import java.util.Collection; |
| | | import java.util.Iterator; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Set; |
| | | import java.util.*; |
| | | import java.util.concurrent.TimeUnit; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.data.redis.core.BoundSetOperations; |
| | | import org.springframework.data.redis.core.HashOperations; |
| | | import org.springframework.data.redis.core.RedisTemplate; |
| | | import org.springframework.data.redis.core.ValueOperations; |
| | | import org.springframework.data.redis.core.script.DefaultRedisScript; |
| | | import org.springframework.data.redis.core.script.RedisScript; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | /** |
| | |
| | | @Component |
| | | public class RedisCache |
| | | { |
| | | private static final String LOCK_PREFIX = "lock:"; |
| | | private static final RedisScript<Long> UNLOCK_SCRIPT = new DefaultRedisScript<>( |
| | | "if redis.call('get', KEYS[1]) == ARGV[1] then " + |
| | | " return redis.call('del', KEYS[1]) " + |
| | | "else " + |
| | | " return 0 " + |
| | | "end", |
| | | Long.class |
| | | ); |
| | | @Autowired |
| | | public RedisTemplate redisTemplate; |
| | | |
| | |
| | | { |
| | | return redisTemplate.keys(pattern); |
| | | } |
| | | |
| | | /** |
| | | * 尝试加锁 |
| | | * |
| | | * @param lockKey 锁的key |
| | | * @param requestId 锁的持有者标识符(如UUID) |
| | | * @param expireTime 锁的过期时间(秒) |
| | | * @return 加锁成功返回true,否则返回false |
| | | */ |
| | | public boolean tryLock(String lockKey, String requestId, long expireTime) { |
| | | String lockKeyWithPrefix = LOCK_PREFIX + lockKey; |
| | | // 使用SET命令的NX和PX选项来加锁 |
| | | Boolean result = redisTemplate.opsForValue().setIfAbsent(lockKeyWithPrefix, requestId, expireTime, TimeUnit.SECONDS); |
| | | return result != null && result; |
| | | } |
| | | |
| | | /** |
| | | * 解锁 |
| | | * |
| | | * @param lockKey 锁的key |
| | | * @param requestId 锁的持有者标识符(如UUID) |
| | | * @return 解锁成功返回true,否则返回false |
| | | */ |
| | | public boolean unlock(String lockKey, String requestId) { |
| | | String lockKeyWithPrefix = LOCK_PREFIX + lockKey; |
| | | // 使用Lua脚本来验证锁的持有者并解锁 |
| | | Long result = (Long) redisTemplate.execute(UNLOCK_SCRIPT, Collections.singletonList(lockKeyWithPrefix), requestId); |
| | | return result != null && result == 1L; |
| | | } |
| | | } |
New file |
| | |
| | | package com.ruoyi.common.utils; |
| | | |
| | | import com.ruoyi.common.utils.ip.IpUtils; |
| | | import org.apache.commons.lang3.StringUtils; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | |
| | | import java.util.concurrent.atomic.AtomicLong; |
| | | |
| | | public class OrderNos { |
| | | |
| | | public static final char PADCHAR = '0'; |
| | | |
| | | |
| | | |
| | | /** |
| | | * 长度24位全球唯一标识 |
| | | */ |
| | | |
| | | /** |
| | | * 统一不重复内部订单号 |
| | | * |
| | | * @param systemCode |
| | | * 4字节系统编码 |
| | | * @return 24字节不重复编码 |
| | | */ |
| | | public static String oid(String systemCode) { |
| | | StringBuilder sb = new StringBuilder(); |
| | | sb.append(padding(systemCode, 4)); |
| | | sb.append(Did.getInstance().getId(20)); |
| | | return sb.toString(); |
| | | } |
| | | |
| | | public static String oid() { |
| | | return oid("O001"); |
| | | } |
| | | |
| | | /** |
| | | * 获取分布式Id |
| | | * |
| | | * @return 默认20字符长度的数字不重复编码 |
| | | */ |
| | | public static String getDid() { |
| | | return Did.getInstance().getId(); |
| | | } |
| | | |
| | | public static String getDid(int size) { |
| | | return Did.getInstance().getId(size); |
| | | } |
| | | |
| | | public static String getDid(String prefix) { |
| | | return prefix + Did.getInstance().getId(); |
| | | } |
| | | |
| | | private static String padding(String text, int size) { |
| | | String txt = StringUtils.trimToEmpty(text); |
| | | if (StringUtils.length(txt) > size) { |
| | | txt = StringUtils.substring(txt, StringUtils.length(txt) - size); |
| | | } |
| | | return StringUtils.leftPad(txt, size, PADCHAR); |
| | | } |
| | | |
| | | /** |
| | | * ID生成器 |
| | | * |
| | | * 20字符长度 yyMMddHHmmss+3位本机IP末三位+5位随机数字 |
| | | * |
| | | * @author zhangpu |
| | | * |
| | | */ |
| | | public static class Did { |
| | | private static final Logger logger = LoggerFactory.getLogger(OrderNos.class); |
| | | private static final int MIN_LENGTH = 19; |
| | | private static final int SEQU_MAX = 99999; |
| | | private static final int SEQU_19_MAX = 9999; |
| | | private volatile static long BASE = 0; |
| | | private AtomicLong sequence = new AtomicLong(0); |
| | | private String nodeFlag; |
| | | private Object nodeFlagLock = new Object(); |
| | | private static Did did = new Did(); |
| | | |
| | | |
| | | public static Did getInstance() { |
| | | return did; |
| | | } |
| | | |
| | | /** |
| | | * 生产新Id |
| | | * |
| | | * @return |
| | | */ |
| | | public String getId() { |
| | | return getId(20); |
| | | } |
| | | |
| | | public String getId(int size) { |
| | | if (size < MIN_LENGTH) { |
| | | throw new RuntimeException("did最小长度为" + MIN_LENGTH); |
| | | } |
| | | StringBuilder sb = new StringBuilder(); |
| | | sb.append(DateUtils.dateTimeNow("yyMMddHHmmss")); |
| | | sb.append(getNodeFlag()); |
| | | sb.append(getSequ(size-15)); |
| | | return sb.toString(); |
| | | } |
| | | |
| | | public synchronized String getSequ(int size) { |
| | | long timeCount = System.currentTimeMillis() / 1000; |
| | | |
| | | while (true) { |
| | | long now = sequence.get(); |
| | | if (timeCount > now) { |
| | | // 已经过了本秒,则设置新的值 |
| | | if (sequence.compareAndSet(now, timeCount)) { |
| | | break; |
| | | } |
| | | } else { |
| | | if (sequence.compareAndSet(now, now + 1)) { |
| | | timeCount = now + 1; |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | int sn = (int) (timeCount % (size>=5?SEQU_MAX:SEQU_19_MAX)); |
| | | return StringUtils.leftPad(String.valueOf(sn), size, '0'); |
| | | } |
| | | |
| | | private String getNodeFlag(){ |
| | | if (this.nodeFlag == null) { |
| | | synchronized (Did.class){ |
| | | if (this.nodeFlag==null){ |
| | | this.nodeFlag = generateNodeFlag(); |
| | | } |
| | | } |
| | | } |
| | | return this.nodeFlag; |
| | | } |
| | | |
| | | /** |
| | | * 简单节点编码 |
| | | * |
| | | * 逻辑:Ip地址后三位,便于快速知道是哪个节点 |
| | | * |
| | | * @return |
| | | */ |
| | | private String generateNodeFlag() { |
| | | String ipPostfix = null; |
| | | try { |
| | | String ip = IpUtils.getFirstNoLoopbackIPV4Address(); |
| | | ipPostfix = StringUtils.substringAfterLast(ip, "."); |
| | | } catch (Exception e) { |
| | | logger.warn("生产DID要素本机IP获取失败:" + e.getMessage()); |
| | | } |
| | | return StringUtils.leftPad(ipPostfix, 3, "0"); |
| | | } |
| | | |
| | | private Did() { |
| | | super(); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | } |
| | |
| | | package com.ruoyi.common.utils.ip; |
| | | |
| | | import java.net.InetAddress; |
| | | import java.net.UnknownHostException; |
| | | import java.net.*; |
| | | import java.util.ArrayList; |
| | | import java.util.Collection; |
| | | import java.util.Enumeration; |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import com.ruoyi.common.utils.ServletUtils; |
| | | import com.ruoyi.common.utils.StringUtils; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | |
| | | /** |
| | | * 获取IP方法 |
| | | * |
| | | * @author ruoyi |
| | | */ |
| | | @Slf4j |
| | | public class IpUtils |
| | | { |
| | | public final static String REGX_0_255 = "(25[0-5]|2[0-4]\\d|1\\d{2}|[1-9]\\d|\\d)"; |
| | |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | |
| | | private static final String LOOP_BACK = "127.0.0.1"; |
| | | private static String firstNoLoopbackIPV4Address = null; |
| | | |
| | | private static Collection<InetAddress> allHostIPV4Address = null; |
| | | /** |
| | | * 获取ipv4地址,如果有多个网卡的情况,获取第一个非loopback ip地址 |
| | | * |
| | | * @return |
| | | */ |
| | | public static String getFirstNoLoopbackIPV4Address() { |
| | | if (firstNoLoopbackIPV4Address != null) { |
| | | return firstNoLoopbackIPV4Address; |
| | | } |
| | | Collection<String> allNoLoopbackAddresses = null; |
| | | try { |
| | | allNoLoopbackAddresses = getAllNoLoopbackIPV4Addresses(); |
| | | } catch (Exception e) { |
| | | log.error("获取ip失败", e); |
| | | return LOOP_BACK; |
| | | } |
| | | if (allNoLoopbackAddresses.isEmpty()) { |
| | | return LOOP_BACK; |
| | | } |
| | | |
| | | return firstNoLoopbackIPV4Address = allNoLoopbackAddresses.iterator().next(); |
| | | } |
| | | |
| | | |
| | | public static Collection<String> getAllNoLoopbackIPV4Addresses() { |
| | | Collection<String> noLoopbackAddresses = new ArrayList<String>(); |
| | | Collection<InetAddress> allInetAddresses = getAllHostIPV4Address(); |
| | | |
| | | for (InetAddress address : allInetAddresses) { |
| | | if (!address.isLoopbackAddress()) { |
| | | noLoopbackAddresses.add(address.getHostAddress()); |
| | | } |
| | | } |
| | | |
| | | return noLoopbackAddresses; |
| | | } |
| | | |
| | | public static Collection<InetAddress> getAllHostIPV4Address() { |
| | | if (allHostIPV4Address == null) { |
| | | try { |
| | | Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces(); |
| | | Collection<InetAddress> addresses = new ArrayList<InetAddress>(); |
| | | |
| | | while (networkInterfaces.hasMoreElements()) { |
| | | NetworkInterface networkInterface = networkInterfaces.nextElement(); |
| | | Enumeration<InetAddress> inetAddresses = networkInterface.getInetAddresses(); |
| | | while (inetAddresses.hasMoreElements()) { |
| | | InetAddress inetAddress = inetAddresses.nextElement(); |
| | | if (inetAddress instanceof Inet4Address) { |
| | | addresses.add(inetAddress); |
| | | } |
| | | } |
| | | } |
| | | allHostIPV4Address = addresses; |
| | | } catch (SocketException e) { |
| | | log.error("获取ip地址失败", e); |
| | | throw new RuntimeException(e.getMessage(), e); |
| | | } |
| | | |
| | | } |
| | | return allHostIPV4Address; |
| | | } |
| | | } |
| | |
| | | package com.ruoyi.common.utils.poi; |
| | | |
| | | import java.io.File; |
| | | import java.io.FileOutputStream; |
| | | import java.io.IOException; |
| | | import java.io.InputStream; |
| | | import java.io.OutputStream; |
| | | import java.lang.reflect.Field; |
| | | import java.lang.reflect.Method; |
| | | import java.lang.reflect.ParameterizedType; |
| | | import java.math.BigDecimal; |
| | | import java.text.DecimalFormat; |
| | | import java.time.LocalDate; |
| | | import java.time.LocalDateTime; |
| | | import java.util.ArrayList; |
| | | import java.util.Arrays; |
| | | import java.util.Collection; |
| | | import java.util.Comparator; |
| | | import java.util.Date; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Set; |
| | | import java.util.UUID; |
| | | import java.util.stream.Collectors; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | |
| | | import com.sun.rowset.internal.Row; |
| | | import javafx.scene.control.Cell; |
| | | import org.apache.commons.io.IOUtils; |
| | | import org.apache.commons.lang3.ArrayUtils; |
| | | import org.apache.commons.lang3.RegExUtils; |
| | | import org.apache.commons.lang3.reflect.FieldUtils; |
| | | //import org.apache.poi.hssf.usermodel.HSSFClientAnchor; |
| | | //import org.apache.poi.hssf.usermodel.HSSFPicture; |
| | | //import org.apache.poi.hssf.usermodel.HSSFPictureData; |
| | | //import org.apache.poi.hssf.usermodel.HSSFShape; |
| | | //import org.apache.poi.hssf.usermodel.HSSFSheet; |
| | | //import org.apache.poi.hssf.usermodel.HSSFWorkbook; |
| | | //import org.apache.poi.ooxml.POIXMLDocumentPart; |
| | | //import org.apache.poi.ss.usermodel.BorderStyle; |
| | | //import org.apache.poi.ss.usermodel.Cell; |
| | | //import org.apache.poi.ss.usermodel.CellStyle; |
| | | //import org.apache.poi.ss.usermodel.CellType; |
| | | //import org.apache.poi.ss.usermodel.ClientAnchor; |
| | | //import org.apache.poi.ss.usermodel.DataValidation; |
| | | //import org.apache.poi.ss.usermodel.DataValidationConstraint; |
| | | //import org.apache.poi.ss.usermodel.DataValidationHelper; |
| | | //import org.apache.poi.ss.usermodel.DateUtil; |
| | | //import org.apache.poi.ss.usermodel.Drawing; |
| | | //import org.apache.poi.ss.usermodel.FillPatternType; |
| | | //import org.apache.poi.ss.usermodel.Font; |
| | | //import org.apache.poi.ss.usermodel.HorizontalAlignment; |
| | | //import org.apache.poi.ss.usermodel.IndexedColors; |
| | | //import org.apache.poi.ss.usermodel.Name; |
| | | //import org.apache.poi.ss.usermodel.PictureData; |
| | | //import org.apache.poi.ss.usermodel.Row; |
| | | //import org.apache.poi.ss.usermodel.Sheet; |
| | | //import org.apache.poi.ss.usermodel.VerticalAlignment; |
| | | //import org.apache.poi.ss.usermodel.Workbook; |
| | | //import org.apache.poi.ss.usermodel.WorkbookFactory; |
| | | //import org.apache.poi.ss.util.CellRangeAddress; |
| | | //import org.apache.poi.ss.util.CellRangeAddressList; |
| | | //import org.apache.poi.util.IOUtils; |
| | | //import org.apache.poi.xssf.streaming.SXSSFWorkbook; |
| | | //import org.apache.poi.xssf.usermodel.XSSFClientAnchor; |
| | | //import org.apache.poi.xssf.usermodel.XSSFDataValidation; |
| | | //import org.apache.poi.xssf.usermodel.XSSFDrawing; |
| | | //import org.apache.poi.xssf.usermodel.XSSFPicture; |
| | | //import org.apache.poi.xssf.usermodel.XSSFShape; |
| | | //import org.apache.poi.xssf.usermodel.XSSFSheet; |
| | | //import org.apache.poi.xssf.usermodel.XSSFWorkbook; |
| | | //import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTMarker; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | //import com.ruoyi.common.annotation.Excel; |
| | | //import com.ruoyi.common.annotation.Excel.ColumnType; |
| | | //import com.ruoyi.common.annotation.Excel.Type; |
| | | import com.ruoyi.common.annotation.Excels; |
| | | import com.ruoyi.common.config.RuoYiConfig; |
| | | import com.ruoyi.common.core.domain.AjaxResult; |
| | | import com.ruoyi.common.core.text.Convert; |
| | | import com.ruoyi.common.exception.UtilException; |
| | | import com.ruoyi.common.utils.DateUtils; |
| | | import com.ruoyi.common.utils.DictUtils; |
| | | import com.ruoyi.common.utils.StringUtils; |
| | | import com.ruoyi.common.utils.file.FileTypeUtils; |
| | | import com.ruoyi.common.utils.file.FileUtils; |
| | | import com.ruoyi.common.utils.file.ImageUtils; |
| | | import com.ruoyi.common.utils.reflect.ReflectUtils; |
| | | |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * Excel相关处理 |
| | |
| | | // 过滤请求 |
| | | .authorizeRequests() |
| | | // 对于登录login 注册register 验证码captchaImage 允许匿名访问 |
| | | .antMatchers("/getPrivacyAgreement/{agreementType}","/applet/queryProtocolConfigByType","/applet/login","/login","/applet/queryProtocolConfigByType", "/register","/applet/getCode","/applet/loginCode","/applet/changepwd", "/captchaImage","/getCode","/loginCode","/operations/getBySingleNum/**", |
| | | "/user/getUserInfoByNumber/**").permitAll() |
| | | .antMatchers("/getPrivacyAgreement/{agreementType}", |
| | | "/applet/queryProtocolConfigByType","/applet/login", |
| | | "/login","/applet/queryProtocolConfigByType", |
| | | "/register","/applet/getCode","/applet/loginCode", |
| | | "/applet/changepwd", "/captchaImage","/getCode","/loginCode", |
| | | "/operations/getBySingleNum/**", |
| | | "/user/getUserInfoByNumber/**", |
| | | "/open/**" |
| | | ).permitAll() |
| | | // 静态资源,可匿名访问 |
| | | .antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll() |
| | | .antMatchers("/swagger-ui.html","/doc.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll() |
| | |
| | | { |
| | | System.out.println("执行无参方法"); |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package com.ruoyi.system.dto; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | import javax.validation.constraints.NotBlank; |
| | | import javax.validation.constraints.NotEmpty; |
| | | import javax.validation.constraints.NotNull; |
| | | import java.io.Serializable; |
| | | import java.util.List; |
| | | |
| | | @Data |
| | | @ApiModel(value = "使用账单创建订单请求") |
| | | public class MakeOrderDto implements Serializable { |
| | | /** |
| | | * 用户ID |
| | | */ |
| | | @ApiModelProperty(value = "用户ID") |
| | | @NotBlank(message = "用户ID不能为空") |
| | | private String userId; |
| | | /** |
| | | * 用户openid |
| | | */ |
| | | @ApiModelProperty(value = "用户微信或支付宝openid") |
| | | private String openId; |
| | | |
| | | @ApiModelProperty(value = "支付金额,单位:分") |
| | | @NotNull(message = "用户ID不能为空") |
| | | private Long amount; |
| | | |
| | | @ApiModelProperty(value = "账单ID列表",notes = "如果只有1个账单ID,金额可以小于账单金额,进行部分缴费;如果是多个账单,将会核对金额,未交费金额需要与缴费金额一致") |
| | | @NotEmpty(message = "用户ID不能为空") |
| | | private List<String> billIds; |
| | | |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package com.ruoyi.system.dto; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | import java.io.Serializable; |
| | | |
| | | @Data |
| | | @ApiModel(value = "使用账单创建订单请求") |
| | | public class MakeOrderResp implements Serializable { |
| | | /** |
| | | * 订单编号 |
| | | */ |
| | | @ApiModelProperty("订单编号") |
| | | private String orderNo; |
| | | @ApiModelProperty("金额,分") |
| | | private Long amount; |
| | | @ApiModelProperty("微信小程序支付跳转链接,用于生成二维码") |
| | | private String appletUrl; |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package com.ruoyi.system.dto; |
| | | |
| | | import com.ruoyi.system.model.TBill; |
| | | import lombok.Data; |
| | | |
| | | import java.util.List; |
| | | |
| | | @Data |
| | | public class TBillDto extends TBill { |
| | | |
| | | private String residentName; |
| | | |
| | | private String phone; |
| | | |
| | | private String account; |
| | | |
| | | private String houseName; |
| | | |
| | | } |
New file |
| | |
| | | package com.ruoyi.system.dto; |
| | | |
| | | import com.ruoyi.system.model.TInvoice; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | import java.util.List; |
| | | |
| | | @Data |
| | | @ApiModel(value = "开票DTO") |
| | | public class TInvoiceDTO extends TInvoice { |
| | | |
| | | @ApiModelProperty(value = "账单id集合") |
| | | private List<String> billIds; |
| | | |
| | | } |
New file |
| | |
| | | package com.ruoyi.system.mapper; |
| | | |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.ruoyi.system.model.TBankFlow; |
| | | |
| | | /** |
| | | * <p> |
| | | * 流水管理 Mapper 接口 |
| | | * </p> |
| | | * |
| | | * @author xiaochen |
| | | * @since 2025-02-07 |
| | | */ |
| | | public interface TBankFlowMapper extends BaseMapper<TBankFlow> { |
| | | |
| | | } |
New file |
| | |
| | | package com.ruoyi.system.mapper; |
| | | |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.ruoyi.system.model.TBillConfirm; |
| | | |
| | | /** |
| | | * <p> |
| | | * 账单线下缴费关联表 Mapper 接口 |
| | | * </p> |
| | | * |
| | | * @author xiaochen |
| | | * @since 2025-02-10 |
| | | */ |
| | | public interface TBillConfirmMapper extends BaseMapper<TBillConfirm> { |
| | | |
| | | } |
New file |
| | |
| | | package com.ruoyi.system.mapper; |
| | | |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.ruoyi.system.model.TBillDetail; |
| | | |
| | | /** |
| | | * <p> |
| | | * 账单水电费子表 Mapper 接口 |
| | | * </p> |
| | | * |
| | | * @author xiaochen |
| | | * @since 2025-02-10 |
| | | */ |
| | | public interface TBillDetailMapper extends BaseMapper<TBillDetail> { |
| | | |
| | | } |
| | |
| | | package com.ruoyi.system.mapper; |
| | | |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.ruoyi.common.basic.PageInfo; |
| | | import com.ruoyi.system.dto.TBillDto; |
| | | import com.ruoyi.system.model.TBill; |
| | | import com.ruoyi.system.query.TBillQuery; |
| | | import org.apache.ibatis.annotations.Param; |
| | | import org.apache.ibatis.annotations.Select; |
| | | |
| | | /** |
| | | * <p> |
| | |
| | | */ |
| | | public interface TBillMapper extends BaseMapper<TBill> { |
| | | |
| | | PageInfo<TBillDto> page(@Param("pageInfo") PageInfo<TBill> pageInfo, @Param("query") TBillQuery query); |
| | | |
| | | } |
New file |
| | |
| | | package com.ruoyi.system.mapper; |
| | | |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.ruoyi.system.model.TInvoiceToBill; |
| | | |
| | | /** |
| | | * <p> |
| | | * 账单开票中间表 Mapper 接口 |
| | | * </p> |
| | | * |
| | | * @author xiaochen |
| | | * @since 2025-02-10 |
| | | */ |
| | | public interface TInvoiceToBillMapper extends BaseMapper<TInvoiceToBill> { |
| | | |
| | | } |
New file |
| | |
| | | package com.ruoyi.system.mapper; |
| | | |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.ruoyi.system.model.TOrderBill; |
| | | |
| | | /** |
| | | * <p> |
| | | * 订单表与账单的关联表 Mapper 接口 |
| | | * </p> |
| | | * |
| | | * @author xiaochen |
| | | * @since 2025-02-07 |
| | | */ |
| | | public interface TOrderBillMapper extends BaseMapper<TOrderBill> { |
| | | |
| | | } |
New file |
| | |
| | | package com.ruoyi.system.mapper; |
| | | |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.ruoyi.system.model.TPayOrder; |
| | | |
| | | /** |
| | | * <p> |
| | | * 支付订单表 Mapper 接口 |
| | | * </p> |
| | | * |
| | | * @author xiaochen |
| | | * @since 2025-02-07 |
| | | */ |
| | | public interface TPayOrderMapper extends BaseMapper<TPayOrder> { |
| | | |
| | | } |
New file |
| | |
| | | package com.ruoyi.system.model; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | |
| | | import java.io.Serializable; |
| | | import java.time.LocalDateTime; |
| | | |
| | | /** |
| | | * <p> |
| | | * 流水管理 |
| | | * </p> |
| | | * |
| | | * @author xiaochen |
| | | * @since 2025-02-07 |
| | | */ |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = false) |
| | | @TableName("t_bank_flow") |
| | | @ApiModel(value="TBankFlow对象", description="流水管理") |
| | | public class TBankFlow implements Serializable { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | @TableId("id") |
| | | private String id; |
| | | |
| | | @ApiModelProperty(value = "银行流水号") |
| | | @TableField("bank_serial_number") |
| | | private String bankSerialNumber; |
| | | |
| | | @ApiModelProperty(value = "流水金额") |
| | | @TableField("flow_money") |
| | | private Double flowMoney; |
| | | |
| | | @ApiModelProperty(value = "抵扣金额") |
| | | @TableField("deduction_money") |
| | | private Double deductionMoney; |
| | | |
| | | @ApiModelProperty(value = "剩余金额") |
| | | @TableField("remaining_money") |
| | | private Double remainingMoney; |
| | | |
| | | @ApiModelProperty(value = "支付时间") |
| | | @TableField("pay_time") |
| | | private LocalDateTime payTime; |
| | | |
| | | @ApiModelProperty(value = "付款人") |
| | | @TableField("payer") |
| | | private String payer; |
| | | |
| | | @ApiModelProperty(value = "流水状态 1=正常 2=异常") |
| | | @TableField("flow_status") |
| | | private Integer flowStatus; |
| | | |
| | | @ApiModelProperty(value = "支付方式 1=微信支付 2=支付宝支付 3=线下支付") |
| | | @TableField("pay_type") |
| | | private Integer payType; |
| | | |
| | | @ApiModelProperty(value = "缴费账单id") |
| | | @TableField("payment_bill_id") |
| | | private String paymentBillId; |
| | | |
| | | @ApiModelProperty(value = "创建时间") |
| | | @TableField("create_time") |
| | | private LocalDateTime createTime; |
| | | |
| | | @ApiModelProperty(value = "修改时间") |
| | | @TableField("update_time") |
| | | private LocalDateTime updateTime; |
| | | |
| | | @ApiModelProperty(value = "创建人") |
| | | @TableField("create_by") |
| | | private String createBy; |
| | | |
| | | @ApiModelProperty(value = "修改人") |
| | | @TableField("update_by") |
| | | private String updateBy; |
| | | |
| | | @ApiModelProperty(value = "是否删除 0=否 1=是") |
| | | @TableField("disabled") |
| | | private Integer disabled; |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package com.ruoyi.system.model; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.IdType; |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | |
| | | import java.io.Serializable; |
| | | |
| | | /** |
| | | * <p> |
| | | * 账单线下缴费关联表 |
| | | * </p> |
| | | * |
| | | * @author xiaochen |
| | | * @since 2025-02-10 |
| | | */ |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = false) |
| | | @TableName("t_bill_confirm") |
| | | @ApiModel(value="TBillConfirm对象", description="账单线下缴费关联表") |
| | | public class TBillConfirm implements Serializable { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | @TableId(value = "id", type = IdType.ASSIGN_ID) |
| | | private String id; |
| | | |
| | | @ApiModelProperty(value = "账单id,逗号分隔") |
| | | @TableField("bill_id") |
| | | private String billId; |
| | | |
| | | @ApiModelProperty(value = "缴费金额") |
| | | @TableField("pay_fees_money") |
| | | private Double payFeesMoney; |
| | | |
| | | @ApiModelProperty(value = "凭证上传") |
| | | @TableField("voucher") |
| | | private String voucher; |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package com.ruoyi.system.model; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.IdType; |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import com.ruoyi.common.core.domain.BaseModel; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | |
| | | import java.io.Serializable; |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDateTime; |
| | | |
| | | /** |
| | | * <p> |
| | | * 账单水电费子表 |
| | | * </p> |
| | | * |
| | | * @author xiaochen |
| | | * @since 2025-02-10 |
| | | */ |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = false) |
| | | @TableName("t_bill_detail") |
| | | @ApiModel(value="TBillDetail对象", description="账单水电费子表") |
| | | public class TBillDetail extends BaseModel { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | @TableId(value = "id", type = IdType.ASSIGN_ID) |
| | | private String id; |
| | | |
| | | @ApiModelProperty(value = "账单id") |
| | | @TableField("bill_id") |
| | | private String billId; |
| | | |
| | | @ApiModelProperty(value = "初始读数") |
| | | @TableField("start_reading") |
| | | private BigDecimal startReading; |
| | | |
| | | @ApiModelProperty(value = "结束读数") |
| | | @TableField("end_reading") |
| | | private BigDecimal endReading; |
| | | |
| | | @ApiModelProperty(value = "使用量") |
| | | @TableField("usage_measure") |
| | | private BigDecimal usageMeasure; |
| | | |
| | | @ApiModelProperty(value = "单价") |
| | | @TableField("unit_price") |
| | | private BigDecimal unitPrice; |
| | | |
| | | @ApiModelProperty(value = "总金额") |
| | | @TableField("total_amount") |
| | | private BigDecimal totalAmount; |
| | | |
| | | @ApiModelProperty(value = "费用类型 1=水费 2=电费") |
| | | @TableField("live_type") |
| | | private Integer liveType; |
| | | |
| | | } |
New file |
| | |
| | | package com.ruoyi.system.model; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.IdType; |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | |
| | | import java.io.Serializable; |
| | | |
| | | /** |
| | | * <p> |
| | | * 账单开票中间表 |
| | | * </p> |
| | | * |
| | | * @author xiaochen |
| | | * @since 2025-02-10 |
| | | */ |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = false) |
| | | @TableName("t_invoice_to_bill") |
| | | @ApiModel(value="TInvoiceToBill对象", description="账单开票中间表") |
| | | public class TInvoiceToBill implements Serializable { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | @TableId(value = "id", type = IdType.ASSIGN_ID) |
| | | private String id; |
| | | |
| | | @ApiModelProperty(value = "开票id") |
| | | @TableField("invoice_id") |
| | | private String invoiceId; |
| | | |
| | | @ApiModelProperty(value = "账单id") |
| | | @TableField("bill_id") |
| | | private String billId; |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package com.ruoyi.system.model; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.IdType; |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | import java.io.Serializable; |
| | | import java.time.LocalDateTime; |
| | | |
| | | /** |
| | | * <p> |
| | | * 订单表与账单的关联表 |
| | | * </p> |
| | | * |
| | | * @author xiaochen |
| | | * @since 2025-02-07 |
| | | */ |
| | | @Data |
| | | @NoArgsConstructor |
| | | @EqualsAndHashCode(callSuper = false) |
| | | @TableName("t_order_bill") |
| | | @ApiModel(value="TOrderBill对象", description="订单表与账单的关联表") |
| | | public class TOrderBill implements Serializable { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | @TableId(value = "id", type = IdType.ASSIGN_ID) |
| | | private String id; |
| | | |
| | | @ApiModelProperty(value = "订单号") |
| | | @TableField("order_no") |
| | | private String orderNo; |
| | | |
| | | @ApiModelProperty(value = "账单编号") |
| | | @TableField("bill_id") |
| | | private String billId; |
| | | |
| | | @TableField("create_time") |
| | | private LocalDateTime createTime; |
| | | |
| | | @TableField("update_time") |
| | | private LocalDateTime updateTime; |
| | | |
| | | public TOrderBill(String orderNo, String billId) { |
| | | this.orderNo = orderNo; |
| | | this.billId = billId; |
| | | } |
| | | } |
New file |
| | |
| | | package com.ruoyi.system.model; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.IdType; |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | |
| | | import java.io.Serializable; |
| | | import java.time.LocalDateTime; |
| | | |
| | | /** |
| | | * <p> |
| | | * 支付订单表 |
| | | * </p> |
| | | * |
| | | * @author xiaochen |
| | | * @since 2025-02-07 |
| | | */ |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = false) |
| | | @TableName("t_pay_order") |
| | | @ApiModel(value="TPayOrder对象", description="支付订单表") |
| | | public class TPayOrder implements Serializable { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | @ApiModelProperty(value = "订单号") |
| | | @TableId("id") |
| | | private String id; |
| | | |
| | | @ApiModelProperty(value = "发起支付的用户ID") |
| | | @TableField("user_id") |
| | | private String userId; |
| | | |
| | | @ApiModelProperty(value = "用户名称") |
| | | @TableField("user_name") |
| | | private String userName; |
| | | |
| | | @ApiModelProperty(value = "用户微信openid或支付宝userid") |
| | | @TableField("open_id") |
| | | private String openId; |
| | | |
| | | @ApiModelProperty(value = "用户手机号码") |
| | | @TableField("phone") |
| | | private String phone; |
| | | |
| | | @ApiModelProperty(value = "订单金额") |
| | | @TableField("amount") |
| | | private Long amount; |
| | | |
| | | @ApiModelProperty(value = "实付金额") |
| | | @TableField("act_pay_amount") |
| | | private Long actPayAmount; |
| | | |
| | | @ApiModelProperty(value = "支付时间") |
| | | @TableField("pay_time") |
| | | private LocalDateTime payTime; |
| | | |
| | | @ApiModelProperty(value = "支付方式") |
| | | @TableField("pay_type") |
| | | private String payType; |
| | | |
| | | @ApiModelProperty(value = "支付的回调信息") |
| | | @TableField("pay_info") |
| | | private String payInfo; |
| | | |
| | | @ApiModelProperty(value = "银行的支付流水编号") |
| | | @TableField("pay_no") |
| | | private String payNo; |
| | | |
| | | @ApiModelProperty(value = "支付的回调时间") |
| | | @TableField("callback_time") |
| | | private LocalDateTime callbackTime; |
| | | |
| | | @ApiModelProperty(value = "订单创建时间") |
| | | @TableField("create_time") |
| | | private LocalDateTime createTime; |
| | | |
| | | @ApiModelProperty(value = "订单更新时间") |
| | | @TableField("update_time") |
| | | private LocalDateTime updateTime; |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package com.ruoyi.system.query; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import com.ruoyi.common.core.domain.BasePage; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | |
| | | import java.io.Serializable; |
| | | import java.time.LocalDateTime; |
| | | |
| | | /** |
| | | * <p> |
| | | * 流水管理 |
| | | * </p> |
| | | * |
| | | * @author xiaochen |
| | | * @since 2025-02-07 |
| | | */ |
| | | @Data |
| | | @ApiModel(value="银行流水列表query") |
| | | public class TBankFlowQuery extends BasePage { |
| | | |
| | | @ApiModelProperty(value = "银行流水号") |
| | | private String bankSerialNumber; |
| | | |
| | | @ApiModelProperty(value = "流水金额") |
| | | private Double flowMoney; |
| | | |
| | | @ApiModelProperty(value = "抵扣金额") |
| | | private Double deductionMoney; |
| | | |
| | | @ApiModelProperty(value = "剩余金额") |
| | | private Double remainingMoney; |
| | | |
| | | @ApiModelProperty(value = "支付时间") |
| | | private LocalDateTime payTime; |
| | | |
| | | @ApiModelProperty(value = "付款人") |
| | | private String payer; |
| | | |
| | | @ApiModelProperty(value = "流水状态 1=正常 2=异常") |
| | | private Integer flowStatus; |
| | | |
| | | @ApiModelProperty(value = "支付方式 1=微信支付 2=支付宝支付 3=线下支付") |
| | | private Integer payType; |
| | | |
| | | @ApiModelProperty(value = "缴费账单id") |
| | | private String paymentBillId; |
| | | |
| | | @ApiModelProperty(value = "支付开始时间") |
| | | private String payStartTime; |
| | | |
| | | @ApiModelProperty(value = "支付结束时间") |
| | | private String payEndTime; |
| | | |
| | | } |
| | |
| | | package com.ruoyi.system.query; |
| | | |
| | | import com.ruoyi.common.core.domain.BasePage; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | @Data |
| | | @ApiModel(value = "账单查询对象query") |
| | | public class TBillQuery extends BasePage { |
| | | /** |
| | | * 缴费状态 1=未缴费 2=待确认 3=已缴费 4=已逾期 |
| | | */ |
| | | @ApiModelProperty("缴费状态 1=未缴费 2=待确认 3=已缴费 4=已逾期") |
| | | private Integer payFeesStatus; |
| | | @ApiModelProperty("联系电话") |
| | | private String phone; |
| | | @ApiModelProperty("租户名称") |
| | | private String residentName; |
| | | @ApiModelProperty("合同编号") |
| | | private String contractNumber; |
| | | /** |
| | | * 租户ID |
| | | */ |
| | | @ApiModelProperty("租户ID") |
| | | private String userId; |
| | | |
| | | @ApiModelProperty(value = "缴费状态 1=未缴费 2=待确认 3=已缴费 4=已逾期 5=已失效") |
| | | private String payFeesStatus; |
| | | |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package com.ruoyi.system.query; |
| | | |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import com.ruoyi.common.core.domain.BasePage; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDateTime; |
| | | |
| | | /** |
| | | * <p> |
| | | * 流水管理 |
| | | * </p> |
| | | * |
| | | * @author xiaochen |
| | | * @since 2025-01-20 |
| | | */ |
| | | @Data |
| | | @ApiModel(value="流水列表query") |
| | | public class TFlowManagementQuery extends BasePage { |
| | | |
| | | @ApiModelProperty(value = "系统流水号") |
| | | private String sysSerialNumber; |
| | | |
| | | @ApiModelProperty(value = "银行流水号") |
| | | private String bankSerialNumber; |
| | | |
| | | @ApiModelProperty(value = "流水金额") |
| | | private BigDecimal flowMoney; |
| | | |
| | | @ApiModelProperty(value = "抵扣金额") |
| | | private BigDecimal deductionMoney; |
| | | |
| | | @ApiModelProperty(value = "剩余金额") |
| | | private BigDecimal remainingMoney; |
| | | |
| | | @ApiModelProperty(value = "支付时间") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") |
| | | private LocalDateTime payTime; |
| | | |
| | | @ApiModelProperty(value = "付款人") |
| | | private String payer; |
| | | |
| | | @ApiModelProperty(value = "流水状态 1=正常 2=异常") |
| | | private Integer flowStatus; |
| | | |
| | | |
| | | @ApiModelProperty(value = "支付方式 1=微信支付 2=支付宝支付 3=线下支付") |
| | | private Integer payType; |
| | | |
| | | @ApiModelProperty(value = "缴费账单id") |
| | | private String paymentBillId; |
| | | |
| | | @ApiModelProperty(value = "支付开始时间") |
| | | private String payStartTime; |
| | | |
| | | @ApiModelProperty(value = "支付结束时间") |
| | | private String payEndTime; |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package com.ruoyi.system.query; |
| | | |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import com.ruoyi.common.core.domain.BasePage; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | import java.time.LocalDateTime; |
| | | |
| | | |
| | | @Data |
| | | @ApiModel(value="开票查询列表Query") |
| | | public class TInvoiceQuery extends BasePage { |
| | | @ApiModelProperty(value = "申请编号") |
| | | private String invoiceNumber; |
| | | |
| | | @ApiModelProperty(value = "金额") |
| | | private Double invoiceMoney; |
| | | |
| | | @ApiModelProperty(value = "申请人") |
| | | private String applyName; |
| | | |
| | | @ApiModelProperty(value = "抬头类型 1=企业 2=个人") |
| | | private Integer titleType; |
| | | |
| | | @ApiModelProperty(value = "抬头名称") |
| | | private String titleName; |
| | | |
| | | @ApiModelProperty(value = "税号/身份证号") |
| | | private String serialNumber; |
| | | |
| | | @ApiModelProperty(value = "开票状态 1=待开票 2=已开票") |
| | | private Integer status; |
| | | |
| | | @ApiModelProperty(value = "开票日期") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") |
| | | private LocalDateTime invoiceTime; |
| | | |
| | | @ApiModelProperty(value = "开票凭证") |
| | | private String invoiceVoucher; |
| | | |
| | | @ApiModelProperty(value = "邮箱") |
| | | private String email; |
| | | |
| | | @ApiModelProperty(value = "开票合同编号逗号分割") |
| | | private String contractNumber; |
| | | |
| | | @ApiModelProperty(value = "开票开始日期") |
| | | private String invoiceStartTime; |
| | | |
| | | @ApiModelProperty(value = "开票结束日期") |
| | | private String invoiceEndTime; |
| | | |
| | | } |
New file |
| | |
| | | package com.ruoyi.system.service; |
| | | |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import com.ruoyi.common.basic.PageInfo; |
| | | import com.ruoyi.system.model.TBankFlow; |
| | | import com.ruoyi.system.model.TFlowManagement; |
| | | import com.ruoyi.system.query.TBankFlowQuery; |
| | | import com.ruoyi.system.query.TFlowManagementQuery; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * <p> |
| | | * 流水管理 服务类 |
| | | * </p> |
| | | * |
| | | * @author xiaochen |
| | | * @since 2025-02-07 |
| | | */ |
| | | public interface TBankFlowService extends IService<TBankFlow> { |
| | | |
| | | PageInfo<TBankFlow> pageList(TBankFlowQuery query); |
| | | List<TBankFlow> makeQuery(TBankFlowQuery query); |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package com.ruoyi.system.service; |
| | | |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import com.ruoyi.system.model.TBillConfirm; |
| | | |
| | | /** |
| | | * <p> |
| | | * 账单线下缴费关联表 服务类 |
| | | * </p> |
| | | * |
| | | * @author xiaochen |
| | | * @since 2025-02-10 |
| | | */ |
| | | public interface TBillConfirmService extends IService<TBillConfirm> { |
| | | |
| | | } |
New file |
| | |
| | | package com.ruoyi.system.service; |
| | | |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import com.ruoyi.system.model.TBillDetail; |
| | | |
| | | /** |
| | | * <p> |
| | | * 账单水电费子表 服务类 |
| | | * </p> |
| | | * |
| | | * @author xiaochen |
| | | * @since 2025-02-10 |
| | | */ |
| | | public interface TBillDetailService extends IService<TBillDetail> { |
| | | |
| | | } |
| | |
| | | |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import com.ruoyi.common.basic.PageInfo; |
| | | import com.ruoyi.system.dto.TBillDto; |
| | | import com.ruoyi.system.model.TBill; |
| | | import com.ruoyi.system.query.TBillQuery; |
| | | import com.ruoyi.system.vo.TBillVO; |
| | | |
| | | /** |
| | | * <p> |
| | |
| | | */ |
| | | public interface TBillService extends IService<TBill> { |
| | | |
| | | /** |
| | | * 获取账单列表 |
| | | * @param query |
| | | * @return |
| | | */ |
| | | PageInfo<TBillVO> pageList(TBillQuery query); |
| | | PageInfo<TBillDto> queryPage(TBillQuery query); |
| | | |
| | | } |
| | |
| | | package com.ruoyi.system.service; |
| | | |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import com.ruoyi.common.basic.PageInfo; |
| | | import com.ruoyi.system.model.TFlowManagement; |
| | | import com.ruoyi.system.query.TFlowManagementQuery; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * <p> |
| | |
| | | * @since 2025-01-17 |
| | | */ |
| | | public interface TFlowManagementService extends IService<TFlowManagement> { |
| | | PageInfo<TFlowManagement> pageList(TFlowManagementQuery query); |
| | | List<TFlowManagement> makeQuery(TFlowManagementQuery query); |
| | | |
| | | |
| | | |
| | | } |
| | |
| | | package com.ruoyi.system.service; |
| | | |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import com.ruoyi.common.basic.PageInfo; |
| | | import com.ruoyi.system.model.TInvoice; |
| | | import com.ruoyi.system.query.TInvoiceQuery; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * <p> |
| | |
| | | * @since 2025-01-17 |
| | | */ |
| | | public interface TInvoiceService extends IService<TInvoice> { |
| | | |
| | | PageInfo<TInvoice> pageList(TInvoiceQuery query); |
| | | List<TInvoice> makeQuery(TInvoiceQuery query); |
| | | } |
New file |
| | |
| | | package com.ruoyi.system.service; |
| | | |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import com.ruoyi.system.model.TInvoiceToBill; |
| | | |
| | | /** |
| | | * <p> |
| | | * 账单开票中间表 服务类 |
| | | * </p> |
| | | * |
| | | * @author xiaochen |
| | | * @since 2025-02-10 |
| | | */ |
| | | public interface TInvoiceToBillService extends IService<TInvoiceToBill> { |
| | | |
| | | } |
New file |
| | |
| | | package com.ruoyi.system.service; |
| | | |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import com.ruoyi.system.model.TOrderBill; |
| | | |
| | | /** |
| | | * <p> |
| | | * 订单表与账单的关联表 服务类 |
| | | * </p> |
| | | * |
| | | * @author xiaochen |
| | | * @since 2025-02-07 |
| | | */ |
| | | public interface TOrderBillService extends IService<TOrderBill> { |
| | | |
| | | } |
New file |
| | |
| | | package com.ruoyi.system.service; |
| | | |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import com.ruoyi.system.dto.MakeOrderDto; |
| | | import com.ruoyi.system.dto.MakeOrderResp; |
| | | import com.ruoyi.system.model.TPayOrder; |
| | | |
| | | /** |
| | | * <p> |
| | | * 支付订单表 服务类 |
| | | * </p> |
| | | * |
| | | * @author xiaochen |
| | | * @since 2025-02-07 |
| | | */ |
| | | public interface TPayOrderService extends IService<TPayOrder> { |
| | | |
| | | MakeOrderResp makeOrder(MakeOrderDto dto); |
| | | } |
New file |
| | |
| | | package com.ruoyi.system.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.common.basic.PageInfo; |
| | | import com.ruoyi.common.utils.StringUtils; |
| | | import com.ruoyi.system.mapper.TBankFlowMapper; |
| | | import com.ruoyi.system.model.TBankFlow; |
| | | import com.ruoyi.system.model.TFlowManagement; |
| | | import com.ruoyi.system.query.TBankFlowQuery; |
| | | import com.ruoyi.system.service.TBankFlowService; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * <p> |
| | | * 流水管理 服务实现类 |
| | | * </p> |
| | | * |
| | | * @author xiaochen |
| | | * @since 2025-02-07 |
| | | */ |
| | | @Service |
| | | public class TBankFlowServiceImpl extends ServiceImpl<TBankFlowMapper, TBankFlow> implements TBankFlowService { |
| | | @Override |
| | | public PageInfo<TBankFlow> pageList(TBankFlowQuery query) { |
| | | PageInfo<TBankFlow> pageInfo = new PageInfo<>(query.getPageNum(), query.getPageSize()); |
| | | List<TBankFlow> list = makeQuery(query); |
| | | pageInfo.setRecords(list); |
| | | pageInfo.setTotal(list.size()); |
| | | return pageInfo; |
| | | } |
| | | @Override |
| | | public List<TBankFlow> makeQuery(TBankFlowQuery query) { |
| | | LambdaQueryWrapper<TBankFlow> queryWrapper = new LambdaQueryWrapper<>(); |
| | | queryWrapper.eq(StringUtils.isNotEmpty(query.getBankSerialNumber()),TBankFlow::getBankSerialNumber,query.getBankSerialNumber()) |
| | | .like(StringUtils.isNotEmpty(query.getPayer()),TBankFlow::getPayer,query.getPayer()) |
| | | .ge(StringUtils.isNotEmpty(query.getPayStartTime()),TBankFlow::getPayTime,query.getPayStartTime()) |
| | | .lt(StringUtils.isNotEmpty(query.getPayEndTime()),TBankFlow::getPayTime,query.getPayEndTime()) |
| | | .eq(null != query.getFlowStatus(),TBankFlow::getFlowStatus,query.getFlowStatus()) |
| | | .orderByDesc(TBankFlow::getCreateTime) |
| | | ; |
| | | return this.baseMapper.selectList(queryWrapper); |
| | | } |
| | | } |
New file |
| | |
| | | package com.ruoyi.system.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.system.mapper.TBillConfirmMapper; |
| | | import com.ruoyi.system.model.TBillConfirm; |
| | | import com.ruoyi.system.service.TBillConfirmService; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | /** |
| | | * <p> |
| | | * 账单线下缴费关联表 服务实现类 |
| | | * </p> |
| | | * |
| | | * @author xiaochen |
| | | * @since 2025-02-10 |
| | | */ |
| | | @Service |
| | | public class TBillConfirmServiceImpl extends ServiceImpl<TBillConfirmMapper, TBillConfirm> implements TBillConfirmService { |
| | | |
| | | } |
New file |
| | |
| | | package com.ruoyi.system.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.system.mapper.TBillDetailMapper; |
| | | import com.ruoyi.system.model.TBillDetail; |
| | | import com.ruoyi.system.service.TBillDetailService; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | /** |
| | | * <p> |
| | | * 账单水电费子表 服务实现类 |
| | | * </p> |
| | | * |
| | | * @author xiaochen |
| | | * @since 2025-02-10 |
| | | */ |
| | | @Service |
| | | public class TBillDetailServiceImpl extends ServiceImpl<TBillDetailMapper, TBillDetail> implements TBillDetailService { |
| | | |
| | | } |
| | |
| | | package com.ruoyi.system.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.ruoyi.common.basic.PageInfo; |
| | | import com.ruoyi.common.core.domain.AjaxResult; |
| | | import com.ruoyi.common.core.redis.RedisCache; |
| | | import com.ruoyi.system.dto.TBillDto; |
| | | import com.ruoyi.system.mapper.TBillMapper; |
| | | import com.ruoyi.system.model.TBill; |
| | | import com.ruoyi.system.model.TContract; |
| | | import com.ruoyi.system.model.THouse; |
| | | import com.ruoyi.system.query.TBillQuery; |
| | | import com.ruoyi.system.service.TBillService; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.system.vo.TBillVO; |
| | | import io.jsonwebtoken.lang.Assert; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.time.LocalDateTime; |
| | | |
| | | /** |
| | | * <p> |
| | |
| | | @Service |
| | | public class TBillServiceImpl extends ServiceImpl<TBillMapper, TBill> implements TBillService { |
| | | |
| | | @Override |
| | | public PageInfo<TBillVO> pageList(TBillQuery query) { |
| | | return null; |
| | | @Autowired |
| | | RedisCache redisCache; |
| | | |
| | | @Autowired |
| | | TBillMapper tBillMapper; |
| | | |
| | | public PageInfo<TBillDto> queryPage(TBillQuery query){ |
| | | PageInfo<TBill> pageInfo = new PageInfo<>(query.getPageNum(), query.getPageSize()); |
| | | PageInfo<TBillDto> info = tBillMapper.page(pageInfo, query); |
| | | return info; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 传的金额 |
| | | * @param tBill |
| | | * @return |
| | | */ |
| | | public Boolean checkAndUpdateBill(TBill tBill){ |
| | | return true; |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | } |
| | |
| | | package com.ruoyi.system.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.ruoyi.common.basic.PageInfo; |
| | | import com.ruoyi.common.utils.StringUtils; |
| | | import com.ruoyi.system.mapper.TFlowManagementMapper; |
| | | import com.ruoyi.system.model.TFlowManagement; |
| | | import com.ruoyi.system.query.TFlowManagementQuery; |
| | | import com.ruoyi.system.service.TFlowManagementService; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * <p> |
| | |
| | | @Service |
| | | public class TFlowManagementServiceImpl extends ServiceImpl<TFlowManagementMapper, TFlowManagement> implements TFlowManagementService { |
| | | |
| | | @Override |
| | | public PageInfo<TFlowManagement> pageList(TFlowManagementQuery query) { |
| | | PageInfo<TFlowManagement> pageInfo = new PageInfo<>(query.getPageNum(), query.getPageSize()); |
| | | List<TFlowManagement> list = makeQuery(query); |
| | | pageInfo.setRecords(list); |
| | | pageInfo.setTotal(list.size()); |
| | | return pageInfo; |
| | | } |
| | | @Override |
| | | public List<TFlowManagement> makeQuery(TFlowManagementQuery query){ |
| | | LambdaQueryWrapper<TFlowManagement> queryWrapper = new LambdaQueryWrapper<>(); |
| | | queryWrapper.eq(StringUtils.isNotEmpty(query.getSysSerialNumber()),TFlowManagement::getSysSerialNumber,query.getSysSerialNumber()) |
| | | .eq(StringUtils.isNotEmpty(query.getBankSerialNumber()),TFlowManagement::getBankSerialNumber,query.getBankSerialNumber()) |
| | | .like(StringUtils.isNotEmpty(query.getPayer()),TFlowManagement::getPayer,query.getPayer()) |
| | | .ge(StringUtils.isNotEmpty(query.getPayStartTime()),TFlowManagement::getPayTime,query.getPayStartTime()) |
| | | .lt(StringUtils.isNotEmpty(query.getPayEndTime()),TFlowManagement::getPayTime,query.getPayEndTime()) |
| | | .eq(null != query.getFlowStatus(),TFlowManagement::getFlowStatus,query.getFlowStatus()) |
| | | .orderByDesc(TFlowManagement::getCreateTime) |
| | | ; |
| | | return this.baseMapper.selectList(queryWrapper); |
| | | } |
| | | } |
| | |
| | | package com.ruoyi.system.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.ruoyi.common.basic.PageInfo; |
| | | import com.ruoyi.common.utils.StringUtils; |
| | | import com.ruoyi.system.mapper.TInvoiceMapper; |
| | | import com.ruoyi.system.model.TInvoice; |
| | | import com.ruoyi.system.query.TInvoiceQuery; |
| | | import com.ruoyi.system.service.TInvoiceService; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * <p> |
| | |
| | | @Service |
| | | public class TInvoiceServiceImpl extends ServiceImpl<TInvoiceMapper, TInvoice> implements TInvoiceService { |
| | | |
| | | @Override |
| | | public PageInfo<TInvoice> pageList(TInvoiceQuery query) { |
| | | PageInfo<TInvoice> pageInfo = new PageInfo<>(query.getPageNum(), query.getPageSize()); |
| | | List<TInvoice> list = makeQuery(query); |
| | | pageInfo.setRecords(list); |
| | | pageInfo.setTotal(list.size()); |
| | | return pageInfo; |
| | | } |
| | | |
| | | @Override |
| | | public List<TInvoice> makeQuery(TInvoiceQuery query) { |
| | | LambdaQueryWrapper<TInvoice> queryWrapper = new LambdaQueryWrapper<>(); |
| | | queryWrapper.eq(null != query.getTitleType(),TInvoice::getTitleType,query.getTitleType()) |
| | | .like(StringUtils.isNotEmpty(query.getTitleName()),TInvoice::getTitleName,query.getTitleName()) |
| | | .eq(null != query.getStatus(),TInvoice::getStatus,query.getStatus()) |
| | | .ge(StringUtils.isNotEmpty(query.getInvoiceStartTime()),TInvoice::getInvoiceTime,query.getInvoiceStartTime()) |
| | | .le(StringUtils.isNotEmpty(query.getInvoiceEndTime()),TInvoice::getInvoiceTime,query.getInvoiceEndTime()) |
| | | .orderByDesc(TInvoice::getCreateTime); |
| | | return this.baseMapper.selectList(queryWrapper); |
| | | } |
| | | } |
New file |
| | |
| | | package com.ruoyi.system.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.system.mapper.TInvoiceToBillMapper; |
| | | import com.ruoyi.system.model.TInvoiceToBill; |
| | | import com.ruoyi.system.service.TInvoiceToBillService; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | /** |
| | | * <p> |
| | | * 账单开票中间表 服务实现类 |
| | | * </p> |
| | | * |
| | | * @author xiaochen |
| | | * @since 2025-02-10 |
| | | */ |
| | | @Service |
| | | public class TInvoiceToBillServiceImpl extends ServiceImpl<TInvoiceToBillMapper, TInvoiceToBill> implements TInvoiceToBillService { |
| | | |
| | | } |
New file |
| | |
| | | package com.ruoyi.system.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.system.mapper.TOrderBillMapper; |
| | | import com.ruoyi.system.model.TOrderBill; |
| | | import com.ruoyi.system.service.TOrderBillService; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | /** |
| | | * <p> |
| | | * 订单表与账单的关联表 服务实现类 |
| | | * </p> |
| | | * |
| | | * @author xiaochen |
| | | * @since 2025-02-07 |
| | | */ |
| | | @Service |
| | | public class TOrderBillServiceImpl extends ServiceImpl<TOrderBillMapper, TOrderBill> implements TOrderBillService { |
| | | |
| | | } |
New file |
| | |
| | | package com.ruoyi.system.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.common.constant.AmountConstant; |
| | | import com.ruoyi.common.exception.ServiceException; |
| | | import com.ruoyi.common.utils.OrderNos; |
| | | import com.ruoyi.system.dto.MakeOrderDto; |
| | | import com.ruoyi.system.dto.MakeOrderResp; |
| | | import com.ruoyi.system.mapper.TPayOrderMapper; |
| | | import com.ruoyi.system.model.TBill; |
| | | import com.ruoyi.system.model.TOrderBill; |
| | | import com.ruoyi.system.model.TPayOrder; |
| | | import com.ruoyi.system.model.TTenant; |
| | | import com.ruoyi.system.service.TBillService; |
| | | import com.ruoyi.system.service.TOrderBillService; |
| | | import com.ruoyi.system.service.TPayOrderService; |
| | | import com.ruoyi.system.service.TTenantService; |
| | | import org.apache.poi.ss.formula.functions.T; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.math.RoundingMode; |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * <p> |
| | | * 支付订单表 服务实现类 |
| | | * </p> |
| | | * |
| | | * @author xiaochen |
| | | * @since 2025-02-07 |
| | | */ |
| | | @Service |
| | | public class TPayOrderServiceImpl extends ServiceImpl<TPayOrderMapper, TPayOrder> implements TPayOrderService { |
| | | |
| | | @Autowired |
| | | TBillService billService; |
| | | |
| | | @Autowired |
| | | TTenantService tTenantService; |
| | | |
| | | @Autowired |
| | | TOrderBillService tOrderBillService; |
| | | |
| | | |
| | | public long caculateRentFee(TBill bill){ |
| | | return bill.getOutstandingMoney() |
| | | .longValue(); |
| | | } |
| | | |
| | | |
| | | public String createAppletUrl(String orderNo){ |
| | | return ""+orderNo; |
| | | } |
| | | |
| | | @Override |
| | | public MakeOrderResp makeOrder(MakeOrderDto dto) { |
| | | |
| | | TTenant user = tTenantService.getById(dto.getUserId()); |
| | | if (user==null){ |
| | | throw new ServiceException("租户不存在"); |
| | | } |
| | | MakeOrderResp resp = new MakeOrderResp(); |
| | | if (dto.getBillIds().size()==1){ |
| | | TBill bill = billService.getById(dto.getBillIds().get(0)); |
| | | if (bill == null) { |
| | | throw new ServiceException("账单不存在"); |
| | | } |
| | | //计算欠费金额:租金+违约金-实收金额 |
| | | long rent = caculateRentFee(bill); |
| | | if (rent==0){ |
| | | throw new ServiceException("该订单已缴费"); |
| | | } |
| | | if (rent>dto.getAmount()){ |
| | | throw new ServiceException("支付金额超过了账单欠费金额"); |
| | | } |
| | | |
| | | TPayOrder order = new TPayOrder(); |
| | | order.setId(OrderNos.getDid(32)); |
| | | order.setAmount(dto.getAmount()); |
| | | order.setUserId(user.getId()); |
| | | order.setPhone(user.getPhone()); |
| | | order.setOpenId(dto.getOpenId()); |
| | | order.setUserName(user.getResidentName()); |
| | | save(order); |
| | | TOrderBill tOrderBill = new TOrderBill(); |
| | | tOrderBill.setBillId(bill.getId()); |
| | | tOrderBill.setOrderNo(order.getId()); |
| | | tOrderBillService.save(tOrderBill); |
| | | resp.setAmount(dto.getAmount()); |
| | | resp.setOrderNo(order.getId()); |
| | | resp.setAppletUrl(createAppletUrl(order.getId())); |
| | | return resp; |
| | | } |
| | | List<TOrderBill> orderBills = new ArrayList<>(); |
| | | String orderNo = OrderNos.getDid(32); |
| | | List<TBill> bills = dto.getBillIds().stream().map(id -> { |
| | | TBill bill = billService.getById(id); |
| | | if (bill == null) { |
| | | throw new ServiceException("billId:" + id + "不存在"); |
| | | } |
| | | orderBills.add(new TOrderBill(orderNo,bill.getId())); |
| | | return bill; |
| | | }).collect(Collectors.toList()); |
| | | long sumRent = bills.stream().mapToLong((bill) -> caculateRentFee(bill)).sum(); |
| | | if (sumRent==0){ |
| | | throw new ServiceException("账单已缴费"); |
| | | } |
| | | if (dto.getAmount()>sumRent){ |
| | | throw new ServiceException("支付金额超过所选账单欠费金额"); |
| | | } |
| | | TPayOrder order = new TPayOrder(); |
| | | order.setId(orderNo); |
| | | order.setAmount(dto.getAmount()); |
| | | order.setUserId(user.getId()); |
| | | order.setPhone(user.getPhone()); |
| | | order.setOpenId(dto.getOpenId()); |
| | | order.setUserName(user.getResidentName()); |
| | | save(order); |
| | | tOrderBillService.saveBatch(orderBills); |
| | | resp.setAmount(dto.getAmount()); |
| | | resp.setOrderNo(orderNo); |
| | | resp.setAppletUrl(createAppletUrl(orderNo)); |
| | | return resp; |
| | | } |
| | | } |
| | |
| | | package com.ruoyi.system.vo; |
| | | |
| | | import com.ruoyi.system.model.TBill; |
| | | import com.ruoyi.system.model.TBillDetail; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | import java.util.List; |
| | | |
| | | @Data |
| | | @ApiModel(value = "缴费账单VO") |
| | | public class TBillVO extends TBill { |
| | | |
| | | @ApiModelProperty(value = "水电费明细") |
| | | private List<TBillDetail> billDetailList; |
| | | |
| | | } |
New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
| | | <mapper namespace="com.ruoyi.system.mapper.TBankFlowMapper"> |
| | | |
| | | <!-- 通用查询映射结果 --> |
| | | <resultMap id="BaseResultMap" type="com.ruoyi.system.model.TBankFlow"> |
| | | <id column="id" property="id" /> |
| | | <result column="bank_serial_number" property="bankSerialNumber" /> |
| | | <result column="flow_money" property="flowMoney" /> |
| | | <result column="deduction_money" property="deductionMoney" /> |
| | | <result column="remaining_money" property="remainingMoney" /> |
| | | <result column="pay_time" property="payTime" /> |
| | | <result column="payer" property="payer" /> |
| | | <result column="flow_status" property="flowStatus" /> |
| | | <result column="pay_type" property="payType" /> |
| | | <result column="payment_bill_id" property="paymentBillId" /> |
| | | <result column="create_time" property="createTime" /> |
| | | <result column="update_time" property="updateTime" /> |
| | | <result column="create_by" property="createBy" /> |
| | | <result column="update_by" property="updateBy" /> |
| | | <result column="disabled" property="disabled" /> |
| | | </resultMap> |
| | | |
| | | <!-- 通用查询结果列 --> |
| | | <sql id="Base_Column_List"> |
| | | id, bank_serial_number, flow_money, deduction_money, remaining_money, pay_time, payer, flow_status, pay_type, payment_bill_id, create_time, update_time, create_by, update_by, disabled |
| | | </sql> |
| | | |
| | | </mapper> |
New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
| | | <mapper namespace="com.ruoyi.system.mapper.TBillConfirmMapper"> |
| | | |
| | | <!-- 通用查询映射结果 --> |
| | | <resultMap id="BaseResultMap" type="com.ruoyi.system.model.TBillConfirm"> |
| | | <id column="id" property="id" /> |
| | | <result column="bill_id" property="billId" /> |
| | | <result column="pay_fees_money" property="payFeesMoney" /> |
| | | <result column="voucher" property="voucher" /> |
| | | </resultMap> |
| | | |
| | | <!-- 通用查询结果列 --> |
| | | <sql id="Base_Column_List"> |
| | | id, bill_id, pay_fees_money, voucher |
| | | </sql> |
| | | |
| | | </mapper> |
New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
| | | <mapper namespace="com.ruoyi.system.mapper.TBillDetailMapper"> |
| | | |
| | | <!-- 通用查询映射结果 --> |
| | | <resultMap id="BaseResultMap" type="com.ruoyi.system.model.TBillDetail"> |
| | | <id column="id" property="id" /> |
| | | <result column="bill_id" property="billId" /> |
| | | <result column="start_reading" property="startReading" /> |
| | | <result column="end_reading" property="endReading" /> |
| | | <result column="usage_measure" property="usageMeasure" /> |
| | | <result column="unit_price" property="unitPrice" /> |
| | | <result column="total_amount" property="totalAmount" /> |
| | | <result column="live_type" property="liveType" /> |
| | | <result column="create_time" property="createTime" /> |
| | | <result column="update_time" property="updateTime" /> |
| | | <result column="create_by" property="createBy" /> |
| | | <result column="update_by" property="updateBy" /> |
| | | <result column="disabled" property="disabled" /> |
| | | </resultMap> |
| | | |
| | | <!-- 通用查询结果列 --> |
| | | <sql id="Base_Column_List"> |
| | | id, bill_id, start_reading, end_reading, usage_measure, unit_price, total_amount,live_type, create_time, update_time, create_by, update_by, disabled |
| | | </sql> |
| | | |
| | | </mapper> |
| | |
| | | id, contract_id,contract_number, payable_fees_money, payable_fees_time, pay_fees_status, pay_fees_money, pay_fees_time, pay_fees_type, bill_type, over_days, payable_fees_penalty, start_time, end_time, bank_serial_number, outstanding_money, voucher, create_time, update_time, create_by, update_by, disabled |
| | | </sql> |
| | | |
| | | <select id="page" resultType="com.ruoyi.system.dto.TBillDto"> |
| | | SELECT |
| | | b.*, |
| | | t.resident_name as residentName, |
| | | t.phone, |
| | | t.account, |
| | | h.house_name as houseName |
| | | FROM |
| | | t_bill b |
| | | LEFT JOIN t_contract c ON c.contract_number = b.contract_number |
| | | LEFT JOIN t_house h ON h.id = c.house_id |
| | | LEFT JOIN t_tenant t ON t.id = c.tenant_id |
| | | <where> |
| | | <if test="query.payFeesStatus != null"> |
| | | and b.pay_fees_status = #{query.payFeesStatus} |
| | | </if> |
| | | <if test="query.phone != null and query.phone !=''"> |
| | | and t.phone = #{query.phone} |
| | | </if> |
| | | <if test="query.residentName != null and query.residentName !=''"> |
| | | and t.resident_name like concat('%',#{query.residentName},'%') |
| | | </if> |
| | | <if test="query.contractNumber != null and query.contractNumber !=''"> |
| | | and b.contract_number = #{query.contractNumber} |
| | | </if> |
| | | <if test="query.userId != null and query.userId !=''"> |
| | | and t.id = #{query.userId} |
| | | </if> |
| | | </where> |
| | | </select> |
| | | </mapper> |
New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
| | | <mapper namespace="com.ruoyi.system.mapper.TInvoiceToBillMapper"> |
| | | |
| | | <!-- 通用查询映射结果 --> |
| | | <resultMap id="BaseResultMap" type="com.ruoyi.system.model.TInvoiceToBill"> |
| | | <id column="id" property="id" /> |
| | | <result column="invoice_id" property="invoiceId" /> |
| | | <result column="bill_id" property="billId" /> |
| | | </resultMap> |
| | | |
| | | <!-- 通用查询结果列 --> |
| | | <sql id="Base_Column_List"> |
| | | id, invoice_id, bill_id |
| | | </sql> |
| | | |
| | | </mapper> |
| | |
| | | proxy: { |
| | | // detail: https://cli.vuejs.org/config/#devserver-proxy |
| | | [process.env.VUE_APP_BASE_API]: { |
| | | target: `http://localhost:9001`, |
| | | target: `http://localhost:8081`, |
| | | changeOrigin: true, |
| | | pathRewrite: { |
| | | ['^' + process.env.VUE_APP_BASE_API]: '' |