From 87e956caba712c821cd4c83501a727bafa212a50 Mon Sep 17 00:00:00 2001 From: "taylor.dang" Date: Fri, 16 Nov 2018 17:02:06 +0800 Subject: [PATCH] =?UTF-8?q?=E9=A3=8E=E6=8E=A7=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../appclient/web/RetailAppController.java | 87 ++++++- .../mappers/payment/TransactionMapper.java | 12 + .../mappers/riskbusiness/RiskEventMapper.java | 3 + .../core/RiskBusinessService.java | 27 +++ .../core/impl/RiskBusinessServiceImpl.java | 226 +++++++++++++++--- .../core/impl/RiskUploadServiceIpml.java | 8 +- .../manage/mappers/payment/OrderMapper.xml | 12 +- .../mappers/riskbusiness/RiskEventMapper.xml | 15 ++ src/main/resources/i18n/msg_en.properties | 2 +- src/main/resources/i18n/msg_zh.properties | 2 +- src/main/ui/static/analysis/risk_business.js | 47 +++- .../analysis/templates/new_riskEvent.html | 32 ++- .../analysis/templates/riskEvent_detail.html | 36 ++- .../analysis/templates/risk_business.html | 12 +- 14 files changed, 443 insertions(+), 78 deletions(-) diff --git a/src/main/java/au/com/royalpay/payment/manage/appclient/web/RetailAppController.java b/src/main/java/au/com/royalpay/payment/manage/appclient/web/RetailAppController.java index 2b0c92902..7d449f341 100644 --- a/src/main/java/au/com/royalpay/payment/manage/appclient/web/RetailAppController.java +++ b/src/main/java/au/com/royalpay/payment/manage/appclient/web/RetailAppController.java @@ -13,6 +13,10 @@ import au.com.royalpay.payment.manage.bill.core.BillOrderService; import au.com.royalpay.payment.manage.bill.core.BillService; import au.com.royalpay.payment.manage.merchants.beans.ClientAuthFilesInfo; import au.com.royalpay.payment.manage.merchants.beans.ClientUpdateInfo; +import au.com.royalpay.payment.manage.riskbusiness.bean.RiskEventQuery; +import au.com.royalpay.payment.manage.riskbusiness.core.RiskBusinessService; +import au.com.royalpay.payment.manage.riskbusiness.core.RiskUploadService; +import au.com.royalpay.payment.manage.riskbusiness.enums.RiskResultTypeEnum; import au.com.royalpay.payment.manage.settlement.core.ManualSettleSupport; import au.com.royalpay.payment.manage.signin.beans.ChangePwdBean; import au.com.royalpay.payment.manage.signin.core.SignInStatusManager; @@ -25,28 +29,27 @@ import au.com.royalpay.payment.tools.exceptions.ForbiddenException; import au.com.royalpay.payment.tools.http.HttpUtils; import au.com.royalpay.payment.tools.merchants.beans.QRCodeConfig; import au.com.royalpay.payment.tools.merchants.beans.UpdateSurchargeDTO; - import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; - import org.apache.commons.lang3.time.DateUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.Errors; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.servlet.ModelAndView; +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; import java.math.BigDecimal; import java.text.ParseException; +import java.util.Arrays; import java.util.Date; import java.util.List; import java.util.Map; -import javax.annotation.Resource; -import javax.servlet.http.HttpServletResponse; -import javax.validation.Valid; - import static au.com.royalpay.payment.tools.CommonConsts.RETAIL_DEVICE; /** @@ -75,6 +78,11 @@ public class RetailAppController { @Resource private AttachmentClient attachmentClient; + @Autowired + private RiskBusinessService riskBusinessService; + + @Autowired + private RiskUploadService riskUploadService; @RequestMapping(value = "/token", method = RequestMethod.PUT) public void updateDevToken(@ModelAttribute(CommonConsts.RETAIL_DEVICE) JSONObject device, @RequestBody JSONObject token) { @@ -565,4 +573,71 @@ public class RetailAppController { retailAppService.cancelCouponAccuessLog(accuess_id, remark); } + /** + * app端获取风控通知信息 + * @param clientId + * @return + */ + @GetMapping(value = "/risk/business/notice") + public JSONObject riskNotice(@RequestParam("client_id") int clientId) { + return riskBusinessService.getNoticeInfo(clientId); + } + + /** + * app端风控事件列表接口 + * @param riskEventQuery + * @return + */ + @GetMapping(value = "/risk/business/events") + public JSONObject getRiskEvents(RiskEventQuery riskEventQuery) { + JSONObject params = riskEventQuery.toJSON(); + params.put("client_moniker", riskEventQuery.getClientMoniker()); + params.put("is_send_client", 1); + params.putIfAbsent("page", 1); + List resultTypes = Arrays.asList(RiskResultTypeEnum.SEND_EMAIL_TO_BD.getResultType(), + RiskResultTypeEnum.WAIT_FOR_AUDIT.getResultType(), + RiskResultTypeEnum.MATERIAL_AUDIT_PASS.getResultType(), + RiskResultTypeEnum.MATERIAL_NOT_PASS.getResultType(), + RiskResultTypeEnum.ALREADY_HANDLED.getResultType()); + params.put("result_types", resultTypes); + return riskBusinessService.getRiskEventsByPage(params, null); + } + + /** + * app端风控事件详情接口 + * @param riskId + * @return + */ + @GetMapping(value = "/risk/business/events/{risk_id}") + public JSONObject getRiskEventDetail(@PathVariable("risk_id") String riskId) { + JSONObject riskEvent = riskBusinessService.getRiskEventDetail(riskId); + List tradeLogs = riskBusinessService.getRiskEventOrderList(riskEvent); + riskEvent.put("tradeLogs", tradeLogs); + return riskEvent; + } + + /** + * app端获取风控事件上传的材料信息 + * @param riskId + * @return + */ + @GetMapping(value = "/risk/business/events/{risk_id}/materials") + public JSONObject getRiskEventMaterialsRemark(@PathVariable("risk_id") String riskId) { + return riskBusinessService.getRiskEventMaterialsRemark(riskId); + } + + /** + * app端上传调单材料接口 + * @param material + */ + @PostMapping(value = "/risk/business/events") + public void uploadMaterial(@RequestBody JSONObject material) { + riskUploadService.submitMaterial(material); + } + + @RequestMapping(value = "/risk/business/upload/files", method = RequestMethod.POST) + public JSONObject uploadImage(@RequestParam MultipartFile file) throws Exception { + return attachmentClient.uploadFile(file,false); + } + } diff --git a/src/main/java/au/com/royalpay/payment/manage/mappers/payment/TransactionMapper.java b/src/main/java/au/com/royalpay/payment/manage/mappers/payment/TransactionMapper.java index d2b2a2dac..8f4ab97b4 100644 --- a/src/main/java/au/com/royalpay/payment/manage/mappers/payment/TransactionMapper.java +++ b/src/main/java/au/com/royalpay/payment/manage/mappers/payment/TransactionMapper.java @@ -9,6 +9,7 @@ import com.github.miemiedev.mybatis.paginator.domain.PageBounds; import com.github.miemiedev.mybatis.paginator.domain.PageList; import org.apache.ibatis.annotations.Param; import org.joda.time.DateTime; +import org.springframework.beans.factory.annotation.Autowired; import java.math.BigDecimal; import java.util.Date; @@ -145,4 +146,15 @@ public interface TransactionMapper { List getHfClearAmount(JSONObject params); List analysisForATOReport(@Param("clientId") int clientId, @Param("from") Date startOfMon, @Param("to") Date endOfMon); + + /** + * 付款退款都是同一个退款单号 + * @param clientId + * @param systemTransactionId + * @return + */ + @AutoSql(type = SqlType.SELECT) + PageList findByClientIdAndSystemTransactionId(@Param("client_id") int clientId, + @Param("system_transaction_id") String systemTransactionId, + PageBounds pageBounds); } diff --git a/src/main/java/au/com/royalpay/payment/manage/mappers/riskbusiness/RiskEventMapper.java b/src/main/java/au/com/royalpay/payment/manage/mappers/riskbusiness/RiskEventMapper.java index d27b4351b..200a00356 100644 --- a/src/main/java/au/com/royalpay/payment/manage/mappers/riskbusiness/RiskEventMapper.java +++ b/src/main/java/au/com/royalpay/payment/manage/mappers/riskbusiness/RiskEventMapper.java @@ -31,4 +31,7 @@ public interface RiskEventMapper { @AutoSql(type = SqlType.SELECT) JSONObject findById(@Param("risk_id") String riskId); + @AutoSql(type = SqlType.DELETE) + void deleteRiskEvent(@Param("risk_id") String risk_id); + } diff --git a/src/main/java/au/com/royalpay/payment/manage/riskbusiness/core/RiskBusinessService.java b/src/main/java/au/com/royalpay/payment/manage/riskbusiness/core/RiskBusinessService.java index 52ccf932d..9a426ed12 100644 --- a/src/main/java/au/com/royalpay/payment/manage/riskbusiness/core/RiskBusinessService.java +++ b/src/main/java/au/com/royalpay/payment/manage/riskbusiness/core/RiskBusinessService.java @@ -84,4 +84,31 @@ public interface RiskBusinessService { * @return */ JSONObject getRiskMaterial(JSONObject param); + + /** + * 补全历史数据的real_order_ids + */ + void completeEventRealOrderIds(); + + /** + * 删除事件 + * @param riskId + */ + void deleteRiskEvent(String riskId); + + /** + * 商户端获取通知信息 + * @param clientId + * @return + */ + JSONObject getNoticeInfo(int clientId); + + /** + * 获取风控事件所需上传的材料说明 + * @param riskId + * @return + */ + JSONObject getRiskEventMaterialsRemark(String riskId); + + JSONObject updateIsSendClient(String riskId); } diff --git a/src/main/java/au/com/royalpay/payment/manage/riskbusiness/core/impl/RiskBusinessServiceImpl.java b/src/main/java/au/com/royalpay/payment/manage/riskbusiness/core/impl/RiskBusinessServiceImpl.java index 365852461..46f665e31 100644 --- a/src/main/java/au/com/royalpay/payment/manage/riskbusiness/core/impl/RiskBusinessServiceImpl.java +++ b/src/main/java/au/com/royalpay/payment/manage/riskbusiness/core/impl/RiskBusinessServiceImpl.java @@ -6,6 +6,7 @@ import au.com.royalpay.payment.core.exceptions.OrderNotExistsException; import au.com.royalpay.payment.core.exceptions.OrderNotMatchException; import au.com.royalpay.payment.manage.mappers.log.AppMessageLogMapper; import au.com.royalpay.payment.manage.mappers.payment.OrderMapper; +import au.com.royalpay.payment.manage.mappers.payment.TransactionMapper; import au.com.royalpay.payment.manage.mappers.riskbusiness.RiskEventMapper; import au.com.royalpay.payment.manage.mappers.riskbusiness.RiskFileMapper; import au.com.royalpay.payment.manage.mappers.riskbusiness.RiskMaterialMapper; @@ -13,6 +14,7 @@ import au.com.royalpay.payment.manage.mappers.system.ClientDeviceTokenMapper; import au.com.royalpay.payment.manage.mappers.system.ClientMapper; import au.com.royalpay.payment.manage.mappers.system.ClientBDMapper; import au.com.royalpay.payment.manage.notice.core.MailService; +import au.com.royalpay.payment.manage.pushMessage.APNSMessageHelper; import au.com.royalpay.payment.manage.pushMessage.bean.AppManagerMessageBuilder; import au.com.royalpay.payment.manage.riskbusiness.core.RiskBusinessService; import au.com.royalpay.payment.manage.riskbusiness.enums.RiskResultTypeEnum; @@ -29,6 +31,7 @@ import au.com.royalpay.payment.tools.permission.enums.ManagerRole; import au.com.royalpay.payment.tools.exceptions.ServerErrorException; import au.com.royalpay.payment.tools.threadpool.RoyalThreadPoolExecutor; import au.com.royalpay.payment.tools.utils.PageListUtils; +import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.github.miemiedev.mybatis.paginator.domain.Order; import com.github.miemiedev.mybatis.paginator.domain.PageBounds; @@ -45,6 +48,7 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import org.thymeleaf.context.Context; import org.thymeleaf.spring4.SpringTemplateEngine; @@ -77,6 +81,8 @@ public class RiskBusinessServiceImpl implements RiskBusinessService, ManagerTodo @Resource private OrderMapper orderMapper; @Resource + private TransactionMapper transactionMapper; + @Resource private StringRedisTemplate stringRedisTemplate; @Resource private SpringTemplateEngine thymeleaf; @@ -99,6 +105,14 @@ public class RiskBusinessServiceImpl implements RiskBusinessService, ManagerTodo private Map senderMap = new HashMap<>(); + @Resource + private APNSMessageHelper apnsMessageHelper; + + @Resource + public void setAppMsgSenders(AppMsgSender[] senders) { + Arrays.stream(senders).forEach(appMsgSender -> senderMap.put(appMsgSender.devType(), appMsgSender)); + } + private ThreadPoolExecutor sendingAppleMsgPool = new ThreadPoolExecutor(10, 30, 5, TimeUnit.SECONDS, new LinkedBlockingQueue()); @Override @@ -110,7 +124,7 @@ public class RiskBusinessServiceImpl implements RiskBusinessService, ManagerTodo public JSONObject getRiskEventsByPage(JSONObject params, JSONObject manager) { // 如果登录的角色是BD,添加查询条件result_type为1,2,3,4,order_type为1或者2 - if (ManagerRole.BD_USER.hasRole(manager.getIntValue("role"))) { + if (manager != null && ManagerRole.BD_USER.hasRole(manager.getIntValue("role"))) { params.put("bd_id", manager.getString("manager_id")); List orderTypes = Arrays.asList(RiskOrderTypeEnum.WECHAT_ORDER.getOrderType(), RiskOrderTypeEnum.ALIPAY_ORDER.getOrderType()); @@ -146,21 +160,20 @@ public class RiskBusinessServiceImpl implements RiskBusinessService, ManagerTodo @Override public List getRiskEventOrderList(JSONObject riskEvent) { - String orderIds = riskEvent.getString("order_ids"); + //String orderIds = riskEvent.getString("order_ids"); + String realOrderIds = riskEvent.getString("real_order_ids"); JSONObject client = clientMapper.findClientByMonikerAll(riskEvent.getString("client_moniker")); List tradeLogs = new ArrayList<>(); /** * 通用号调单会有client为空的情况,所以无法查到订单信息 */ - if (client != null && StringUtils.isNotBlank(orderIds)) { - String[] orderIdArray = orderIds.trim().split(","); + if (client != null && StringUtils.isNotBlank(realOrderIds)) { + String[] orderIdArray = realOrderIds.trim().split(","); JSONObject orderInfo = new JSONObject(); - String realOrderId = ""; // 获取订单信息 if (riskEvent.getIntValue("order_type") == 3) { for (int i = 0; i < orderIdArray.length; i++) { - realOrderId = orderMapper.findOrderById(orderIdArray[i],client.getIntValue("client_id")).getString("order_id"); - orderInfo = tradeLogService.getOrderDetail(new JSONObject(), riskEvent.getString("client_moniker"), realOrderId, null); + orderInfo = tradeLogService.getOrderDetail(new JSONObject(), riskEvent.getString("client_moniker"), orderIdArray[i], null); tradeLogs.add(orderInfo); } } else { @@ -173,8 +186,7 @@ public class RiskBusinessServiceImpl implements RiskBusinessService, ManagerTodo return tradeLogs; } - @Override - public void addRiskEvent(JSONObject params, JSONObject manager) { + private JSONObject getEvent(JSONObject params) { // 通用号调单不需要填写client_moniker JSONObject client = null; String clientMoniker = params.getString("client_moniker"); @@ -185,8 +197,6 @@ public class RiskBusinessServiceImpl implements RiskBusinessService, ManagerTodo } } - params.put("fillin_id", manager.getString("manager_id")); - params.put("fillin_person", manager.getString("display_name")); String orderIds = params.getString("order_ids"); if (StringUtils.isNotBlank(orderIds)) { // 去除所有空格与中文逗号',' @@ -195,6 +205,7 @@ public class RiskBusinessServiceImpl implements RiskBusinessService, ManagerTodo params.put("order_ids", orderIds); String[] orderIdArray = orderIds.split(","); List orderAmountList = new ArrayList<>(); + List realOrderIdList = new ArrayList<>(); /** * 通用号调单的时候,是不用填写client_moniker的,但是系统需要client_id关联查询订单信息, * 所以当client为空的时候,就不去校验订单的信息了,从而order_amounts字段为空 @@ -202,25 +213,40 @@ public class RiskBusinessServiceImpl implements RiskBusinessService, ManagerTodo */ if (client != null) { for (int i = 0; i < orderIdArray.length; i++) { - JSONObject orderInfo = orderMapper.findOrderById(orderIdArray[i],client.getIntValue("client_id")); + PageList transactionList = transactionMapper.findByClientIdAndSystemTransactionId(client.getIntValue("client_id"), orderIdArray[i], new PageBounds(Order.formString("transaction_time.desc"))); // 判断该笔订单是否存在,是否属于该商户 - if (orderInfo == null) - throw new OrderNotExistsException(); + // 由于查询订单时已经关联商户了,所以只会抛出订单不匹配的异常 + if (transactionList == null || transactionList.size() <= 0) + throw new OrderNotMatchException(); + /* else { - if (!clientMoniker.equals(orderInfo.getString("partner_code"))) { + if (!clientMoniker.equals(orderInfo.getString("client_moniker"))) { throw new OrderNotMatchException(); } orderAmountList.add(orderInfo.getString("total_amount")); } + */ + + // 将订单order_id存入数据库方便后面快速查询 + JSONObject orderInfo = transactionList.get(0); + realOrderIdList.add(orderInfo.getString("order_id")); + orderAmountList.add(orderInfo.getString("transaction_amount")); } params.put("order_amounts", StringUtils.join(orderAmountList, ",")); + params.put("real_order_ids", StringUtils.join(realOrderIdList, ",")); } } + return params; + } + @Override + public void addRiskEvent(JSONObject params, JSONObject manager) { + params = getEvent(params); riskEventMapper.save(params); } @Override public void updateRiskEvent(JSONObject params) { + params = getEvent(params); riskEventMapper.update(params); } @@ -277,7 +303,7 @@ public class RiskBusinessServiceImpl implements RiskBusinessService, ManagerTodo event.put("result_type", RiskResultTypeEnum.SEND_EMAIL_TO_BD.getResultType()); event.put("submit_url",uploadUrl); Integer orderType = event.getInteger("order_type"); - if (orderType == RiskOrderTypeEnum.WARNING_ORDER.getOrderType()) { + if (orderType.equals(RiskOrderTypeEnum.WARNING_ORDER.getOrderType())) { event.put("result_type", RiskResultTypeEnum.ALREADY_HANDLED.getResultType()); } riskEventMapper.update(event); @@ -288,29 +314,29 @@ public class RiskBusinessServiceImpl implements RiskBusinessService, ManagerTodo if(event.getIntValue("order_type")==3){ sendAppRiskMessage(event); } - - } private void sendAppRiskMessage(JSONObject event){ JSONObject client = clientMapper.findClientByMoniker(event.getString("client_moniker")); logger.debug("sendRiskAppMessage-" + client.getString("client_moniker") + "-" + "risk_id:"+event.getString("risk_id")); List tokens = clientDeviceTokenMapper.listTokensByClient_id(client.getIntValue("client_id")); - for (final JSONObject devToken : tokens) { + for (JSONObject devToken : tokens) { Runnable task = () -> { String token = devToken.getString("token"); - if (token == null) { + if (token == null || devToken.getString("client_type") == null) { return; } - JSONObject log = saveAppMessageLog(devToken.getString("dev_id"), devToken.getIntValue("client_id"), "risk", token, + JSONObject log = saveAppMessageLog(devToken.getString("dev_id"), devToken.getIntValue("client_id"), "risk" + devToken.getString("client_type"), token, event.getString("risk_id")); try { - event.put("send_type", "risk"); JSONObject type = new JSONObject(); type.put("send_type", "risk"); type.put("id", event.getString("risk_id")); +// apnsMessageHelper.sendAppleMessageDetail( +// LocaleSupport.localeMessage("app.message.title.risk"), LocaleSupport.localeMessage("app.message.body.risk"), +// token, event, type); AppMsgSender sender = senderMap.get(devToken.getString("client_type")); - if (token == null || sender == null) { + if (StringUtils.isBlank(token) || sender == null) { return; } JSONObject managerMsg = new JSONObject(); @@ -318,7 +344,7 @@ public class RiskBusinessServiceImpl implements RiskBusinessService, ManagerTodo managerMsg.put("body", LocaleSupport.localeMessage("app.message.body.risk")); managerMsg.put("type", type); - managerMsg.put("data", event); + managerMsg.put("data", new JSONObject()); managerMsg.put("msgType", "risk"); AppMessage appMessage = new AppManagerMessageBuilder(managerMsg).buildMessage(); sender.sendMessage(appMessage, devToken); @@ -327,7 +353,7 @@ public class RiskBusinessServiceImpl implements RiskBusinessService, ManagerTodo } catch (Exception e) { logger.error("出错了:" + e.getMessage()); appMessageLogMapper.updateStatus(log.getString("send_id"), 1, e.getMessage()); - throw new ServerErrorException("Send App " + devToken.getString("client_type") + " Failed", e); + throw new ServerErrorException("Send App " + devToken.getString("client_type") + " Failed" + ",token" + token, e); } }; sendingAppleMsgPool.execute(task); @@ -444,12 +470,14 @@ public class RiskBusinessServiceImpl implements RiskBusinessService, ManagerTodo ctx.setVariable("uploadUrl", uploadUrl); ctx.setVariable("royalpay_order_type", event.getIntValue("royalpay_order_type")); ctx.setVariable("warning_order_type", event.getIntValue("warning_order_type")); - String[] orderIds = event.getString("order_ids").split(","); + ctx.setVariable("description", event.getString("description")); + //String[] orderIds = event.getString("order_ids").split(","); + String[] realOrderIds = event.getString("real_order_ids").split(","); List orders = new ArrayList(); switch (event.getIntValue("order_type")){ case 1: case 2: - for(String orderId : orderIds){ + for(String orderId : realOrderIds){ JSONObject order = orderMapper.findOrderById(orderId,client.getIntValue("client_id")); if(order==null){ throw new BadRequestException("Order: "+orderId+" not exists"); @@ -461,10 +489,8 @@ public class RiskBusinessServiceImpl implements RiskBusinessService, ManagerTodo ctx.setVariable("emailsTos", bdEmails); break; case 3: - String realOrderId = ""; - for(String orderId : orderIds){ - realOrderId = orderMapper.findOrderById(orderId,client.getIntValue("client_id")).getString("order_id"); - JSONObject order = tradeLogService.getOrderDetail(new JSONObject(), clientMoniker, realOrderId, null); + for(String orderId : realOrderIds){ + JSONObject order = tradeLogService.getOrderDetail(new JSONObject(), clientMoniker, orderId, null); if(order==null){ throw new BadRequestException("Order: "+orderId+" not exists"); } @@ -522,16 +548,43 @@ public class RiskBusinessServiceImpl implements RiskBusinessService, ManagerTodo return null; } + @Override + @Transactional + public void completeEventRealOrderIds() { + List riskEventList = getRiskEvents(null); + if (riskEventList != null && riskEventList.size() > 0) { + for (JSONObject riskEvent : riskEventList) { + String clientMoniker = riskEvent.getString("client_moniker"); + JSONObject client = clientMapper.findClientByMonikerAll(clientMoniker); + String systemTransactionIds = riskEvent.getString("order_ids"); + if (StringUtils.isBlank(systemTransactionIds)) + continue; + String[] systemTransactionIdArr = riskEvent.getString("order_ids").split(","); + List realOrderIds = new ArrayList<>(); + if (client == null) + continue; + for (int i = 0; i < systemTransactionIdArr.length; i++) { + PageList transactionList = transactionMapper.findByClientIdAndSystemTransactionId( + client.getIntValue("client_id"), + systemTransactionIdArr[i], + new PageBounds(Order.formString("transaction_time.desc"))); + if (transactionList != null && transactionList.size() > 0) + realOrderIds.add(transactionList.get(0).getString("order_id")); + } + riskEvent.put("real_order_ids", StringUtils.join(realOrderIds, ",")); + //updateRiskEvent(riskEvent); + riskEventMapper.update(riskEvent); + } + } + } private byte[] generateRiskOrders(JSONObject event) throws IOException { String[] orderIds = event.getString("order_ids").split(","); JSONObject client = clientMapper.findClientByMonikerAll(event.getString("client_moniker")); Workbook wb = new XSSFWorkbook(); - String realOrderId = ""; for(String orderId : orderIds){ - realOrderId = orderMapper.findOrderById(orderId,client.getIntValue("client_id")).getString("order_id"); - JSONObject orderDetail = tradeLogService.getOrderDetail(new JSONObject(), event.getString("client_moniker"), realOrderId, null); + JSONObject orderDetail = tradeLogService.getOrderDetail(new JSONObject(), event.getString("client_moniker"), orderId, null); Sheet sheet = wb.createSheet(orderId); sheet.setDefaultColumnWidth((short) 40); Row row0 = sheet.createRow(0); @@ -648,6 +701,11 @@ public class RiskBusinessServiceImpl implements RiskBusinessService, ManagerTodo @Override public void checkTodo(JSONObject manager, List notices) { + /** + * 1、判断登录的角色是不是BD + * 2、列出BD管理的商户 + * 3、 + */ if (ManagerRole.BD_USER.hasRole(manager.getIntValue("role"))) { JSONObject params = new JSONObject(); params.put("bd_id", manager.getString("manager_id")); @@ -677,4 +735,104 @@ public class RiskBusinessServiceImpl implements RiskBusinessService, ManagerTodo } } } + + @Override + public void deleteRiskEvent(String riskId) { + riskEventMapper.deleteRiskEvent(riskId); + } + + @Override + public JSONObject getNoticeInfo(int clientId) { + + JSONObject client = clientMapper.findClient(clientId); + if(client == null){ + throw new InvalidShortIdException(); + } + JSONObject params = new JSONObject(); + params.put("is_send_client", 1); + List resultTypes = Arrays.asList(RiskResultTypeEnum.SEND_EMAIL_TO_BD.getResultType(), + RiskResultTypeEnum.MATERIAL_NOT_PASS.getResultType()); + params.put("result_types", resultTypes); + PageList riskEventList = riskEventMapper.listRisksByPage(params, new PageBounds(Order.formString("create_time.desc"))); + + JSONObject result = new JSONObject(); + result.put("notice_flag", false); + if (riskEventList != null && riskEventList.size() > 0) { + result.put("notice_flag", true); + } + return result; + } + + @Override + public JSONObject getRiskEventMaterialsRemark(String riskId) { + JSONObject riskEvent = riskEventMapper.findById(riskId); + Integer orderType = riskEvent.getInteger("order_type"); + List materialItemList = new ArrayList<>(); + + List materialsRemark = new ArrayList<>(); + if (orderType.equals(RiskOrderTypeEnum.WECHAT_ORDER.getOrderType())) { + materialsRemark = Arrays.asList( + "1、物流公司发货单据照片 要求:每笔交易对应的物流单必须提供,且单据必须清晰可见\n" + + "Photos of logistics companies’ goods-delivery documents Requirement: The logistics order record corresponding to each transaction must be provided, and details of records should be clearly visible. ", + "2、用户购买虚拟物品需要提供聊天记录、订单信息、发货凭证截图、 虚拟物品最终消费场景(例如何种游戏、软件)、提供消费场景网址/下载链接 要求:每笔交易对应的截图必须清晰可见\n" + + "Users need to provide chat records, order information, screenshots of delivery documents, final consumption scenarios of virtual goods (such as games, software); provide consumer scene URL / download link. Requirement: The screenshot corresponding to each transaction must be clearly visible. ", + "3、购物小票/发票存根照片 照片应清晰,必须显示商户名称、商户地址、购物时间、物品名称 购物金额等\n" + + "Photos of shopping receipts/ invoice stubs Requirement: The photos should be clear and must show Merchant name, Business address, Transaction time, Product information, Quantity purchased, etc. ", + "4、显示商户门牌号码和店头名称的照片 要求:清晰可见,至少一张\n" + + "Photos of Merchant Street number & Merchant name Requirement: At least one visible photo ", + "5、显示商户营业场景所场内部情况(如店内商品陈列、收银台等)的照片 要求:照片清晰,且能清楚显示商户实际售卖物品或服务,至少三张\n" + + "Photos of internal environment of merchant business (such as in-store merchandise display, checkout counter, etc.) Requirements: The photos (at least three) showing merchant activities including actual selling-goods or services obviously ", + "6、其他图片\n" + + "Other pictures " + ); + } else if (orderType.equals(RiskOrderTypeEnum.ALIPAY_ORDER.getOrderType())) { + String alipayMaterials = riskEvent.getString("alipay_materials"); + if (StringUtils.isNotBlank(alipayMaterials)) { + List alipayMaterialRemarkList = JSONObject.parseArray(alipayMaterials, JSONObject.class); + if (alipayMaterialRemarkList != null && alipayMaterialRemarkList.size() > 0) { + for (int i = 0; i < alipayMaterialRemarkList.size(); i++) { + materialsRemark.add(alipayMaterialRemarkList.get(i).getString("question" + (i + 1))); + } + } + } + } else if (orderType.equals(RiskOrderTypeEnum.ROYALPAY_ORDER.getOrderType())) { + materialsRemark = Arrays.asList( + "1.请解释相应的消费场景/业务模式,例如网站商城,扫码支付, 消费者到店支付等;\n" + + "Please explain the relative payment scenario/business activities, for example, online store, QR code payment, payment at the store, etc;", + "2.提供相应购物清单,订单小票(请提供与被查交易订单号相匹配的交易时间及金额的发票);\n" + + "Provide related shopping lists, invoices. (Please provide the invoices, amount of which matches that of the abnormal transaction);", + "3.提供相应的发货证明,报关单(若有消费者在国内购买,请提供物流单据或报关单);\n" + + "Relative proof of delivery, customs declaration (If the consumer purchased from China, please provide shipping receipt or customs declaration);", + "4.提供您的门店照片(门店照及店铺内的照片各一张, 一张可以看到商户名的门头照,一张可以看到相关商品或服务的店内照片);\n" + + "Photos of the store ( one of each front-store and in-store);", + "5.其他可以还原交易背景的资料,如和消费者的聊天记录等,来佐证被查单号交易的真实性;\n" + + "Other materials that can verify the payment scenario, for example, chatting history, to prove the truth of the transactions;", + "6、其他图片\n" + + "Other pictures" + ); + } + + JSONObject material = getRiskMaterial(riskEvent); + for (int i = 0; i < materialsRemark.size(); i++) { + JSONObject materialItem = new JSONObject(); + materialItem.put("question", materialsRemark.get(i)); + if (material != null) + materialItem.put("file", material.getJSONArray("file" + (i + 1))); + materialItemList.add(materialItem); + } + JSONObject result = new JSONObject(); + result.put("material", materialItemList); + if (material != null && material.containsKey("description")) + result.put("description", material.getString("description")); + return result; + } + + @Override + public JSONObject updateIsSendClient(String riskId) { + JSONObject event = riskEventMapper.findById(riskId); + event.put("is_send_client", 1); + riskEventMapper.update(event); + event = riskEventMapper.findById(riskId); + return event; + } } diff --git a/src/main/java/au/com/royalpay/payment/manage/riskbusiness/core/impl/RiskUploadServiceIpml.java b/src/main/java/au/com/royalpay/payment/manage/riskbusiness/core/impl/RiskUploadServiceIpml.java index 17133ae4a..6dae1717d 100644 --- a/src/main/java/au/com/royalpay/payment/manage/riskbusiness/core/impl/RiskUploadServiceIpml.java +++ b/src/main/java/au/com/royalpay/payment/manage/riskbusiness/core/impl/RiskUploadServiceIpml.java @@ -1,24 +1,17 @@ package au.com.royalpay.payment.manage.riskbusiness.core.impl; -import au.com.royalpay.payment.core.exceptions.EmailException; import au.com.royalpay.payment.manage.mappers.riskbusiness.RiskEventMapper; import au.com.royalpay.payment.manage.mappers.riskbusiness.RiskFileMapper; import au.com.royalpay.payment.manage.mappers.riskbusiness.RiskMaterialMapper; -import au.com.royalpay.payment.manage.mappers.system.ClientMapper; -import au.com.royalpay.payment.manage.notice.core.MailService; -import au.com.royalpay.payment.manage.riskbusiness.core.RiskBusinessService; import au.com.royalpay.payment.manage.riskbusiness.core.RiskUploadService; import au.com.royalpay.payment.manage.riskbusiness.enums.RiskResultTypeEnum; import au.com.royalpay.payment.tools.exceptions.BadRequestException; -import au.com.royalpay.payment.tools.threadpool.RoyalThreadPoolExecutor; import com.alibaba.fastjson.JSONObject; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.time.DateFormatUtils; import org.apache.commons.lang3.time.DateUtils; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; -import org.thymeleaf.context.Context; -import org.thymeleaf.spring4.SpringTemplateEngine; import javax.annotation.Resource; import java.text.ParseException; @@ -40,6 +33,7 @@ public class RiskUploadServiceIpml implements RiskUploadService { @Override public void submitMaterial(JSONObject material) { JSONObject event = riskEventMapper.findById(material.getString("risk_id")); + material.putIfAbsent("update_time", DateFormatUtils.format(new Date(), "yyyy-MM-dd hh:mm:ss")); riskMaterialMapper.save(material); material.put("material_id",riskMaterialMapper.findAllMaterials(material.getString("risk_id")).get(0).getString("material_id")); for(int i=1;i<=10;i++){ diff --git a/src/main/resources/au/com/royalpay/payment/manage/mappers/payment/OrderMapper.xml b/src/main/resources/au/com/royalpay/payment/manage/mappers/payment/OrderMapper.xml index 2eb0ebb9b..5afcb370e 100644 --- a/src/main/resources/au/com/royalpay/payment/manage/mappers/payment/OrderMapper.xml +++ b/src/main/resources/au/com/royalpay/payment/manage/mappers/payment/OrderMapper.xml @@ -739,17 +739,10 @@ - \ No newline at end of file diff --git a/src/main/resources/i18n/msg_en.properties b/src/main/resources/i18n/msg_en.properties index 5af979791..e7663bb89 100644 --- a/src/main/resources/i18n/msg_en.properties +++ b/src/main/resources/i18n/msg_en.properties @@ -88,7 +88,7 @@ todo.bd.order=The merchant managed by you is transferred. Please submit the mate app.message.title.payment=Payment Message app.message.body.payment=You have received a payment of app.message.title.risk=Risk Control Message -app.message.body.risk=You have received a risk control reminder. Please check the email for details. +app.message.body.risk=You have received a risk control reminder. Please handle as soon as possible. app.message.title.notice=System Message app.message.body.refund=Your refund request has bean sent,refund count is app.message.body.cashback=You got a cashback of diff --git a/src/main/resources/i18n/msg_zh.properties b/src/main/resources/i18n/msg_zh.properties index 44b3ca6ea..c700ff329 100644 --- a/src/main/resources/i18n/msg_zh.properties +++ b/src/main/resources/i18n/msg_zh.properties @@ -84,7 +84,7 @@ todo.bd.order=有商户被调单,请尽快提交材料 app.message.title.payment=到账通知 app.message.body.payment=您有一笔新的到账, app.message.title.risk=风控通知 -app.message.body.risk=您收到了一条风控提醒,详情请查看邮件 +app.message.body.risk=您收到了一条风控提醒,请及时处理 app.message.title.notice=系统通知 app.message.body.refund=退款申请已提交渠道方处理,退款金额 app.message.body.cashback=您获得了一笔ROYALPAY返现,金额 diff --git a/src/main/ui/static/analysis/risk_business.js b/src/main/ui/static/analysis/risk_business.js index fa8177534..113e07cc1 100644 --- a/src/main/ui/static/analysis/risk_business.js +++ b/src/main/ui/static/analysis/risk_business.js @@ -161,13 +161,15 @@ define(['angular', 'jquery', 'uiRouter', './monitoring/analysis-monitoring'], } ]); - app.controller('riskEventDetailCtrl', ['$scope', '$state', '$http', '$uibModal', '$filter', 'Upload', 'commonDialog', 'riskEvent', - function ($scope, $state, $http, $uibModal, $filter, Upload, commonDialog, riskEvent) { + app.controller('riskEventDetailCtrl', ['$scope', '$state', '$http', '$uibModal', '$filter', 'Upload', 'commonDialog', 'riskEvent', 'orderService', + function ($scope, $state, $http, $uibModal, $filter, Upload, commonDialog, riskEvent, orderService) { $scope.orderTypes = orderTypesMap; $scope.resultTypes = resultTypesMap; $scope.channelResults = channelResultArray; $scope.riskEvent = riskEvent.data; + //var index = $scope.riskEvent.order_ids.lastIndexOf(","); + //$scope.riskEvent.order_ids = $scope.riskEvent.order_ids.substring(0, index) + "," + $scope.riskEvent.order_ids.substring(index + 1); // 获取数据库中对应的渠道字段 var orderChannel = 'enable_'; if ($scope.riskEvent.order_type == 1) { @@ -279,6 +281,7 @@ define(['angular', 'jquery', 'uiRouter', './monitoring/analysis-monitoring'], }) }; + // 发送email $scope.resendUploadEmail = function () { commonDialog.confirm({ title: 'Warning', @@ -295,6 +298,10 @@ define(['angular', 'jquery', 'uiRouter', './monitoring/analysis-monitoring'], }) }; + // 订单详情 + $scope.showTradeDetail = function (order) { + orderService.managerOrderDetail(order) + }; // 以下为BD上传材料相关 $scope.material={}; @@ -535,6 +542,36 @@ define(['angular', 'jquery', 'uiRouter', './monitoring/analysis-monitoring'], $scope.orderTypes = orderTypesMap; $scope.royapayOrderTypes = royalpayOrderTypesMap; $scope.warningOrderTypes = warningOrderTypesMap; + $scope.materials = [{key: 0, value: ""}]; + $scope.canMinus = false; + + $scope.increase = function($index) { + $scope.materials.splice($index + 1, 0, + {key: new Date().getTime(), value: ""}); // 用时间戳作为每个item的key + // 增加新的input后允许删除 + $scope.canMinus = true; + } + + $scope.decrease = function($index) { + // 如果input大于1,删除 + if ($scope.materials.length > 1) { + $scope.materials.splice($index, 1); + } + // 如果回复数为1,不允许删除 + if ($scope.materials.length == 1) { + $scope.canMinus = false; + } + } + var array=new Array(); + $scope.combineMaterials = function() { + for (var i = 0; i < $scope.materials.length; i++) { + var cr = {}; + cr['question'+(i+1)] = $scope.materials[i].value; + array[i] = cr; + } + console.log(JSON.stringify(array)); + return JSON.stringify(array); + } $scope.save = function(form) { if (form.$invalid) { @@ -558,6 +595,8 @@ define(['angular', 'jquery', 'uiRouter', './monitoring/analysis-monitoring'], $scope.riskEvent.receive_email_date = $filter('date')($scope.riskEvent.receive_email_date, 'yyyy-MM-dd'); + $scope.riskEvent.alipay_materials = $scope.combineMaterials(); + $http.post('/risk/business/events', $scope.riskEvent).then(function (resp) { commonDialog.alert({ title: 'Success', @@ -579,7 +618,9 @@ define(['angular', 'jquery', 'uiRouter', './monitoring/analysis-monitoring'], $http.get('/risk/business/partners', {params: $scope.partnerParam}).then(function (resp) { $scope.partners = resp.data; if ($scope.partners != null && $scope.partners.length > 0) { - $scope.riskEvent.client_moniker = $scope.partners[0].client_moniker; + // 由于通用号调单可能无法提供商户client_moniker,所以后台无法查询到订单 + if ($scope.partners.length == 1 || $scope.riskEvent.order_type != 5) + $scope.riskEvent.client_moniker = $scope.partners[0].client_moniker; } else { commonDialog.confirm({ diff --git a/src/main/ui/static/analysis/templates/new_riskEvent.html b/src/main/ui/static/analysis/templates/new_riskEvent.html index 4900bf874..d1308f634 100644 --- a/src/main/ui/static/analysis/templates/new_riskEvent.html +++ b/src/main/ui/static/analysis/templates/new_riskEvent.html @@ -158,15 +158,17 @@ ng-if="riskEvent.order_type != 4" ng-class="{'has-error':riskEventForm.order_ids.$invalid && riskEventForm.order_ids.$dirty}"> + for="order-ids-input">Platform Transaction IDs
- +

+ +
+ + +
+ +
+
+ + +
+
+ diff --git a/src/main/ui/static/analysis/templates/riskEvent_detail.html b/src/main/ui/static/analysis/templates/riskEvent_detail.html index 32ac4246e..cf87f3394 100644 --- a/src/main/ui/static/analysis/templates/riskEvent_detail.html +++ b/src/main/ui/static/analysis/templates/riskEvent_detail.html @@ -43,6 +43,14 @@ +
+ +
+

+
+
+
@@ -53,10 +61,10 @@
- -
-

+ +

+

+ {{riskEvent.order_ids}}

@@ -227,8 +235,8 @@ Partner - Order ID Platform Transaction ID + Order ID Order Description Customer ID IP @@ -247,8 +255,8 @@ {{trade.client.short_name}}({{trade.client.client_moniker}}) - {{trade.order_id}} {{trade.system_transaction_id}} + {{trade.order_id}} {{trade.order_description}} {{trade.customer_id}} {{trade.customer_ip}} @@ -267,6 +275,7 @@ + @@ -275,24 +284,31 @@ + + +
Platform Transaction ID Order ID Amount Input AmountStatus Create Time GatewayOperation
{{trade.system_transaction_id}} {{trade.order_id}} {{trade.currency}} {{trade.total_amount}} {{trade.currency}} {{trade.display_amount}} AUD {{trade.clearing_amount}} - - + + - + + + +
@@ -389,7 +405,7 @@ ng-if="riskEventEdit.order_type != 4" ng-class="{'has-error':riskEventForm.order_ids.$invalid && riskEventForm.order_ids.$dirty}">
- +
- {{riskEvent.result_type | resultType:resultSearchTypes}} + - + {{riskEvent.result_type | resultType:resultSearchTypes}} - + + {{riskEvent.email_status | emailStatus}} + - +