|
@@ -1,139 +1,212 @@
|
|
|
-//package thyyxxk.webserver.api.ccbmispos;
|
|
|
|
|
-//
|
|
|
|
|
-//import com.ccb.wlpt.RequestProcess;
|
|
|
|
|
-//import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
-//import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
|
-//import org.springframework.web.bind.annotation.GetMapping;
|
|
|
|
|
-//import org.springframework.web.bind.annotation.RequestMapping;
|
|
|
|
|
-//import org.springframework.web.bind.annotation.RestController;
|
|
|
|
|
-//import thyyxxk.webserver.config.auth.PassToken;
|
|
|
|
|
-//import thyyxxk.webserver.config.envionment.CcbMisConfig;
|
|
|
|
|
-//import thyyxxk.webserver.config.exception.BizException;
|
|
|
|
|
-//import thyyxxk.webserver.config.exception.ExceptionEnum;
|
|
|
|
|
-//import thyyxxk.webserver.entity.ResultVo;
|
|
|
|
|
-//import thyyxxk.webserver.utils.ResultVoUtil;
|
|
|
|
|
-//
|
|
|
|
|
-//import java.util.Objects;
|
|
|
|
|
-//
|
|
|
|
|
-//@Slf4j
|
|
|
|
|
-//@RestController
|
|
|
|
|
-//@RequestMapping("/api/ccbmispos")
|
|
|
|
|
-//public class CcbMisPosApi {
|
|
|
|
|
-// private volatile boolean initialized = false;
|
|
|
|
|
-// private final CcbMisConfig cfg;
|
|
|
|
|
-//
|
|
|
|
|
-// @Autowired
|
|
|
|
|
-// public CcbMisPosApi(CcbMisConfig cfg) {
|
|
|
|
|
-// this.cfg = cfg;
|
|
|
|
|
-// }
|
|
|
|
|
-//
|
|
|
|
|
-// @PassToken
|
|
|
|
|
-// @GetMapping("/initFileCert")
|
|
|
|
|
-// public String initFileCert() {
|
|
|
|
|
-// log.info("initFileCert:{}", cfg);
|
|
|
|
|
-// String initResult = RequestProcess.initFileCert(cfg.getMchId(), cfg.getUserid(),
|
|
|
|
|
-// cfg.getCertFile(), cfg.getCertPassword(), cfg.getConfigFile());
|
|
|
|
|
-// if (Objects.equals(initResult, "")) {
|
|
|
|
|
-// initResult = "INIT SUCCESS";
|
|
|
|
|
-// initialized = true;
|
|
|
|
|
-// } else {
|
|
|
|
|
-// initialized = false;
|
|
|
|
|
-// initResult = "INIT FAILED:" + initResult;
|
|
|
|
|
-// }
|
|
|
|
|
-// log.info("initResult:{}", initResult);
|
|
|
|
|
-// return initResult;
|
|
|
|
|
-// }
|
|
|
|
|
-//
|
|
|
|
|
-// @PassToken
|
|
|
|
|
-// @GetMapping("/removeFileCert")
|
|
|
|
|
-// public String removeFileCert() {
|
|
|
|
|
-// RequestProcess.removeFileCert(cfg.getMchId(), cfg.getUserid());
|
|
|
|
|
-// return "OK";
|
|
|
|
|
-// }
|
|
|
|
|
-//
|
|
|
|
|
-// @PassToken
|
|
|
|
|
-// @GetMapping("/downloadTradeList")
|
|
|
|
|
-// public ResultVo<String> downloadTradeList() {
|
|
|
|
|
-// if (!initialized) {
|
|
|
|
|
-// String initResult = initFileCert();
|
|
|
|
|
-// if (!Objects.equals(initResult, "INIT SUCCESS")) {
|
|
|
|
|
-// throw new BizException(ExceptionEnum.LOGICAL_ERROR, "初始化证书失败:" + initResult);
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-// String xml = "<?xml version=\"1.0\" encoding=\"GB2312\" standalone=\"yes\" ?> \n" +
|
|
|
|
|
-// "<TX> \n" +
|
|
|
|
|
-// " <REQUEST_SN>" + System.currentTimeMillis() + "000</REQUEST_SN> \n" +
|
|
|
|
|
-// " <CUST_ID>"+cfg.getMchId() +"</CUST_ID> \n" +
|
|
|
|
|
-// " <USER_ID>"+cfg.getUserid()+"</USER_ID> \n" +
|
|
|
|
|
-// " <PASSWORD>"+cfg.getUserPassword()+"</PASSWORD> \n" +
|
|
|
|
|
-// " <TX_CODE>5W1005</TX_CODE> \n" +
|
|
|
|
|
-// " <LANGUAGE>CN</LANGUAGE> \n" +
|
|
|
|
|
-// " <TX_INFO> \n" +
|
|
|
|
|
-// " <DATE>20250715</DATE> \n" +
|
|
|
|
|
-// " <KIND>1</KIND> \n" +
|
|
|
|
|
-// " <FILETYPE>1</FILETYPE> \n" +
|
|
|
|
|
-// " <TYPE>0</TYPE> \n" +
|
|
|
|
|
-// " <NORDERBY>1</NORDERBY> \n" +
|
|
|
|
|
-// " <POS_CODE></POS_CODE> \n" +
|
|
|
|
|
-// " <ORDER></ORDER> \n" +
|
|
|
|
|
-// " <STATUS>1</STATUS> \n" +
|
|
|
|
|
-// " <BILL_FLAG>1</BILL_FLAG> \n" +
|
|
|
|
|
-// " <Mrch_No></Mrch_No> \n" +
|
|
|
|
|
-// " <GROUP_FLAG>0</GROUP_FLAG> \n" +
|
|
|
|
|
-// " <TXN_TPCD>1</TXN_TPCD> \n" +
|
|
|
|
|
-// " </TX_INFO>\n" +
|
|
|
|
|
-// "</TX> \n";
|
|
|
|
|
-// log.info("入参:\r\n{}", xml);
|
|
|
|
|
-// String result = RequestProcess.sendRequest(cfg.getServiceUrl(), xml);
|
|
|
|
|
-// log.info("出参:\r\n{}", result);
|
|
|
|
|
-//
|
|
|
|
|
-// String code = analyzeCodeValue(result);
|
|
|
|
|
-//
|
|
|
|
|
-// if (code.equals("000000")) {
|
|
|
|
|
-// String fileName = result.split("<FILE_NAME>")[1]
|
|
|
|
|
-// .split("</FILE_NAME>")[0];
|
|
|
|
|
-// log.info("fileName: {}", fileName);
|
|
|
|
|
-// return downloadFile(fileName);
|
|
|
|
|
-// }
|
|
|
|
|
-// String errMsg = result.split("<RETURN_MSG>")[1]
|
|
|
|
|
-// .split("</RETURN_MSG>")[0];
|
|
|
|
|
-// throw new BizException(ExceptionEnum.LOGICAL_ERROR, errMsg);
|
|
|
|
|
-// }
|
|
|
|
|
-//
|
|
|
|
|
-// private ResultVo<String> downloadFile(String fileName) {
|
|
|
|
|
-// String xml = "<?xml version=\"1.0\" encoding=\"GB2312\" standalone=\"yes\" ?> \n" +
|
|
|
|
|
-// "<TX> \n" +
|
|
|
|
|
-// " <REQUEST_SN>" + System.currentTimeMillis() + "000</REQUEST_SN> \n" +
|
|
|
|
|
-// " <CUST_ID>"+cfg.getMchId() +"</CUST_ID> \n" +
|
|
|
|
|
-// " <USER_ID>"+cfg.getUserid()+"</USER_ID> \n" +
|
|
|
|
|
-// " <PASSWORD>"+cfg.getUserPassword()+"</PASSWORD> \n" +
|
|
|
|
|
-// " <TX_CODE>6W0111</TX_CODE> \n" +
|
|
|
|
|
-// " <LANGUAGE>CN</LANGUAGE> \n" +
|
|
|
|
|
-// " <TX_INFO> \n" +
|
|
|
|
|
-// " <SOURCE>" + fileName + "</SOURCE> \n" +
|
|
|
|
|
-// " <FILEPATH>merchant/shls</FILEPATH> \n" +
|
|
|
|
|
-// " <LOCAL_REMOTE>0</LOCAL_REMOTE> \n" +
|
|
|
|
|
-// " </TX_INFO> \n" +
|
|
|
|
|
-// "</TX> \n";
|
|
|
|
|
-// log.info("入参:\r\n{}", xml);
|
|
|
|
|
-//
|
|
|
|
|
-// String result = RequestProcess.downloadFile(cfg.getServiceUrl(), xml, "D:\\work\\ccbmis");
|
|
|
|
|
-//
|
|
|
|
|
-//// String result = RequestProcess.sendRequest(cfg.getServiceUrl(), xml);
|
|
|
|
|
-// log.info("出参:\r\n{}", result);
|
|
|
|
|
-// String code = analyzeCodeValue(result);
|
|
|
|
|
-// if (code.equals("000000")) {
|
|
|
|
|
-// return ResultVoUtil.success("下载文件成功");
|
|
|
|
|
-// }
|
|
|
|
|
-// String errMsg = result.split("<RETURN_MSG>")[1]
|
|
|
|
|
-// .split("</RETURN_MSG>")[0];
|
|
|
|
|
-// throw new BizException(ExceptionEnum.LOGICAL_ERROR, errMsg);
|
|
|
|
|
-// }
|
|
|
|
|
-//
|
|
|
|
|
-// private String analyzeCodeValue(String resultXml) {
|
|
|
|
|
-// if (resultXml.contains("<RETURN_CODE>") && resultXml.contains("</RETURN_CODE>")) {
|
|
|
|
|
-// return resultXml.split("<RETURN_CODE>")[1].split("</RETURN_CODE>")[0];
|
|
|
|
|
-// }
|
|
|
|
|
-// throw new BizException(ExceptionEnum.NULL_POINTER, "返回值异常,没有 <RETURN_CODE> 节点。");
|
|
|
|
|
-// }
|
|
|
|
|
-//}
|
|
|
|
|
|
|
+package thyyxxk.webserver.api.ccbmispos;
|
|
|
|
|
+
|
|
|
|
|
+import com.ccb.wlpt.RequestProcess;
|
|
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
|
+import org.springframework.web.bind.annotation.GetMapping;
|
|
|
|
|
+import org.springframework.web.bind.annotation.RequestMapping;
|
|
|
|
|
+import org.springframework.web.bind.annotation.RequestParam;
|
|
|
|
|
+import org.springframework.web.bind.annotation.RestController;
|
|
|
|
|
+import thyyxxk.webserver.config.auth.PassToken;
|
|
|
|
|
+import thyyxxk.webserver.config.envionment.CcbMisConfig;
|
|
|
|
|
+import thyyxxk.webserver.config.exception.BizException;
|
|
|
|
|
+import thyyxxk.webserver.config.exception.ExceptionEnum;
|
|
|
|
|
+import thyyxxk.webserver.dao.his.api.CcbMisposDao;
|
|
|
|
|
+import thyyxxk.webserver.entity.ResultVo;
|
|
|
|
|
+import thyyxxk.webserver.utils.*;
|
|
|
|
|
+
|
|
|
|
|
+import java.io.IOException;
|
|
|
|
|
+import java.util.ArrayList;
|
|
|
|
|
+import java.util.List;
|
|
|
|
|
+import java.util.Objects;
|
|
|
|
|
+import java.util.Queue;
|
|
|
|
|
+
|
|
|
|
|
+@Slf4j
|
|
|
|
|
+@RestController
|
|
|
|
|
+@RequestMapping("/api/ccbmispos")
|
|
|
|
|
+public class CcbMisPosApi {
|
|
|
|
|
+ private volatile boolean initialized = false;
|
|
|
|
|
+ private final CcbMisConfig cfg;
|
|
|
|
|
+ private final CcbMisposDao dao;
|
|
|
|
|
+
|
|
|
|
|
+ @Autowired
|
|
|
|
|
+ public CcbMisPosApi(CcbMisConfig cfg, CcbMisposDao dao) {
|
|
|
|
|
+ this.cfg = cfg;
|
|
|
|
|
+ this.dao = dao;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @PassToken
|
|
|
|
|
+ @GetMapping("/initFileCert")
|
|
|
|
|
+ public String initFileCert() {
|
|
|
|
|
+ log.info("initFileCert:{}", cfg);
|
|
|
|
|
+ String initResult = RequestProcess.initFileCert(cfg.getMchId(), cfg.getUserid(),
|
|
|
|
|
+ cfg.getCertFile(), cfg.getCertPassword(), cfg.getConfigFile());
|
|
|
|
|
+ if (Objects.equals(initResult, "")) {
|
|
|
|
|
+ initResult = "INIT SUCCESS";
|
|
|
|
|
+ initialized = true;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ initialized = false;
|
|
|
|
|
+ initResult = "INIT FAILED:" + initResult;
|
|
|
|
|
+ }
|
|
|
|
|
+ log.info("initResult:{}", initResult);
|
|
|
|
|
+ return initResult;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @PassToken
|
|
|
|
|
+ @GetMapping("/removeFileCert")
|
|
|
|
|
+ public String removeFileCert() {
|
|
|
|
|
+ RequestProcess.removeFileCert(cfg.getMchId(), cfg.getUserid());
|
|
|
|
|
+ return "OK";
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @PassToken
|
|
|
|
|
+ @GetMapping("/downloadTradeList")
|
|
|
|
|
+ public ResultVo<String> downloadTradeList(@RequestParam("date") String date) throws IOException {
|
|
|
|
|
+ // date 应是 yyyyMMdd 格式:20250903
|
|
|
|
|
+ if (date.contains("-")) {
|
|
|
|
|
+ date = date.replaceAll("-", "");
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!initialized) {
|
|
|
|
|
+ String initResult = initFileCert();
|
|
|
|
|
+ if (!Objects.equals(initResult, "INIT SUCCESS")) {
|
|
|
|
|
+ throw new BizException(ExceptionEnum.LOGICAL_ERROR, "初始化证书失败:" + initResult);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ String xml = "<?xml version=\"1.0\" encoding=\"GB2312\" standalone=\"yes\" ?> \n" +
|
|
|
|
|
+ "<TX> \n" +
|
|
|
|
|
+ " <REQUEST_SN>" + System.currentTimeMillis() + "000</REQUEST_SN> \n" +
|
|
|
|
|
+ " <CUST_ID>"+cfg.getMchId() +"</CUST_ID> \n" +
|
|
|
|
|
+ " <USER_ID>"+cfg.getUserid()+"</USER_ID> \n" +
|
|
|
|
|
+ " <PASSWORD>"+cfg.getUserPassword()+"</PASSWORD> \n" +
|
|
|
|
|
+ " <TX_CODE>5W1005</TX_CODE> \n" +
|
|
|
|
|
+ " <LANGUAGE>CN</LANGUAGE> \n" +
|
|
|
|
|
+ " <TX_INFO> \n" +
|
|
|
|
|
+ " <DATE>" + date + "</DATE> \n" +
|
|
|
|
|
+ " <KIND>1</KIND> \n" +
|
|
|
|
|
+ " <FILETYPE>1</FILETYPE> \n" +
|
|
|
|
|
+ " <TYPE>0</TYPE> \n" +
|
|
|
|
|
+ " <NORDERBY>1</NORDERBY> \n" +
|
|
|
|
|
+ " <POS_CODE></POS_CODE> \n" +
|
|
|
|
|
+ " <ORDER></ORDER> \n" +
|
|
|
|
|
+ " <STATUS>1</STATUS> \n" +
|
|
|
|
|
+ " <BILL_FLAG>1</BILL_FLAG> \n" +
|
|
|
|
|
+ " <Mrch_No></Mrch_No> \n" +
|
|
|
|
|
+ " <GROUP_FLAG>0</GROUP_FLAG> \n" +
|
|
|
|
|
+ " <TXN_TPCD>1</TXN_TPCD> \n" +
|
|
|
|
|
+ " </TX_INFO>\n" +
|
|
|
|
|
+ "</TX> \n";
|
|
|
|
|
+ log.info("入参:\r\n{}", xml);
|
|
|
|
|
+ String result = RequestProcess.sendRequest(cfg.getServiceUrl(), xml);
|
|
|
|
|
+ log.info("出参:\r\n{}", result);
|
|
|
|
|
+
|
|
|
|
|
+ String code = analyzeCodeValue(result);
|
|
|
|
|
+
|
|
|
|
|
+ if (code.equals("000000")) {
|
|
|
|
|
+ String fileName = result.split("<FILE_NAME>")[1]
|
|
|
|
|
+ .split("</FILE_NAME>")[0];
|
|
|
|
|
+ log.info("fileName: {}", fileName);
|
|
|
|
|
+ return downloadFile(fileName);
|
|
|
|
|
+ }
|
|
|
|
|
+ String errMsg = result.split("<RETURN_MSG>")[1]
|
|
|
|
|
+ .split("</RETURN_MSG>")[0];
|
|
|
|
|
+ throw new BizException(ExceptionEnum.LOGICAL_ERROR, errMsg);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private ResultVo<String> downloadFile(String fileName) throws IOException {
|
|
|
|
|
+ String xml = "<?xml version=\"1.0\" encoding=\"GB2312\" standalone=\"yes\" ?> \n" +
|
|
|
|
|
+ "<TX> \n" +
|
|
|
|
|
+ " <REQUEST_SN>" + System.currentTimeMillis() + "000</REQUEST_SN> \n" +
|
|
|
|
|
+ " <CUST_ID>"+cfg.getMchId() +"</CUST_ID> \n" +
|
|
|
|
|
+ " <USER_ID>"+cfg.getUserid()+"</USER_ID> \n" +
|
|
|
|
|
+ " <PASSWORD>"+cfg.getUserPassword()+"</PASSWORD> \n" +
|
|
|
|
|
+ " <TX_CODE>6W0111</TX_CODE> \n" +
|
|
|
|
|
+ " <LANGUAGE>CN</LANGUAGE> \n" +
|
|
|
|
|
+ " <TX_INFO> \n" +
|
|
|
|
|
+ " <SOURCE>" + fileName + "</SOURCE> \n" +
|
|
|
|
|
+ " <FILEPATH>merchant/shls</FILEPATH> \n" +
|
|
|
|
|
+ " <LOCAL_REMOTE>0</LOCAL_REMOTE> \n" +
|
|
|
|
|
+ " </TX_INFO> \n" +
|
|
|
|
|
+ "</TX> \n";
|
|
|
|
|
+ log.info("入参:\r\n{}", xml);
|
|
|
|
|
+
|
|
|
|
|
+ String result = RequestProcess.downloadFile(cfg.getServiceUrl(), xml, cfg.getFileDir());
|
|
|
|
|
+
|
|
|
|
|
+ log.info("出参:\r\n{}", result);
|
|
|
|
|
+ String code = analyzeCodeValue(result);
|
|
|
|
|
+ if (code.equals("000000")) {
|
|
|
|
|
+ unzipFile(fileName);
|
|
|
|
|
+ return ResultVoUtil.success("下载文件成功");
|
|
|
|
|
+ }
|
|
|
|
|
+ String errMsg = result.split("<RETURN_MSG>")[1]
|
|
|
|
|
+ .split("</RETURN_MSG>")[0];
|
|
|
|
|
+ throw new BizException(ExceptionEnum.LOGICAL_ERROR, errMsg);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void unzipFile(String zipFileName) throws IOException {
|
|
|
|
|
+ String txtPath = ZipUtil.unZip(zipFileName, cfg.getFileDir(), ".det.");
|
|
|
|
|
+ Queue<String> queue = SiUtil.readTxtFile(txtPath);
|
|
|
|
|
+ List<CcbMisposPaymentRecord> recordList = new ArrayList<>();
|
|
|
|
|
+ if (!queue.isEmpty()) {
|
|
|
|
|
+ queue.poll();
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!queue.isEmpty()) {
|
|
|
|
|
+ String textLine = queue.poll();
|
|
|
|
|
+ CcbMisposPaymentRecord record = makeRecordFromText(textLine);
|
|
|
|
|
+ recordList.add(record);
|
|
|
|
|
+ String date = textLine.split("\\|")[4];
|
|
|
|
|
+ String begin = date + " 00:00:00";
|
|
|
|
|
+ String end = date + " 23:59:59";
|
|
|
|
|
+ dao.deleteDuplicateData(begin, end);
|
|
|
|
|
+ }
|
|
|
|
|
+ while (!queue.isEmpty()) {
|
|
|
|
|
+ String textLine = queue.poll();
|
|
|
|
|
+ CcbMisposPaymentRecord record = makeRecordFromText(textLine);
|
|
|
|
|
+ recordList.add(record);
|
|
|
|
|
+ if (recordList.size() == 30) {
|
|
|
|
|
+ dao.insert(recordList);
|
|
|
|
|
+ recordList.clear();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!recordList.isEmpty()) {
|
|
|
|
|
+ dao.insert(recordList);
|
|
|
|
|
+ }
|
|
|
|
|
+ ZipUtil.deleteFile(txtPath);
|
|
|
|
|
+ ZipUtil.deleteFile(cfg.getFileDir() + zipFileName);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private String analyzeCodeValue(String resultXml) {
|
|
|
|
|
+ if (resultXml.contains("<RETURN_CODE>") && resultXml.contains("</RETURN_CODE>")) {
|
|
|
|
|
+ return resultXml.split("<RETURN_CODE>")[1].split("</RETURN_CODE>")[0];
|
|
|
|
|
+ }
|
|
|
|
|
+ throw new BizException(ExceptionEnum.NULL_POINTER, "返回值异常,没有 <RETURN_CODE> 节点。");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private CcbMisposPaymentRecord makeRecordFromText(String txt) {
|
|
|
|
|
+ String[] arr = txt.split("\\|");
|
|
|
|
|
+ CcbMisposPaymentRecord record = new CcbMisposPaymentRecord();
|
|
|
|
|
+ record.setId(SnowFlakeId.instance().nextId());
|
|
|
|
|
+ record.setTerminalNo(arr[0]);
|
|
|
|
|
+ record.setCardBelong(arr[1]);
|
|
|
|
|
+ record.setCardType(arr[2]);
|
|
|
|
|
+ record.setCardSerialNo(arr[3]);
|
|
|
|
|
+ String timeStr = arr[4] + " " + arr[5];
|
|
|
|
|
+ record.setTradeTime(DateUtil.parse(timeStr));
|
|
|
|
|
+ record.setTradeType(arr[6]);
|
|
|
|
|
+ record.setGrantNo(arr[7]);
|
|
|
|
|
+ record.setTradeAmount(arr[8]);
|
|
|
|
|
+ record.setBankHandlingFee(arr[9]);
|
|
|
|
|
+ record.setReceivedAmount(arr[10]);
|
|
|
|
|
+ record.setTraceNo(arr[11]);
|
|
|
|
|
+ record.setBatchNo(arr[12]);
|
|
|
|
|
+ record.setPosTradeSort(arr[13]);
|
|
|
|
|
+ record.setSettleAccount(arr[14]);
|
|
|
|
|
+ record.setTradeNo(arr[15]);
|
|
|
|
|
+ record.setPosNo(arr[16]);
|
|
|
|
|
+ record.setSystemReferNo(arr[17]);
|
|
|
|
|
+ record.setPaymentVoucher(arr[18]);
|
|
|
|
|
+ record.setRemark1(arr[19]);
|
|
|
|
|
+ record.setRemark2(arr[20]);
|
|
|
|
|
+ record.setOrderAmount(arr[21]);
|
|
|
|
|
+ return record;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|