diff --git a/src/main/java/au/com/royalpay/payment/manage/analysis/core/impls/EstimateAnalysisServiceImpl.java b/src/main/java/au/com/royalpay/payment/manage/analysis/core/impls/EstimateAnalysisServiceImpl.java index 9521c1680..c12c98bcb 100644 --- a/src/main/java/au/com/royalpay/payment/manage/analysis/core/impls/EstimateAnalysisServiceImpl.java +++ b/src/main/java/au/com/royalpay/payment/manage/analysis/core/impls/EstimateAnalysisServiceImpl.java @@ -167,42 +167,6 @@ public class EstimateAnalysisServiceImpl implements EstimateAnalysisService { dayInfo.put("t1", 0); } - List hfSettle = platformSettlementMapper.findBySettleDate(new Date(estimateAnalysisMapper.findLastCleanDays(end_date, 1).getDate("date_str").getTime()), "hf"); - if (hfSettle !=null && hfSettle.size()>0) { - for (JSONObject logs : hfSettle) { - dayInfo.put("hfSettleFee_" + logs.getString("merchants"), logs.getBigDecimal("settlement_fee")); - dayInfo.put("platformGetSettleFee",dayInfo.getBigDecimal("hfSettleFee_" + logs.getString("merchants"))); - } - }else { - dayInfo.put("platformGetSettleFee",BigDecimal.ZERO); - } - - List alipaySettleLogs = platformSettlementMapper.findBySettleDate(new Date(estimateAnalysisMapper.findLastCleanDays(end_date, 1).getDate("date_str").getTime()), "Alipay"); - for (JSONObject logs : alipaySettleLogs) { - dayInfo.put("aliSettleFee_" + logs.getString("merchants"), logs.getBigDecimal("settlement_fee")); - dayInfo.put("platformGetSettleFee",dayInfo.getBigDecimal("platformGetSettleFee").add(dayInfo.getBigDecimal("aliSettleFee_" + logs.getString("merchants")))); - } - - List alipayOnlineSettleLogs = platformSettlementMapper.findBySettleDate(new Date(estimateAnalysisMapper.findLastCleanDays(end_date, 1).getDate("date_str").getTime()), "AlipayOnline"); - logger.info(" Estimate alipayOnlineSettleLogs is :{}", alipayOnlineSettleLogs.toString()); - for (JSONObject logs : alipayOnlineSettleLogs) { - dayInfo.put("aliOnlineSettleFee_" + logs.getString("merchants"), logs.getBigDecimal("settlement_fee")); - dayInfo.put("platformGetSettleFee", dayInfo.getBigDecimal("platformGetSettleFee").add(dayInfo.getBigDecimal("aliOnlineSettleFee_" + logs.getString("merchants")))); - } - cleanDays.clear(); - - //T2 - maxDays = estimateAnalysisMapper.findLastCleanDays(end_date, 1); - end_date = maxDays.getString("date_str"); - cleanDays = estimateAnalysisMapper.findLastCleanDays(start_date, 1); - start_date = cleanDays.getString("date_str"); - JSONObject totalAmountT2 = estimateAnalysisMapper.findAllTransactionByDate(start_date, end_date, t2client); - if (totalAmountT2 != null) { - dayInfo.put("t2", totalAmountT2.getBigDecimal("total_amount")); - } else { - dayInfo.put("t2", 0); - } - List tencentSettle = platformSettlementMapper.findBySettleDate(new Date(maxDays.getDate("date_str").getTime() - 86400000L), "Wechat"); if (tencentSettle != null && tencentSettle.size()>0) { for (JSONObject logs : tencentSettle) { @@ -239,6 +203,42 @@ public class EstimateAnalysisServiceImpl implements EstimateAnalysisService { } + List hfSettle = platformSettlementMapper.findBySettleDate(new Date(estimateAnalysisMapper.findLastCleanDays(end_date, 1).getDate("date_str").getTime()), "hf"); + if (hfSettle !=null && hfSettle.size()>0) { + for (JSONObject logs : hfSettle) { + dayInfo.put("hfSettleFee_" + logs.getString("merchants"), logs.getBigDecimal("settlement_fee")); + dayInfo.put("platformGetSettleFee",dayInfo.getBigDecimal("hfSettleFee_" + logs.getString("merchants"))); + } + }else { + dayInfo.put("platformGetSettleFee",BigDecimal.ZERO); + } + + List alipaySettleLogs = platformSettlementMapper.findBySettleDate(new Date(estimateAnalysisMapper.findLastCleanDays(end_date, 1).getDate("date_str").getTime()), "Alipay"); + for (JSONObject logs : alipaySettleLogs) { + dayInfo.put("aliSettleFee_" + logs.getString("merchants"), logs.getBigDecimal("settlement_fee")); + dayInfo.put("platformGetSettleFee",dayInfo.getBigDecimal("platformGetSettleFee").add(dayInfo.getBigDecimal("aliSettleFee_" + logs.getString("merchants")))); + } + + List alipayOnlineSettleLogs = platformSettlementMapper.findBySettleDate(new Date(estimateAnalysisMapper.findLastCleanDays(end_date, 1).getDate("date_str").getTime()), "AlipayOnline"); + logger.info(" Estimate alipayOnlineSettleLogs is :{}", alipayOnlineSettleLogs.toString()); + for (JSONObject logs : alipayOnlineSettleLogs) { + dayInfo.put("aliOnlineSettleFee_" + logs.getString("merchants"), logs.getBigDecimal("settlement_fee")); + dayInfo.put("platformGetSettleFee", dayInfo.getBigDecimal("platformGetSettleFee").add(dayInfo.getBigDecimal("aliOnlineSettleFee_" + logs.getString("merchants")))); + } + cleanDays.clear(); + + //T2 + maxDays = estimateAnalysisMapper.findLastCleanDays(end_date, 1); + end_date = maxDays.getString("date_str"); + cleanDays = estimateAnalysisMapper.findLastCleanDays(start_date, 1); + start_date = cleanDays.getString("date_str"); + JSONObject totalAmountT2 = estimateAnalysisMapper.findAllTransactionByDate(start_date, end_date, t2client); + if (totalAmountT2 != null) { + dayInfo.put("t2", totalAmountT2.getBigDecimal("total_amount")); + } else { + dayInfo.put("t2", 0); + } + //T3 maxDays = estimateAnalysisMapper.findLastCleanDays(end_date, 1); end_date = maxDays.getString("date_str"); diff --git a/src/main/java/au/com/royalpay/payment/manage/mappers/payment/OrderMapper.java b/src/main/java/au/com/royalpay/payment/manage/mappers/payment/OrderMapper.java index cb0a76396..0b400d7dd 100644 --- a/src/main/java/au/com/royalpay/payment/manage/mappers/payment/OrderMapper.java +++ b/src/main/java/au/com/royalpay/payment/manage/mappers/payment/OrderMapper.java @@ -80,7 +80,7 @@ public interface OrderMapper { PageList listTransactionsForApp(JSONObject params, PageBounds pageBounds); - JSONObject findOrderById(@Param("order_id") String orderId); + JSONObject findOrderById(@Param("order_id") String orderId,@Param("client_id") int clientId); List listHalloweenActOrder(JSONObject param); } 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 new file mode 100644 index 000000000..d27b4351b --- /dev/null +++ b/src/main/java/au/com/royalpay/payment/manage/mappers/riskbusiness/RiskEventMapper.java @@ -0,0 +1,34 @@ +package au.com.royalpay.payment.manage.mappers.riskbusiness; + +import cn.yixblog.support.mybatis.autosql.annotations.AutoMapper; +import cn.yixblog.support.mybatis.autosql.annotations.AutoSql; +import cn.yixblog.support.mybatis.autosql.annotations.SqlType; +import com.alibaba.fastjson.JSONObject; +import com.github.miemiedev.mybatis.paginator.domain.PageBounds; +import com.github.miemiedev.mybatis.paginator.domain.PageList; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @Author lvjian + * @Date 2018/10/10 10:25 + */ +@AutoMapper(tablename = "risk_event", pkName = "risk_id") +public interface RiskEventMapper { + + @AutoSql(type = SqlType.INSERT) + void save(JSONObject riskEvent); + + @AutoSql(type = SqlType.UPDATE) + void update(JSONObject riskEvent); + + @AutoSql(type = SqlType.SELECT) + List findAll(JSONObject params); + + PageList listRisksByPage(JSONObject params, PageBounds pageBounds); + + @AutoSql(type = SqlType.SELECT) + JSONObject findById(@Param("risk_id") String riskId); + +} diff --git a/src/main/java/au/com/royalpay/payment/manage/mappers/riskbusiness/RiskFileMapper.java b/src/main/java/au/com/royalpay/payment/manage/mappers/riskbusiness/RiskFileMapper.java new file mode 100644 index 000000000..6120db3cd --- /dev/null +++ b/src/main/java/au/com/royalpay/payment/manage/mappers/riskbusiness/RiskFileMapper.java @@ -0,0 +1,18 @@ +package au.com.royalpay.payment.manage.mappers.riskbusiness; + +import cn.yixblog.support.mybatis.autosql.annotations.AutoMapper; +import cn.yixblog.support.mybatis.autosql.annotations.AutoSql; +import cn.yixblog.support.mybatis.autosql.annotations.SqlType; +import com.alibaba.fastjson.JSONObject; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +@AutoMapper(tablename = "risk_file", pkName = "file_id") +public interface RiskFileMapper { + @AutoSql(type= SqlType.INSERT) + void save(JSONObject file); + + @AutoSql(type= SqlType.SELECT) + List findAllFiles(@Param("material_id") String material_id); +} diff --git a/src/main/java/au/com/royalpay/payment/manage/mappers/riskbusiness/RiskMaterialMapper.java b/src/main/java/au/com/royalpay/payment/manage/mappers/riskbusiness/RiskMaterialMapper.java new file mode 100644 index 000000000..f5e9f5b9f --- /dev/null +++ b/src/main/java/au/com/royalpay/payment/manage/mappers/riskbusiness/RiskMaterialMapper.java @@ -0,0 +1,20 @@ +package au.com.royalpay.payment.manage.mappers.riskbusiness; + + +import cn.yixblog.support.mybatis.autosql.annotations.AutoMapper; +import cn.yixblog.support.mybatis.autosql.annotations.AutoSql; +import cn.yixblog.support.mybatis.autosql.annotations.SqlType; +import com.alibaba.fastjson.JSONObject; +import org.apache.ibatis.annotations.Param; + + +import java.util.List; + +@AutoMapper(tablename = "risk_material", pkName = "material_id") +public interface RiskMaterialMapper { + @AutoSql(type = SqlType.INSERT) + void save(JSONObject material); + + List findAllMaterials(@Param("risk_id") String risk_id); + +} diff --git a/src/main/java/au/com/royalpay/payment/manage/mappers/system/ClientBDMapper.java b/src/main/java/au/com/royalpay/payment/manage/mappers/system/ClientBDMapper.java index 09bc51de0..b8e390f0b 100644 --- a/src/main/java/au/com/royalpay/payment/manage/mappers/system/ClientBDMapper.java +++ b/src/main/java/au/com/royalpay/payment/manage/mappers/system/ClientBDMapper.java @@ -25,6 +25,8 @@ public interface ClientBDMapper { List listClientBDInfoAvailable(@Param("client_id") int clientId, @Param("date") Date date); + List listBDClientInfo(JSONObject param); + void updateClientDB(JSONObject jsonObject); @AutoSql(type = SqlType.UPDATE) diff --git a/src/main/java/au/com/royalpay/payment/manage/mappers/system/ClientMapper.java b/src/main/java/au/com/royalpay/payment/manage/mappers/system/ClientMapper.java index 4ade2bd6a..4e48045ce 100644 --- a/src/main/java/au/com/royalpay/payment/manage/mappers/system/ClientMapper.java +++ b/src/main/java/au/com/royalpay/payment/manage/mappers/system/ClientMapper.java @@ -36,6 +36,10 @@ public interface ClientMapper { @AutoSql(type = SqlType.SELECT) JSONObject findClientByMonikerAll(@Param("client_moniker") String clientMoniker); + @AutoSql(type = SqlType.SELECT) + @AdvanceSelect(addonWhereClause = "is_valid=1") + List getClientBySubMerchantId(@Param("sub_merchant_id") String subMerchantId); + PageList listPartners(JSONObject params, PageBounds pagination); PageList comListPartners(JSONObject params, PageBounds pagination); diff --git a/src/main/java/au/com/royalpay/payment/manage/merchants/core/ClientManager.java b/src/main/java/au/com/royalpay/payment/manage/merchants/core/ClientManager.java index f19d10018..1c21c90fd 100644 --- a/src/main/java/au/com/royalpay/payment/manage/merchants/core/ClientManager.java +++ b/src/main/java/au/com/royalpay/payment/manage/merchants/core/ClientManager.java @@ -351,4 +351,6 @@ public interface ClientManager { boolean postponeClientRate(int clientId, String clientMoniker,String nextYearExipryDate); JSONObject comListPartnerSelection(JSONObject manager, PartnerQuery query); + + List getClientBySimpleQuery(JSONObject param); } diff --git a/src/main/java/au/com/royalpay/payment/manage/merchants/core/impls/ClientManagerImpl.java b/src/main/java/au/com/royalpay/payment/manage/merchants/core/impls/ClientManagerImpl.java index 0520f541e..40042d8cc 100644 --- a/src/main/java/au/com/royalpay/payment/manage/merchants/core/impls/ClientManagerImpl.java +++ b/src/main/java/au/com/royalpay/payment/manage/merchants/core/impls/ClientManagerImpl.java @@ -4029,6 +4029,14 @@ public class ClientManagerImpl implements ClientManager, ManagerTodoNoticeProvid }); } + @Override + public List getClientBySimpleQuery(JSONObject param) { + String subMerchantId = param.getString("sub_merchant_id"); + if (StringUtils.isNotBlank(subMerchantId)) { + return clientMapper.getClientBySubMerchantId(subMerchantId); + } + return null; + } @Override @Transactional public boolean postponeClientRate(int clientId, String clientMoniker, String nextYearExipryDate) { diff --git a/src/main/java/au/com/royalpay/payment/manage/notice/core/MailService.java b/src/main/java/au/com/royalpay/payment/manage/notice/core/MailService.java index 3044b09fc..1763781d6 100644 --- a/src/main/java/au/com/royalpay/payment/manage/notice/core/MailService.java +++ b/src/main/java/au/com/royalpay/payment/manage/notice/core/MailService.java @@ -17,6 +17,8 @@ public interface MailService { String sendEmail(String title, String mailTos, String mailCcs, String content, List attachFiles) throws URISyntaxException, IOException; + String sendRiskEmail(String title, String mailTos, String mailCcs,String mailBcc, String content, List attachFiles, int order_type) throws URISyntaxException, IOException; + List checkEmailStatus(String emailId); void removeUnsub(Long id); diff --git a/src/main/java/au/com/royalpay/payment/manage/notice/core/impls/MailServiceImp.java b/src/main/java/au/com/royalpay/payment/manage/notice/core/impls/MailServiceImp.java index 63a1ed1db..cb639e796 100644 --- a/src/main/java/au/com/royalpay/payment/manage/notice/core/impls/MailServiceImp.java +++ b/src/main/java/au/com/royalpay/payment/manage/notice/core/impls/MailServiceImp.java @@ -266,4 +266,40 @@ public class MailServiceImp implements MailService { } } + @Override + public String sendRiskEmail(String title, String mailTos, String mailCcs,String mailBcc, String content, List attachFiles, int order_type) throws URISyntaxException, IOException { + NoticeBean noticeBean = new NoticeBean(); + noticeBean.setTitle(title); + List mailClients = new ArrayList<>(); + JSONObject mailClient = new JSONObject(); + mailClient.put("mailto", mailTos); + mailClient.put("mailcc", mailCcs); + mailClient.put("mailbcc", mailBcc); + mailClients.add(mailClient); + noticeBean.setMailClients(mailClients); + noticeBean.setContent(content); + noticeBean.setAttachFiles(attachFiles); + noticeBean.setSenderAddress("riskcontrol@royalpay.com.au"); + noticeBean.setPassword("RPrisk123"); + if(order_type == 1 || order_type == 2){ + noticeBean.setSenderAddress("risk@royalpay.com.au"); + noticeBean.setPassword("Tunnelrisk123"); + } + String postUrl = mailHost + "/mail/single?" + generateMailSignParam(); + HttpRequestResult result = null; + try { + logger.info("===sendEmail===noticeBean:" + JSON.toJSON(noticeBean)); + result = new HttpRequestGenerator(postUrl, RequestMethod.POST).setJSONEntity(noticeBean).setTimeout(60_000).execute(); + if (result.isSuccess()) { + String mail_id = result.getResponseContentJSONObj().getString("mail_id"); + return mail_id; + //System.out.println("send Mail=============="+mail_id); + } else { + throw new ServerErrorException("Error Connection"); + } + } catch (URISyntaxException e) { + throw new ServerErrorException("Error Connection"); + } + } + } diff --git a/src/main/java/au/com/royalpay/payment/manage/riskbusiness/bean/RiskEventQuery.java b/src/main/java/au/com/royalpay/payment/manage/riskbusiness/bean/RiskEventQuery.java new file mode 100644 index 000000000..29b3bb14f --- /dev/null +++ b/src/main/java/au/com/royalpay/payment/manage/riskbusiness/bean/RiskEventQuery.java @@ -0,0 +1,201 @@ +package au.com.royalpay.payment.manage.riskbusiness.bean; + +import au.com.royalpay.payment.core.exceptions.ParamInvalidException; +import com.alibaba.fastjson.JSONObject; +import org.apache.commons.lang3.StringUtils; + +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; + +/** + * @Author lvjian + * @Date 2018/10/10 11:27 + */ +public class RiskEventQuery { + + // 调单类型 + private Integer orderType; + + // 商户编码 + private String clientMoniker; + + // 子商户号 + private String subMerchantId; + + // 订单号(多个,以逗号分隔) + private String orderIds; + + // 邮件发送状态 + private Integer emailStatus; + + // 行业 + private String industry; + + // 处理结果 + private Integer resultType; + + // 收到调单邮件日期 + private String receiveEmailDate; + + // 邮件回复截止日期 + private String replyEmailDate; + + private Integer page = 1; + + // 金额区间 + private String startAmount; + private String endAmount; + + public String getStartAmount() { + return startAmount; + } + + public void setStartAmount(String startAmount) { + this.startAmount = startAmount; + } + + public String getEndAmount() { + return endAmount; + } + + public void setEndAmount(String endAmount) { + this.endAmount = endAmount; + } + + public Integer getOrderType() { + return orderType; + } + + public void setOrderType(Integer orderType) { + this.orderType = orderType; + } + + public String getClientMoniker() { + return clientMoniker; + } + + public void setClientMoniker(String clientMoniker) { + this.clientMoniker = clientMoniker; + } + + public String getSubMerchantId() { + return subMerchantId; + } + + public void setSubMerchantId(String subMerchantId) { + this.subMerchantId = subMerchantId; + } + + public String getOrderIds() { + return orderIds; + } + + public void setOrderIds(String orderIds) { + this.orderIds = orderIds; + } + + public Integer getEmailStatus() { + return emailStatus; + } + + public void setEmailStatus(Integer emailStatus) { + this.emailStatus = emailStatus; + } + + public String getIndustry() { + return industry; + } + + public void setIndustry(String industry) { + this.industry = industry; + } + + public Integer getResultType() { + return resultType; + } + + public void setResultType(Integer resultType) { + this.resultType = resultType; + } + + public String getReceiveEmailDate() { + return receiveEmailDate; + } + + public void setReceiveEmailDate(String receiveEmailDate) { + this.receiveEmailDate = receiveEmailDate; + } + + public String getReplyEmailDate() { + return replyEmailDate; + } + + public void setReplyEmailDate(String replyEmailDate) { + this.replyEmailDate = replyEmailDate; + } + + public Integer getPage() { + return page; + } + + public void setPage(Integer page) { + this.page = page; + } + + public JSONObject toJSON() { + + JSONObject params = new JSONObject(); + + if (orderType != null && orderType >= 1) { + params.put("order_type", orderType); + } + + if (StringUtils.isNotBlank(clientMoniker)) { + params.put("client_moniker", clientMoniker); + } + + if (StringUtils.isNotBlank(subMerchantId)) { + params.put("sub_merchant_id", subMerchantId); + } + + if (StringUtils.isNotBlank(orderIds)) { + orderIds = orderIds.trim().replace(",", ","); + params.put("order_ids", orderIds); + } + + if (emailStatus != null && emailStatus >= 0) { + params.put("email_status", emailStatus); + } + + if (resultType != null && resultType >= 0) { + params.put("result_type", resultType); + } + + if (StringUtils.isNotBlank(industry)) { + params.put("industry", industry); + } + + if (receiveEmailDate != null) { + params.put("receive_email_date", receiveEmailDate); + } + + if (replyEmailDate != null) { + params.put("reply_email_date", replyEmailDate); + } + + if (page != null && page > 0) { + params.put("page", page); + } + + if (StringUtils.isNotBlank(startAmount)) { + params.put("start_amount", startAmount); + } + + if (StringUtils.isNotBlank(endAmount)) { + params.put("end_amount", endAmount); + } + + return params; + } +} 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 new file mode 100644 index 000000000..52ccf932d --- /dev/null +++ b/src/main/java/au/com/royalpay/payment/manage/riskbusiness/core/RiskBusinessService.java @@ -0,0 +1,87 @@ +package au.com.royalpay.payment.manage.riskbusiness.core; + +import com.alibaba.fastjson.JSONObject; +import com.github.miemiedev.mybatis.paginator.domain.PageBounds; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.List; + +/** + * @Author lvjian + * @Date 2018/10/10 10:29 + */ +public interface RiskBusinessService { + + /** + * 风险事件列表 + * @param params + * @return + */ + List getRiskEvents(JSONObject params); + + /** + * 分页查询风险事件 + * @param params + * @return + */ + JSONObject getRiskEventsByPage(JSONObject params, JSONObject manager); + + /** + * 风险事件详情 + * @param riskId + * @return + */ + JSONObject getRiskEventDetail(String riskId); + + /** + * 获取风险事件的调单信息 + * @param riskEvent + * @return + */ + List getRiskEventOrderList(JSONObject riskEvent); + + /** + * 新增风险事件 + * @param params + */ + void addRiskEvent(JSONObject params, JSONObject manager); + + /** + * 更新事件 + * @param params + */ + void updateRiskEvent(JSONObject params); + + /** + * 下载审核材料(zip) + * @param riskId + */ + void downloadAuditMaterialZiP(String riskId, HttpServletResponse response); + + /** + * 发送上传材料的邮件 + * @param riskId + */ + void sendUploadEmail(String riskId) throws IOException; + + /** + * 发送拒绝邮件 + * @param riskId + */ + void sendRefuseEmail(String riskId) throws IOException; + + /** + * 发送提醒邮件 + * @param riskId + */ + void sendUrgeEmail(String riskId) throws IOException; + + + /** + * 获取最新上传的审核材料 + * @param param + * @return + */ + JSONObject getRiskMaterial(JSONObject param); +} diff --git a/src/main/java/au/com/royalpay/payment/manage/riskbusiness/core/RiskUploadService.java b/src/main/java/au/com/royalpay/payment/manage/riskbusiness/core/RiskUploadService.java new file mode 100644 index 000000000..33cc158b2 --- /dev/null +++ b/src/main/java/au/com/royalpay/payment/manage/riskbusiness/core/RiskUploadService.java @@ -0,0 +1,24 @@ +package au.com.royalpay.payment.manage.riskbusiness.core; + +import com.alibaba.fastjson.JSONObject; + +public interface RiskUploadService { + /** + * 上传材料 + * @param material + */ + void submitMaterial(JSONObject material); + + /** + * 删除缓存 + * @param codeKey + */ + void deleteUploadMailKey(String codeKey); + + /** + * + * @param codeKey + * @param risk_id + */ + void checkUploadMailKey(String codeKey,String risk_id); +} 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 new file mode 100644 index 000000000..27802aa3e --- /dev/null +++ b/src/main/java/au/com/royalpay/payment/manage/riskbusiness/core/impl/RiskBusinessServiceImpl.java @@ -0,0 +1,670 @@ +package au.com.royalpay.payment.manage.riskbusiness.core.impl; + +import au.com.royalpay.payment.core.exceptions.EmailException; +import au.com.royalpay.payment.core.exceptions.InvalidShortIdException; +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.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.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.bean.AppManagerMessageBuilder; +import au.com.royalpay.payment.manage.riskbusiness.core.RiskBusinessService; +import au.com.royalpay.payment.manage.riskbusiness.enums.RiskResultTypeEnum; +import au.com.royalpay.payment.manage.signin.beans.TodoNotice; +import au.com.royalpay.payment.manage.signin.core.ManagerTodoNoticeProvider; +import au.com.royalpay.payment.manage.tradelog.core.TradeLogService; +import au.com.royalpay.payment.manage.riskbusiness.enums.RiskOrderTypeEnum; +import au.com.royalpay.payment.tools.device.message.AppMessage; +import au.com.royalpay.payment.tools.device.message.AppMsgSender; +import au.com.royalpay.payment.tools.env.PlatformEnvironment; +import au.com.royalpay.payment.tools.exceptions.BadRequestException; +import au.com.royalpay.payment.tools.locale.LocaleSupport; +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.JSONObject; +import com.github.miemiedev.mybatis.paginator.domain.Order; +import com.github.miemiedev.mybatis.paginator.domain.PageBounds; +import com.github.miemiedev.mybatis.paginator.domain.PageList; +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.lang3.RandomStringUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.time.DateFormatUtils; +import org.apache.commons.lang3.time.DateUtils; +import org.apache.poi.ss.usermodel.*; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.slf4j.Logger; +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.thymeleaf.context.Context; +import org.thymeleaf.spring4.SpringTemplateEngine; + +import javax.servlet.http.HttpServletResponse; +import java.io.*; +import java.net.URL; +import java.util.*; +import javax.annotation.Resource; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; +import java.util.concurrent.TimeUnit; + +/** + * @Author lvjian + * @Date 2018/10/10 10:30 + */ +@Service +public class RiskBusinessServiceImpl implements RiskBusinessService, ManagerTodoNoticeProvider { + + private Logger logger = LoggerFactory.getLogger(RiskBusinessServiceImpl.class); + + @Resource + private RiskEventMapper riskEventMapper; + @Resource + private ClientMapper clientMapper; + @Resource + private ClientBDMapper clientBDMapper; + @Resource + private OrderMapper orderMapper; + @Resource + private StringRedisTemplate stringRedisTemplate; + @Resource + private SpringTemplateEngine thymeleaf; + @Resource + private MailService mailService; + @Resource + private TradeLogService tradeLogService; + @Resource + private RoyalThreadPoolExecutor royalThreadPoolExecutor; + private final String UPLOAD_MAIL_PREFIX = "UPLOAD_MAIL"; + + @Resource + private RiskMaterialMapper riskMaterialMapper; + @Resource + private RiskFileMapper riskFileMapper; + @Resource + private ClientDeviceTokenMapper clientDeviceTokenMapper; + @Resource + private AppMessageLogMapper appMessageLogMapper; + + private Map senderMap = new HashMap<>(); + + private ThreadPoolExecutor sendingAppleMsgPool = new ThreadPoolExecutor(10, 30, 5, TimeUnit.SECONDS, new LinkedBlockingQueue()); + + @Override + public List getRiskEvents(JSONObject params) { + return riskEventMapper.findAll(params); + } + + @Override + 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"))) { + params.put("bd_id", manager.getString("manager_id")); + List orderTypes = Arrays.asList(RiskOrderTypeEnum.WECHAT_ORDER.getOrderType(), + RiskOrderTypeEnum.ALIPAY_ORDER.getOrderType()); + params.put("order_types", orderTypes); + + 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()); + params.put("result_types", resultTypes); + } + + PageList riskEvents = riskEventMapper.listRisksByPage(params, new PageBounds(params.getInteger("page"), 10, Order.formString("create_time.desc"))); + return PageListUtils.buildPageListResult(riskEvents); + } + + @Override + public JSONObject getRiskEventDetail(String riskId) { + + JSONObject riskEventDetail = riskEventMapper.findById(riskId); + // 获取商户信息 + JSONObject client = null; + String clientMoniker = riskEventDetail.getString("client_moniker"); + if (clientMoniker != null) { + client = clientMapper.findClientByMonikerAll(clientMoniker); + if (client == null) { + throw new InvalidShortIdException(); + } + } + riskEventDetail.put("clientInfo", client); + return riskEventDetail; + } + + @Override + public List getRiskEventOrderList(JSONObject riskEvent) { + String orderIds = riskEvent.getString("order_ids"); + JSONObject client = clientMapper.findClientByMonikerAll(riskEvent.getString("client_moniker")); + List tradeLogs = new ArrayList<>(); + if (StringUtils.isNotBlank(orderIds)) { + String[] orderIdArray = orderIds.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); + tradeLogs.add(orderInfo); + } + } else { + for (int i = 0; i < orderIdArray.length; i++) { + orderInfo = orderMapper.findOrderById(orderIdArray[i],client.getIntValue("client_id")); + tradeLogs.add(orderInfo); + } + } + } + return tradeLogs; + } + + @Override + public void addRiskEvent(JSONObject params, JSONObject manager) { + // 通用号调单不需要填写client_moniker + JSONObject client = null; + String clientMoniker = params.getString("client_moniker"); + if (clientMoniker != null) { + client = clientMapper.findClientByMoniker(clientMoniker); + if(client == null){ + throw new InvalidShortIdException(); + } + } + + 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)) { + // 去除所有空格与中文逗号',' + orderIds = orderIds.replace(",", ","); + orderIds = orderIds.replace(" ", ""); + params.put("order_ids", orderIds); + String[] orderIdArray = orderIds.split(","); + List orderAmountList = new ArrayList<>(); + for (int i = 0; i < orderIdArray.length; i++) { + JSONObject orderInfo = orderMapper.findOrderById(orderIdArray[i],client.getIntValue("client_id")); + // 判断该笔订单是否存在,是否属于该商户 + if (orderInfo == null) + throw new OrderNotExistsException(); + else { + if (!clientMoniker.equals(orderInfo.getString("partner_code"))) { + throw new OrderNotMatchException(); + } + orderAmountList.add(orderInfo.getString("total_amount")); + } + } + params.put("order_amounts", StringUtils.join(orderAmountList, ",")); + } + riskEventMapper.save(params); + } + + @Override + public void updateRiskEvent(JSONObject params) { + riskEventMapper.update(params); + } + + @Override + public void downloadAuditMaterialZiP(String riskId, HttpServletResponse response) { + + JSONObject riskEvent = riskEventMapper.findById(riskId); + String clientMoniker = riskEvent.getString("client_moniker"); + JSONObject param = new JSONObject(); + param.put("risk_id", riskId); + param.put("orderby_type", "update_time"); + JSONObject riskMaterial = getRiskMaterial(param); + try { + String downloadFilename = clientMoniker + "_audit_materials_" + DateFormatUtils.format(new Date(), "dd/MM/yyyy HH:mm:ss").toString() + ".zip"; + response.setContentType("application/octet-stream"); + response.setHeader("Content-Disposition", "attachment;filename=" + downloadFilename); + ZipOutputStream zos = new ZipOutputStream(response.getOutputStream()); + for(int i=1;i<=6;i++){ + if(riskMaterial.containsKey("file"+i)){ + List fileList= (List)riskMaterial.get("file"+i); + for(String fileUrl : fileList){ + zos.putNextEntry(new ZipEntry("file" + i+fileUrl.substring(fileUrl.lastIndexOf("/")))); + InputStream inputStream = new URL(fileUrl).openConnection().getInputStream(); + byte[] buffer = new byte[1024]; + int result = 0; + while ((result = inputStream.read(buffer)) != -1) { + zos.write(buffer, 0, result); + } + inputStream.close(); + } + } + } + zos.flush(); + zos.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + public void sendUploadEmail(String riskId) throws IOException { + JSONObject event = getRiskEventDetail(riskId); + Context ctx = getMailContext(event); + final List emailsTos = (List)ctx.getVariable("emailsTos"); + final List emailsCcs = ctx.getVariable("emailsCcs")==null?new ArrayList<>():(List)ctx.getVariable("emailsCcs"); + final String title = (String)ctx.getVariable("title"); + final String content = thymeleaf.process("mail/risk_upload_mail.html", ctx); + final String uploadUrl = (String)ctx.getVariable("uploadUrl"); + royalThreadPoolExecutor.execute(() -> { + try { + String emailId = mailService.sendRiskEmail(title, emailsTos.isEmpty() ? "" : StringUtils.join(emailsTos, ","), + emailsCcs.isEmpty() ? "" : StringUtils.join(emailsCcs, ","), "",content, null,event.getIntValue("order_type")); + event.put("email_status",1); + 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()) { + event.put("result_type", RiskResultTypeEnum.ALREADY_HANDLED.getResultType()); + } + riskEventMapper.update(event); + } catch (Exception e) { + throw new EmailException("Email Sending Failed", e); + } + }); + 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) { + Runnable task = () -> { + String token = devToken.getString("token"); + if (token == null) { + return; + } + JSONObject log = saveAppMessageLog(devToken.getString("dev_id"), devToken.getIntValue("client_id"), "risk", 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")); + AppMsgSender sender = senderMap.get(devToken.getString("client_type")); + if (token == null || sender == null) { + return; + } + JSONObject managerMsg = new JSONObject(); + managerMsg.put("title", LocaleSupport.localeMessage("app.message.title.risk")); + managerMsg.put("body", + LocaleSupport.localeMessage("app.message.body.risk")); + managerMsg.put("type", type); + managerMsg.put("data", event); + managerMsg.put("msgType", "risk"); + AppMessage appMessage = new AppManagerMessageBuilder(managerMsg).buildMessage(); + sender.sendMessage(appMessage, devToken); + log.put("status", 2); + appMessageLogMapper.update(log); + } 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); + } + }; + sendingAppleMsgPool.execute(task); + } + } + + private JSONObject saveAppMessageLog(String dev_id, int client_id, String messageType, String dev_token, String remark) { + JSONObject log = new JSONObject(); + log.put("dev_id", dev_id); + log.put("client_id", client_id); + log.put("msg_type", messageType); + log.put("dev_token", dev_token); + log.put("remark", remark); + log.put("send_time", new Date()); + appMessageLogMapper.save(log); + return log; + + } + + @Override + public void sendRefuseEmail(String riskId) throws IOException { + JSONObject event = getRiskEventDetail(riskId); + Context ctx = getMailContext(event); + ctx.setVariable("refuse",true); + final List emailsTos = (List)ctx.getVariable("emailsTos"); + final List emailsCcs = ctx.getVariable("emailsCcs")==null?new ArrayList<>():(List)ctx.getVariable("emailsCcs"); + final String uploadUrl = (String)ctx.getVariable("uploadUrl"); + final String content = thymeleaf.process("mail/risk_upload_mail.html", ctx); + royalThreadPoolExecutor.execute(() -> { + try { + String emailId = mailService.sendRiskEmail("You need to resubmit risk materials", emailsTos.isEmpty() ? "" : StringUtils.join(emailsTos, ","), + emailsCcs.isEmpty() ? "" : StringUtils.join(emailsCcs, ","), "",content, null,event.getIntValue("order_type")); + event.put("email_status",2); + event.put("result_type",RiskResultTypeEnum.MATERIAL_NOT_PASS.getResultType()); + event.put("submit_url",uploadUrl); + riskEventMapper.update(event); + } catch (Exception e) { + throw new EmailException("Email Sending Failed", e); + } + }); + } + + @Override + public void sendUrgeEmail(String riskId) throws IOException { + JSONObject event = getRiskEventDetail(riskId); + Context ctx = getMailContext(event); + final List emailsTos = (List)ctx.getVariable("emailsTos"); + final List emailsCcs = ctx.getVariable("emailsCcs")==null?new ArrayList<>():(List)ctx.getVariable("emailsCcs"); + final String content = thymeleaf.process("mail/risk_urge_mail.html", ctx); + royalThreadPoolExecutor.execute(() -> { + try { + String emailId = mailService.sendRiskEmail("Please submit risk materials as soon as possible", emailsTos.isEmpty() ? "" : StringUtils.join(emailsTos, ","), + emailsCcs.isEmpty() ? "" : StringUtils.join(emailsCcs, ","),"", content, null,event.getIntValue("order_type")); + event.put("email_status",3); + riskEventMapper.update(event); + } catch (Exception e) { + throw new EmailException("Email Sending Failed", e); + } + }); + } + + private Context getMailContext(JSONObject event) throws IOException { + String clientMoniker = event.getString("client_moniker"); + JSONObject client = clientMapper.findClientByMonikerAll(clientMoniker); + if (client == null) { + throw new InvalidShortIdException(); + } + String codeKey = RandomStringUtils.random(20, true, true); + while(stringRedisTemplate.boundValueOps(getRiskUploadKey(codeKey)).get()!=null ){ + codeKey = RandomStringUtils.random(20, true, true); + } + String codeKeyValue = RandomStringUtils.random(10, true, true); + /* + String expireDay = "7"; + if(event.getIntValue("order_type")>2){ + expireDay = "3"; + } + )*/ + // 原来设定的过期时间是7天,现在改成一个月 + String expireDay = "30"; + stringRedisTemplate.boundValueOps(getRiskUploadKey(codeKey)).set(codeKeyValue, Long.parseLong(expireDay), TimeUnit.DAYS); + String uploadUrl = PlatformEnvironment.getEnv().concatUrl("/risk/upload/") + event.getString("risk_id") + "/" + codeKey; + int orderType = event.getIntValue("order_type"); + if (orderType == 1 || orderType == 2) + uploadUrl = PlatformEnvironment.getEnv().concatUrl("/manage.html#/analysis/monitoring/") + event.getString("risk_id") + "/bd/detail?codeKey=" + codeKey; + //uploadUrl = "localhost:9009" + "/manage.html#/analysis/monitoring/" + event.getString("risk_id") + "/bd/detail"; + List bds = clientBDMapper.listClientBDInfoAvailable(client.getIntValue("client_id"), new Date()); + List bdNames = new ArrayList<>(); + List bdEmails = new ArrayList<>(); + for (JSONObject bd : bds) { + String bdName = bd.getString("display_name"); + if (StringUtils.isNotEmpty(bdName)) { + bdNames.add(bdName); + } + String email = bd.getString("email"); + if (StringUtils.isNotEmpty(email)) { + bdEmails.add(email); + } + } + List clientEmails = new ArrayList<>(); + clientEmails.add(client.getString("contact_email")); + String bdNamesStr = bdNames.isEmpty() ? "" : StringUtils.join(bdNames, ","); + String reply_date = DateFormatUtils.format(DateUtils.addDays(event.getDate("reply_email_date"),-1),"yyyy年MM月dd日"); + String reply_date_english = DateFormatUtils.format(DateUtils.addDays(event.getDate("reply_email_date"),-1),"dd/MM/yyyy"); + GregorianCalendar gregorianCalendar = new GregorianCalendar(); + String hello = gregorianCalendar.get(GregorianCalendar.AM_PM) == 0 ? "上午好" : "下午好"; + Context ctx = new Context(); + ctx.setVariable("hello", hello); + ctx.setVariable("order_type", event.getIntValue("order_type")); + ctx.setVariable("bdNamesStr", bdNamesStr); + ctx.setVariable("reply_date", reply_date); + ctx.setVariable("reply_date_english", reply_date_english); + ctx.setVariable("client", client); + 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(","); + List orders = new ArrayList(); + switch (event.getIntValue("order_type")){ + case 1: + case 2: + for(String orderId : orderIds){ + JSONObject order = orderMapper.findOrderById(orderId,client.getIntValue("client_id")); + if(order==null){ + throw new BadRequestException("Order: "+orderId+" not exists"); + } + orders.add(order); + } + ctx.setVariable("orders", orders); + ctx.setVariable("title","Your merchants needs to submit risk materials"); + 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); + if(order==null){ + throw new BadRequestException("Order: "+orderId+" not exists"); + } + order.put("order_description", StringUtils.defaultString(order.getString("order_description"))); + order.put("gateway", getGateWay(order.getIntValue("gateway"))); + order.put("status", getStatus(order.getIntValue("status"))); + order.put("order_detail", StringUtils.defaultString(order.getString("order_detail"))); + order.put("total_amount", order.getString("currency") + " " + order.getString("total_amount")); + order.put("display_amount", order.getString("currency") + " " + order.getString("display_amount")); + order.put("customer_payment_amount", order.getString("currency") + " " + order.getString("customer_payment_amount")); + order.put("clearing_amount", "AUD "+ order.getString("clearing_amount")); + orders.add(order); + } + ctx.setVariable("orders", orders); +// List attachList = new ArrayList<>(); +// JSONObject file = new JSONObject(); +// file.put("name", client.getString("short_name")+ "被查单号相关信息.xlsx"); +// file.put("content", Base64.encodeBase64String(generateRiskOrders(event))); +// attachList.add(file); +// ctx.setVariable("files",attachList); + case 4: + ctx.setVariable("title","RoyalPay风控调查 — " + client.getString("short_name")); + ctx.setVariable("emailsCcs", bdEmails); + ctx.setVariable("emailsTos", clientEmails); + break; + } + return ctx; + } + private String getRiskUploadKey(String codeKey){ + return UPLOAD_MAIL_PREFIX + codeKey; + } + + @Override + public JSONObject getRiskMaterial(JSONObject param) { + List riskMaterialList = riskMaterialMapper.findAllMaterials(param.getString("risk_id")); + if (riskMaterialList != null && riskMaterialList.size() > 0){ + List files = riskFileMapper.findAllFiles(riskMaterialList.get(0).getString("material_id")); + JSONObject fileNew = new JSONObject(); + fileNew.put("description",riskMaterialList.get(0).getString("description")); + for(JSONObject file : files){ + int fileType = file.getIntValue("file_type"); + if(!fileNew.containsKey("file"+fileType)){ + List fileList = new ArrayList<>(); + fileList.add(file.getString("file_url")); + fileNew.put("file"+fileType,fileList); + }else{ + List fileList = (List)fileNew.get("file"+fileType); + fileList.add(file.getString("file_url")); + fileNew.put("file"+fileType,fileList); + } + } + return fileNew; + } + + return null; + } + + + + 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); + Sheet sheet = wb.createSheet(orderId); + sheet.setDefaultColumnWidth((short) 40); + Row row0 = sheet.createRow(0); + Row row1 = sheet.createRow(1); + Row row2 = sheet.createRow(2); + Row row3 = sheet.createRow(3); + Row row4 = sheet.createRow(4); + Row row5 = sheet.createRow(5); + Row row6 = sheet.createRow(6); + Row row7 = sheet.createRow(7); + Row row8 = sheet.createRow(8); + Row row9 = sheet.createRow(9); + Row row10 = sheet.createRow(10); + Row row11 = sheet.createRow(11); + Row row12 = sheet.createRow(12); + Row row13 = sheet.createRow(13); + Row row14 = sheet.createRow(14); + Row row15 = sheet.createRow(15); + row0.createCell(0,Cell.CELL_TYPE_STRING).setCellValue("Partner"); + row0.createCell(1,Cell.CELL_TYPE_STRING).setCellValue(orderDetail.getJSONObject("client").getString("short_name")+"("+orderDetail.getJSONObject("client").getString("client_moniker")+")"); + row1.createCell(0,Cell.CELL_TYPE_STRING).setCellValue("Order ID"); + row1.createCell(1,Cell.CELL_TYPE_STRING).setCellValue(orderDetail.getString("order_id")); + row2.createCell(0,Cell.CELL_TYPE_STRING).setCellValue("Platform Transaction ID"); + row2.createCell(1,Cell.CELL_TYPE_STRING).setCellValue(orderDetail.getString("system_transaction_id")); + row3.createCell(0,Cell.CELL_TYPE_STRING).setCellValue("Order Description"); + row3.createCell(1,Cell.CELL_TYPE_STRING).setCellValue(StringUtils.defaultString(orderDetail.getString("order_description"))); + row4.createCell(0,Cell.CELL_TYPE_STRING).setCellValue("Customer ID"); + row4.createCell(1,Cell.CELL_TYPE_STRING).setCellValue(orderDetail.getString("customer_id")); + row5.createCell(0,Cell.CELL_TYPE_STRING).setCellValue("IP"); + row5.createCell(1,Cell.CELL_TYPE_STRING).setCellValue(orderDetail.getString("customer_ip")); + row6.createCell(0,Cell.CELL_TYPE_STRING).setCellValue("Total Amount"); + row6.createCell(1,Cell.CELL_TYPE_STRING).setCellValue(orderDetail.getString("currency")+" "+orderDetail.getString("total_amount")); + row7.createCell(0,Cell.CELL_TYPE_STRING).setCellValue("Input Amount"); + row7.createCell(1,Cell.CELL_TYPE_STRING).setCellValue(orderDetail.getString("currency")+" "+orderDetail.getString("display_amount")); + row8.createCell(0,Cell.CELL_TYPE_STRING).setCellValue("Pay Amount"); + row8.createCell(1,Cell.CELL_TYPE_STRING).setCellValue(orderDetail.getString("currency")+" "+orderDetail.getString("customer_payment_amount")); + row9.createCell(0,Cell.CELL_TYPE_STRING).setCellValue("Exchange Rate"); + row9.createCell(1,Cell.CELL_TYPE_STRING).setCellValue(orderDetail.getString("exchange_rate")); + row10.createCell(0,Cell.CELL_TYPE_STRING).setCellValue("Clearing Amount"); + row10.createCell(1,Cell.CELL_TYPE_STRING).setCellValue("AUD "+ orderDetail.getString("clearing_amount")); + row11.createCell(0,Cell.CELL_TYPE_STRING).setCellValue("Gateway"); + row11.createCell(1,Cell.CELL_TYPE_STRING).setCellValue(getGateWay(orderDetail.getIntValue("gateway"))); + row12.createCell(0,Cell.CELL_TYPE_STRING).setCellValue("Create Time"); + row12.createCell(1,Cell.CELL_TYPE_STRING).setCellValue(orderDetail.getString("create_time")); + row13.createCell(0,Cell.CELL_TYPE_STRING).setCellValue("Status"); + row13.createCell(1,Cell.CELL_TYPE_STRING).setCellValue(getStatus(orderDetail.getIntValue("status"))); + row14.createCell(0,Cell.CELL_TYPE_STRING).setCellValue("Pay Time"); + row14.createCell(1,Cell.CELL_TYPE_STRING).setCellValue(orderDetail.getString("transaction_time")); + row15.createCell(0,Cell.CELL_TYPE_STRING).setCellValue("Order Detail"); + row15.createCell(1,Cell.CELL_TYPE_STRING).setCellValue(StringUtils.defaultString(orderDetail.getString("order_detail"))); + } + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + wb.write(bos); + bos.flush(); + return bos.toByteArray(); + } + private String getGateWay(int gateWay){ + switch (gateWay) { + case 0: + return "线下扫码"; + case 1: + return "线下扫码"; + case 2: + return "商户静态码"; + case 3: + return "线上网关"; + case 4: + return "JSAPI网关"; + case 5: + return "线下网关"; + case 6: + return "线下网关"; + case 7: + return "商户静态码"; + case 8: + return "Mobile H5"; + case 9: + return "第三方网关"; + case 10: + return "APP网关"; + case 11: + return "账单码"; + case 12: + return "小程序"; + case 13: + return "原生二维码"; + case 14: + return "账单链接"; + } + return ""; + } + + private String getStatus(int status){ + switch (status) { + case 0: + return "Creating"; + case 1: + return "Failed Create Order"; + case 2: + return "Wait For Payment"; + case 3: + return "Closed"; + case 4: + return "Payment Failed"; + case 5: + return "Payment Success"; + case 6: + return "Partial Refund"; + case 7: + return "Full Refund"; + } + return ""; + } + + @Override + public void checkTodo(JSONObject manager, List notices) { + if (ManagerRole.BD_USER.hasRole(manager.getIntValue("role"))) { + JSONObject params = new JSONObject(); + params.put("bd_id", manager.getString("manager_id")); + params.put("date", new Date()); + List riskClientList = clientBDMapper.listBDClientInfo(params); + boolean noticeFlag = false; + for (JSONObject client : riskClientList) { + if (!noticeFlag) { + params.put("client_moniker", client.getString("client_moniker")); + List riskEventList = riskEventMapper.findAll(params); + for (JSONObject event : riskEventList) { + Integer resultType = event.getIntValue("result_type"); + Integer orderType = event.getIntValue("order_type"); + // Integer是对象,所以用equals方法比较 + if ((resultType.equals(RiskResultTypeEnum.SEND_EMAIL_TO_BD.getResultType()) || resultType.equals(RiskResultTypeEnum.MATERIAL_NOT_PASS.getResultType())) && (orderType.equals(RiskOrderTypeEnum.WECHAT_ORDER.getOrderType()) || orderType.equals(RiskOrderTypeEnum.ALIPAY_ORDER.getOrderType()))) { + noticeFlag = true; + break; + } + } + } else { + break; + } + } + if (noticeFlag) { + String msg = LocaleSupport.localeMessage("todo.bd.order"); + notices.add(new TodoNotice("riskBusiness", msg, "#/analysis/monitoring/risk_business_bd")); + } + } + } +} 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 new file mode 100644 index 000000000..17133ae4a --- /dev/null +++ b/src/main/java/au/com/royalpay/payment/manage/riskbusiness/core/impl/RiskUploadServiceIpml.java @@ -0,0 +1,90 @@ +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; +import java.util.Date; +import java.util.List; + +@Service +public class RiskUploadServiceIpml implements RiskUploadService { + @Resource + private RiskMaterialMapper riskMaterialMapper; + @Resource + private RiskFileMapper riskFileMapper; + @Resource + private RiskEventMapper riskEventMapper; + @Resource + private StringRedisTemplate stringRedisTemplate; + private final String UPLOAD_MAIL_PREFIX = "UPLOAD_MAIL"; + + @Override + public void submitMaterial(JSONObject material) { + JSONObject event = riskEventMapper.findById(material.getString("risk_id")); + 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++){ + if(material.containsKey("file"+i+"_url")){ + List urls = (List)material.get("file"+i+"_url"); + for(String url:urls){ + JSONObject file = new JSONObject(); + file.put("file_url",url); + file.put("file_type",i); + file.put("material_id",material.getString("material_id")); + riskFileMapper.save(file); + } + } + } + event.put("result_type", RiskResultTypeEnum.WAIT_FOR_AUDIT.getResultType()); + riskEventMapper.update(event); + } + + @Override + public void deleteUploadMailKey(String codeKey) { + stringRedisTemplate.delete(getRiskUploadKey(codeKey)); + } + + @Override + public void checkUploadMailKey(String codeKey,String risk_id) { + JSONObject event = riskEventMapper.findById(risk_id); + //到期日前一天的下午6点前url可用 + try { + String reply = DateFormatUtils.format(DateUtils.addDays(event.getDate("reply_email_date"),-1),"yyyy-MM-dd 18:00:00"); + if(new Date().after( DateUtils.parseDate(reply,new String[]{"yyyy-MM-dd HH:mm:ss"}))){ + deleteUploadMailKey(codeKey); + throw new BadRequestException("Url expired"); + } + } catch (ParseException e) { + e.printStackTrace(); + } + + if (StringUtils.isNotEmpty(codeKey)) { + String redisUpload = stringRedisTemplate.boundValueOps(getRiskUploadKey(codeKey)).get(); + if (redisUpload == null) { + throw new BadRequestException("Url expired"); + } + } + } + private String getRiskUploadKey(String codeKey){ + return UPLOAD_MAIL_PREFIX + codeKey; + } +} diff --git a/src/main/java/au/com/royalpay/payment/manage/riskbusiness/enums/RiskEmailStatusEnum.java b/src/main/java/au/com/royalpay/payment/manage/riskbusiness/enums/RiskEmailStatusEnum.java new file mode 100644 index 000000000..7f9f2e570 --- /dev/null +++ b/src/main/java/au/com/royalpay/payment/manage/riskbusiness/enums/RiskEmailStatusEnum.java @@ -0,0 +1,27 @@ +package au.com.royalpay.payment.manage.riskbusiness.enums; + +/** + * @Author lvjian + * @Date 2018/10/16 22:22 + */ +public enum RiskEmailStatusEnum { + NOT_SEND(0), + ALREADY_SEND(1), + BACK_AND_SEND(2), + SEND_EMAIL_AGAIN(3), + ; + + private Integer emailStatus; + + RiskEmailStatusEnum(Integer emailStatus) { + this.emailStatus = emailStatus; + } + + public Integer getEmailStatus() { + return emailStatus; + } + + public void setEmailStatus(Integer emailStatus) { + this.emailStatus = emailStatus; + } +} diff --git a/src/main/java/au/com/royalpay/payment/manage/riskbusiness/enums/RiskOrderTypeEnum.java b/src/main/java/au/com/royalpay/payment/manage/riskbusiness/enums/RiskOrderTypeEnum.java new file mode 100644 index 000000000..d0d5604ff --- /dev/null +++ b/src/main/java/au/com/royalpay/payment/manage/riskbusiness/enums/RiskOrderTypeEnum.java @@ -0,0 +1,29 @@ +package au.com.royalpay.payment.manage.riskbusiness.enums; + +/** + * @Author lvjian + * @Date 2018/10/16 20:18 + */ +public enum RiskOrderTypeEnum { + + WECHAT_ORDER(1), + ALIPAY_ORDER(2), + ROYALPAY_ORDER(3), + WARNING_ORDER(4), + GENERAL_ORDER(5) + ; + + private Integer orderType; + + public Integer getOrderType() { + return orderType; + } + + public void setOrderType(Integer orderType) { + this.orderType = orderType; + } + + RiskOrderTypeEnum(Integer orderType) { + this.orderType = orderType; + } +} diff --git a/src/main/java/au/com/royalpay/payment/manage/riskbusiness/enums/RiskResultTypeEnum.java b/src/main/java/au/com/royalpay/payment/manage/riskbusiness/enums/RiskResultTypeEnum.java new file mode 100644 index 000000000..2938586d8 --- /dev/null +++ b/src/main/java/au/com/royalpay/payment/manage/riskbusiness/enums/RiskResultTypeEnum.java @@ -0,0 +1,29 @@ +package au.com.royalpay.payment.manage.riskbusiness.enums; + +/** + * @Author lvjian + * @Date 2018/10/16 20:40 + */ +public enum RiskResultTypeEnum { + + NOT_HANDLED(0), + SEND_EMAIL_TO_BD(1), + WAIT_FOR_AUDIT(2), + MATERIAL_AUDIT_PASS(3), + MATERIAL_NOT_PASS(4), + ALREADY_HANDLED(5); + + private Integer resultType; + + RiskResultTypeEnum(Integer resultType) { + this.resultType = resultType; + } + + public Integer getResultType() { + return resultType; + } + + public void setResultType(Integer resultType) { + this.resultType = resultType; + } +} diff --git a/src/main/java/au/com/royalpay/payment/manage/riskbusiness/web/RiskBusinessController.java b/src/main/java/au/com/royalpay/payment/manage/riskbusiness/web/RiskBusinessController.java new file mode 100644 index 000000000..b92252ec5 --- /dev/null +++ b/src/main/java/au/com/royalpay/payment/manage/riskbusiness/web/RiskBusinessController.java @@ -0,0 +1,132 @@ +package au.com.royalpay.payment.manage.riskbusiness.web; + +import au.com.royalpay.payment.manage.merchants.beans.PartnerQuery; +import au.com.royalpay.payment.manage.merchants.core.ClientManager; +import au.com.royalpay.payment.manage.permission.manager.ManagerMapping; +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.enums.RiskResultTypeEnum; +import au.com.royalpay.payment.tools.CommonConsts; +import au.com.royalpay.payment.tools.permission.enums.ManagerRole; +import com.alibaba.fastjson.JSONObject; +import com.sun.org.apache.xerces.internal.impl.dv.xs.BooleanDV; +import com.sun.org.apache.xpath.internal.operations.Bool; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; + +/** + * 风控业务 + * @Author lvjian + * @Date 2018/10/10 1:12 + */ +@RestController +@ManagerMapping(value = "/risk/business/", role = {ManagerRole.OPERATOR, ManagerRole.ADMIN, ManagerRole.BD_USER, ManagerRole.RISK_MANAGER}) +public class RiskBusinessController { + + @Autowired + private RiskBusinessService riskBusinessService; + + @Autowired + private ClientManager clientManager; + + @GetMapping(value = "events") + public JSONObject getRiskEvents(RiskEventQuery riskEventQuery, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) { + JSONObject params = riskEventQuery.toJSON(); + return riskBusinessService.getRiskEventsByPage(params, manager); + } + + @GetMapping(value = "events/{risk_id}") + public JSONObject getRiskEventDetail(@PathVariable("risk_id") String riskId, + @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) { + JSONObject riskEvent = riskBusinessService.getRiskEventDetail(riskId); + List tradeLogs = riskBusinessService.getRiskEventOrderList(riskEvent); + riskEvent.put("tradeLogs", tradeLogs); + return riskEvent; + } + + @PostMapping(value = "events") + public void RegisterRiskEvent(@RequestBody JSONObject params, + @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) { + riskBusinessService.addRiskEvent(params, manager); + } + + @PutMapping(value = "events") + public void UpdateRiskEvent(@RequestBody JSONObject params) { + riskBusinessService.updateRiskEvent(params); + } + + @GetMapping(value = "/{risk_id}/download/materialsAsZIP") + public void downloadComplianceZip(@PathVariable("risk_id") String riskId, HttpServletResponse response) throws Exception { + riskBusinessService.downloadAuditMaterialZiP(riskId, response); + } + + + @RequestMapping(value = "/{risk_id}/upload_mail",method = RequestMethod.PUT) + public void uploadEmail(@PathVariable String risk_id) throws IOException { + riskBusinessService.sendUploadEmail(risk_id); + } + + @RequestMapping(value = "/{risk_id}/refuse",method = RequestMethod.PUT) + public void refuseEmail(@PathVariable String risk_id) throws IOException { + riskBusinessService.sendRefuseEmail(risk_id); + } + + @GetMapping(value = "/{risk_id}/material") + public JSONObject getRiskMaterial(@PathVariable("risk_id") String riskId) { + JSONObject param = new JSONObject(); + param.put("risk_id", riskId); + return riskBusinessService.getRiskMaterial(param); + } + + @PutMapping(value = "/channel/{channel}/permission/{channelFlag}") + public void updateMerchantChannel(@RequestBody JSONObject params, + @PathVariable("channelFlag") Boolean channelFlag, + @PathVariable("channel") String channel, + @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) { + clientManager.switchChannelPermission(manager, params.getString("client_moniker"), channel, channelFlag); + + if (channelFlag) + params.put("result_type", RiskResultTypeEnum.ALREADY_HANDLED.getResultType()); + riskBusinessService.updateRiskEvent(params); + } + + @PutMapping(value = "/partner/{isValid}") + public void updateMerchantValid(@RequestBody JSONObject params, + @PathVariable("isValid") Boolean isValid, + @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) { + String clientMoniker = params.getString("client_moniker"); + if (isValid) { + clientManager.disableClient(clientMoniker, manager); + Integer temporaryCloseMerchant = params.getInteger("temporary_close_merchant"); + if (temporaryCloseMerchant != 1) { + params.put("result_type", RiskResultTypeEnum.ALREADY_HANDLED.getResultType()); + } + } + else { + clientManager.revertClient(clientMoniker, manager); + params.put("result_type", RiskResultTypeEnum.ALREADY_HANDLED.getResultType()); + } + riskBusinessService.updateRiskEvent(params); + + } + @RequestMapping(value = "/{risk_id}/urge",method = RequestMethod.PUT) + public void urgeEmail(@PathVariable String risk_id) throws IOException { + riskBusinessService.sendUrgeEmail(risk_id); + } + + @GetMapping(value = "/partners") + public List getPartners(PartnerQuery partnerQuery) { + JSONObject param = partnerQuery.toJsonParam(); + return clientManager.getClientBySimpleQuery(param); + } +} + diff --git a/src/main/java/au/com/royalpay/payment/manage/riskbusiness/web/RiskFileUploadController.java b/src/main/java/au/com/royalpay/payment/manage/riskbusiness/web/RiskFileUploadController.java new file mode 100644 index 000000000..68bb91911 --- /dev/null +++ b/src/main/java/au/com/royalpay/payment/manage/riskbusiness/web/RiskFileUploadController.java @@ -0,0 +1,50 @@ +package au.com.royalpay.payment.manage.riskbusiness.web; + +import au.com.royalpay.payment.manage.riskbusiness.core.RiskBusinessService; +import au.com.royalpay.payment.manage.riskbusiness.core.RiskUploadService; +import com.alibaba.fastjson.JSONObject; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.ModelAndView; + +import javax.annotation.Resource; + +@RestController +@RequestMapping("/risk/upload") +public class RiskFileUploadController { + @Resource + private RiskUploadService riskUploadService; + @Resource + private RiskBusinessService riskBusinessService; + + /** + * 上传材料的链接 + * @param codeKey + * @param risk_id + * @return + */ + @RequestMapping(value = "/{risk_id}/{codeKey}", method = RequestMethod.GET) + public ModelAndView jumpVerifyMail(@PathVariable String codeKey, @PathVariable String risk_id) { + //检查codekey是否有效 + riskUploadService.checkUploadMailKey(codeKey,risk_id); + JSONObject event = riskBusinessService.getRiskEventDetail(risk_id); + ModelAndView view = new ModelAndView("mail/risk_upload"); + view.addObject("codeKey", codeKey); + view.addObject("risk_id",risk_id); + view.addObject("order_type",event.getIntValue("order_type")); + view.addObject("short_name",event.getJSONObject("clientInfo").getString("short_name")); + return view; + } + + /** + * 上传调单材料 + * @param codeKey + * @param material + */ + @RequestMapping(value = "/{codeKey}", method = RequestMethod.POST) + public void upload(@PathVariable String codeKey, @RequestBody JSONObject material) { + riskUploadService.checkUploadMailKey(codeKey, material.getString("risk_id")); + riskUploadService.submitMaterial(material); + riskUploadService.deleteUploadMailKey(codeKey); + } + +} diff --git a/src/main/java/au/com/royalpay/payment/manage/support/attachment/web/AttachmentController.java b/src/main/java/au/com/royalpay/payment/manage/support/attachment/web/AttachmentController.java index 34a8f2907..bccc665f9 100644 --- a/src/main/java/au/com/royalpay/payment/manage/support/attachment/web/AttachmentController.java +++ b/src/main/java/au/com/royalpay/payment/manage/support/attachment/web/AttachmentController.java @@ -27,6 +27,10 @@ public class AttachmentController { public JSONObject uploadImage(@RequestParam MultipartFile file) throws IOException { return attachmentClient.uploadFile(file,false); } + @RequestMapping(value = "/riskFiles", method = RequestMethod.POST) + public JSONObject uploadRiskImage(@RequestParam MultipartFile file) throws IOException { + return attachmentClient.uploadFile(file,false); + } @RequestMapping(value = "/secret_files", method = RequestMethod.POST) @RequirePartner diff --git a/src/main/resources/application-dev.properties b/src/main/resources/application-dev.properties index 91173a856..51ea1ca57 100644 --- a/src/main/resources/application-dev.properties +++ b/src/main/resources/application-dev.properties @@ -1,6 +1,6 @@ spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.schema-name=royalpay_production -spring.datasource.host=192.168.0.49:3306 +spring.datasource.host=192.168.0.111:3306 spring.datasource.url=jdbc:mysql://${spring.datasource.host}/${spring.datasource.schema-name}?useUnicode=true&characterEncoding=utf8&useSSL=false spring.datasource.username=root spring.datasource.password=root \ No newline at end of file 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 de0da503a..2eb0ebb9b 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 @@ -738,6 +738,90 @@ and t.clearing_status=#{clearing_status} + + + + + SELECT + re.risk_id, + re.client_moniker, + re.order_ids, + re.order_type, + re.royalpay_order_type, + re.warning_order_type, + re.description, + re.email_status, + re.receive_email_date, + re.reply_email_date, + re.fillin_person, + re.fillin_id, + re.result_type, + re.channel_result, + re.temporary_close_channel, + re.temporary_close_merchant, + re.in_merchant_blacklist, + re.in_user_blacklist, + re.processed_remark, + re.create_time, + sc.industry, + sc.short_name, + IFNULL(sc.sub_merchant_id, re.sub_merchant_id) sub_merchant_id + FROM risk_event re + LEFT JOIN sys_clients sc + ON re.client_moniker = sc.client_moniker + + RIGHT JOIN( + SELECT distinct re.risk_id + FROM + risk_event re, + risk_event_help reh + + reh.risk_event_help_id < (LENGTH(re.order_amounts) - LENGTH(REPLACE(re.order_amounts, ',' , ''))) + 1 + + AND cast(SUBSTRING_INDEX(SUBSTRING_INDEX(order_amounts,',',reh.risk_event_help_id + 1),',',-1) as signed) >= #{start_amount} + + + + AND cast(SUBSTRING_INDEX(SUBSTRING_INDEX(order_amounts,',',reh.risk_event_help_id + 1),',',-1) as signed) <= #{end_amount} + + + + ) temp + on re.risk_id = temp.risk_id + + + + INNER JOIN( + SELECT DISTINCT client_id + FROM sys_client_bd + WHERE + is_valid = 1 + AND bd_id = #{bd_id} + AND ( end_date IS NULL OR end_date > NOW()) + + ) scb + ON sc.client_id = scb.client_id + + + + AND re.risk_id = #{risk_id} + + + AND re.client_moniker = #{client_moniker} + + + + + #{order_type_item} + + + + + AND re.order_type = #{order_type} + + + + + #{result_type_item} + + + + + AND re.result_type = #{result_type} + + + + AND re.order_ids LIKE CONCAT('%', #{order_ids}, '%') + + + AND sc.sub_merchant_id = #{sub_merchant_id} + + + AND sc.industry = #{industry} + + + AND re.receive_email_date = #{receive_email_date} + + + AND re.reply_email_date = #{reply_email_date} + + + + + \ No newline at end of file diff --git a/src/main/resources/au/com/royalpay/payment/manage/mappers/riskbusiness/RiskMaterialMapper.xml b/src/main/resources/au/com/royalpay/payment/manage/mappers/riskbusiness/RiskMaterialMapper.xml new file mode 100644 index 000000000..5db6ff17c --- /dev/null +++ b/src/main/resources/au/com/royalpay/payment/manage/mappers/riskbusiness/RiskMaterialMapper.xml @@ -0,0 +1,21 @@ + + + + + + + diff --git a/src/main/resources/au/com/royalpay/payment/manage/mappers/system/ClientBDMapper.xml b/src/main/resources/au/com/royalpay/payment/manage/mappers/system/ClientBDMapper.xml index d525812a4..a80c8423e 100644 --- a/src/main/resources/au/com/royalpay/payment/manage/mappers/system/ClientBDMapper.xml +++ b/src/main/resources/au/com/royalpay/payment/manage/mappers/system/ClientBDMapper.xml @@ -41,11 +41,29 @@ #{date} OR end_date IS NULL) AND - b.is_valid = 1 + INNER JOIN sys_client_bd b + ON b.bd_id = m.manager_id + WHERE client_id = #{client_id} + AND start_date <= #{date} + AND (end_date > #{date} OR end_date IS NULL) + AND b.is_valid = 1 + ]]> + + + + + + + + + + + + + + + +
+ Submit +
+ + + + + + + + + + + +
+
+ + diff --git a/src/main/resources/templates/mail/risk_upload_mail.html b/src/main/resources/templates/mail/risk_upload_mail.html new file mode 100644 index 000000000..38e301ca0 --- /dev/null +++ b/src/main/resources/templates/mail/risk_upload_mail.html @@ -0,0 +1,140 @@ + +
+ Dear : +

+ + ,您提交的风控材料已被拒绝。 请于 + + 下午5:00(悉尼时间)前提供腾讯被查商户 + ()的以下材料: +

+

1、请提供以下被查单号的小票, 物流单据(如有邮寄产品的情况), 以及消费者与买家的聊天记录等来佐证被查交易单号。 被查交易单号如下:

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Order IDAmountInput AmountAUD AmountExchange RateStatusCreate TimeGateway
+

如果提交的材料不齐, 则有关停支付的风险。感谢,辛苦。

+ +

Submit Risk Materials

+
+
+ 尊敬的RoyalPay商户 :
+ Dear RoyalPay merchant :
+

您提交的风控材料已被拒绝。
+ The risk materials you submitted has been rejected +

+

近期由于我们的风控系统检测到您的交易异常,已暂时将您的清算周期调整为T+,还请您提供以下材料,还原附件中列明的交易的真实背景:
+ RoyalPay's risk management system recently has identified abnormal transactions from your records, clean days has been adjusted to T+.so please provide us with following materials to assist in verifying the real scenario of the transactions attached:

+

1.请解释相应的消费场景/业务模式,例如网站商城,扫码支付, 消费者到店支付等;
+   Please explain the relative payment scenario/business activities, for example, online store, QR code payment, payment at the store, etc;

+

2.提供相应购物清单,订单小票(请提供与被查交易订单号相匹配的交易时间及金额的发票);
  +   Provide related shopping lists, invoices. (Please provide the invoices, amount of which matches that of the abnormal transaction);

+

3.提供相应的发货证明,报关单(若有消费者在国内购买,请提供物流单据或报关单);
+   Relative proof of delivery, customs declaration (If the consumer purchased from China, please provide shipping receipt or customs declaration);

+

4.提供您的门店照片(门店照及店铺内的照片各一张, 一张可以看到商户名的门头照,一张可以看到相关商品或服务的店内照片);
+     Photos of the store ( one of each front-store and in-store);

+

5.其他可以还原交易背景的资料,如和消费者的聊天记录等,来佐证被查单号交易的真实性;
+   Other materials that can verify the payment scenario, for example, chatting history, to prove the truth of the transactions;

+

注:以上证件需原件扫描件/数码拍摄件,且照片内容需真实有效,不得做任何修改。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PartnerOrder IDPlatform Transaction IDOrder DescriptionCustomer IDIPTotal AmountInput AmountPay AmountExchange RateClearing AmountGatewayCreate TimeStatusPay Time
+

请查收关于被抽查的订单交易的相关信息,并在下午6:00 (悉尼时间)前将所需材料直接回复该邮件,未能按时提交完整证明材料,支付渠道将被关停,请您务必配合调查。感谢。
+ Please find sampled transactions in attachment, and reply required materials to this email before 6:00 pm (AEST). If you can not provide qualified materials on time, the payment channels would be suspended or restricted with amount limit. Please be sure to assist the investigation. Thanks.

+ + + +

Submit Risk Materials

+
+
+ 尊敬的RoyalPay商户 :
+ Dear RoyalPay merchant :
+

我司风控系统检测到您短期内后台交易存在异常行为(单人多次大金额交易退款频繁),触发平台风控预警,特此提醒:请勿使用平台进行违规交易,一经核查将关闭支付权限。请知悉。
+ RoyalPay's risk management system has identified abnormal transactions from your records in a short time(Single person pays large sums several timesfrequent refund transactions),which triggered the platform risk control warning. Here reminds: Do not use the platform for illegal transactions. Once verified, the payment authority will be closed.

+
+

顺颂商祺
+ Sincerely +

+

+ RoyalPay 风控团队
+ RoyalPay Risk Management Team +

+

+
+ Contact Us
+ Email:
+ info@royalpay.com.au
+ Tel:
+ 1300 10 77 50
+
+ Service WeChat Account:
+
+ Level 14, 383 Kent Street, Sydney NSW 2000
+
+ Level 11, 15 William Street, Melbourne VIC 3000 +

+

Tunnel Show Pty Ltd trading as RoyalPay
+ Representative of AFSL licensee 448066 +

+ diff --git a/src/main/resources/templates/mail/risk_urge_mail.html b/src/main/resources/templates/mail/risk_urge_mail.html new file mode 100644 index 000000000..00d0b1fab --- /dev/null +++ b/src/main/resources/templates/mail/risk_urge_mail.html @@ -0,0 +1,25 @@ + +Dear RoyalPay Merchant/BD : +

您好,您的风控材料链接即将过期,请及时提交风控材料。未能按时提交完整证明材料,支付渠道将被关停,请您务必配合调查。感谢。

+

Your link to the risk materials is about to expire, please submit the risk materials in time.If you can not provide qualified materials on time, the payment channels would be suspended or restricted with amount limit. Please be sure to assist the investigation. Thanks.

+

Best Regards

+

+
+ Contact Us
+ Email:
+ info@royalpay.com.au
+ Tel:
+ 1300 10 77 50
+
+ Service WeChat Account:
+
+ Level 14, 383 Kent Street, Sydney NSW 2000
+
+ Level 11, 15 William Street, Melbourne VIC 3000 +

+

Tunnel Show Pty Ltd trading as RoyalPay
+ Representative of AFSL licensee 448066 +

+ diff --git a/src/main/ui/manage.html b/src/main/ui/manage.html index 58b2a0e7b..5e92e2271 100644 --- a/src/main/ui/manage.html +++ b/src/main/ui/manage.html @@ -321,6 +321,12 @@ margin-bottom: 10%;"/> 商户交易额统计 + @@ -393,6 +399,11 @@ margin-bottom: 10%;"/> 风控记录|Risk Records +
  • + + 风控业务|Risk Business + +
  • 黑名单|Risky Merchants @@ -416,6 +427,23 @@ margin-bottom: 10%;"/>
  • + + + -
  • +
  • 清算日管理 diff --git a/src/main/ui/managev2.html b/src/main/ui/managev2.html index e1f30a4f5..13e635968 100644 --- a/src/main/ui/managev2.html +++ b/src/main/ui/managev2.html @@ -98,6 +98,20 @@ border: 1px solid #FFF; padding: 3px 15px; } + .dashboard li { + float: left; + border: 1px solid #FFF; + padding: 3px 15px; + } + .dashboard a{ + color: #FFF; + } + .dashboard .active{ + background-color: #FFF !important; + } + .dashboard .active a{ + color: #f06101 !important; + } @media (min-width: 768px) { .navbar-header { list-style: none; @@ -137,10 +151,10 @@ margin-bottom: 10%;"/> ng-class="currentUser.org?(currentUser.org.banner_class||'fxplus'):'royalpay'">
    -