风控材料上传新界面

master
james.zhao 6 years ago
parent 91e9574eb9
commit 44fdc278ba

@ -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<JSONObject> findAllFiles(@Param("material_id") String material_id);
}

@ -1,12 +1,12 @@
package au.com.royalpay.payment.manage.mappers.riskbusiness;
import cn.yixblog.support.mybatis.autosql.annotations.AdvanceSelect;
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 org.apache.catalina.LifecycleState;
import java.util.List;
@ -15,8 +15,6 @@ public interface RiskMaterialMapper {
@AutoSql(type = SqlType.INSERT)
void save(JSONObject material);
JSONObject findOperatorById(@Param("risk_id") String risk_id);
List<JSONObject> getRiskMaterial(JSONObject param);
List<JSONObject> findAllMaterials(@Param("risk_id") String risk_id);
}

@ -4,6 +4,7 @@ import au.com.royalpay.payment.core.exceptions.EmailException;
import au.com.royalpay.payment.core.exceptions.InvalidShortIdException;
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.ClientMapper;
import au.com.royalpay.payment.manage.mappers.system.ClientBDMapper;
@ -34,16 +35,11 @@ import org.thymeleaf.context.Context;
import org.thymeleaf.spring4.SpringTemplateEngine;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.io.*;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
@ -78,6 +74,8 @@ public class RiskBusinessServiceImpl implements RiskBusinessService {
@Autowired
private RiskMaterialMapper riskMaterialMapper;
@Resource
private RiskFileMapper riskFileMapper;
@Override
public List<JSONObject> getRiskEvents(JSONObject params) {
@ -171,19 +169,19 @@ public class RiskBusinessServiceImpl implements RiskBusinessService {
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment;filename=" + downloadFilename);
ZipOutputStream zos = new ZipOutputStream(response.getOutputStream());
String filePath = null;
for (int i = 1; i <= 10; i++) {
filePath = riskMaterial.getString("file" + i + "_url");
if (filePath != null) {
// 文件名前添加'file' + i是为了防止文件名一样
zos.putNextEntry(new ZipEntry("file" + i + filePath.substring(filePath.lastIndexOf("/"))));
InputStream inputStream = new URL(filePath).openConnection().getInputStream();
byte[] buffer = new byte[1024];
int result = 0;
while ((result = inputStream.read(buffer)) != -1) {
zos.write(buffer, 0, result);
for(int i=1;i<=6;i++){
if(riskMaterial.containsKey("file"+i)){
List<String> fileList= (List<String>)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();
}
inputStream.close();
}
}
zos.flush();
@ -201,12 +199,14 @@ public class RiskBusinessServiceImpl implements RiskBusinessService {
final List<String> emailsCcs = ctx.getVariable("emailsCcs")==null?new ArrayList<>():(List<String>)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, event.getIntValue("order_type")==3?(List<JSONObject>)ctx.getVariable("files"):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());
@ -225,6 +225,7 @@ public class RiskBusinessServiceImpl implements RiskBusinessService {
ctx.setVariable("refuse",true);
final List<String> emailsTos = (List<String>)ctx.getVariable("emailsTos");
final List<String> emailsCcs = ctx.getVariable("emailsCcs")==null?new ArrayList<>():(List<String>)ctx.getVariable("emailsCcs");
final String uploadUrl = (String)ctx.getVariable("uploadUrl");
final String content = thymeleaf.process("mail/risk_upload_mail.html", ctx);
royalThreadPoolExecutor.execute(() -> {
try {
@ -232,6 +233,7 @@ public class RiskBusinessServiceImpl implements RiskBusinessService {
emailsCcs.isEmpty() ? "" : StringUtils.join(emailsCcs, ","), content, event.getIntValue("order_type")==3?(List<JSONObject>)ctx.getVariable("files"):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);
@ -339,9 +341,26 @@ public class RiskBusinessServiceImpl implements RiskBusinessService {
@Override
public JSONObject getRiskMaterial(JSONObject param) {
List<JSONObject> riskMaterialList = riskMaterialMapper.getRiskMaterial(param);
if (riskMaterialList != null && riskMaterialList.size() > 0)
return riskMaterialList.get(0);
List<JSONObject> riskMaterialList = riskMaterialMapper.findAllMaterials(param.getString("risk_id"));
if (riskMaterialList != null && riskMaterialList.size() > 0){
List<JSONObject> 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<String> fileList = new ArrayList<>();
fileList.add(file.getString("file_url"));
fileNew.put("file"+fileType,fileList);
}else{
List<String> fileList = (List<String>)fileNew.get("file"+fileType);
fileList.add(file.getString("file_url"));
fileNew.put("file"+fileType,fileList);
}
}
return fileNew;
}
return null;
}

@ -2,6 +2,7 @@ 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;
@ -22,50 +23,39 @@ 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 RiskEventMapper riskEventMapper;
private RiskFileMapper riskFileMapper;
@Resource
private ClientMapper clientMapper;
private RiskEventMapper riskEventMapper;
@Resource
private StringRedisTemplate stringRedisTemplate;
@Resource
private MailService mailService;
@Resource
private RoyalThreadPoolExecutor royalThreadPoolExecutor;
@Resource
private SpringTemplateEngine thymeleaf;
private final String UPLOAD_MAIL_PREFIX = "UPLOAD_MAIL";
@Override
public void submitMaterial(JSONObject material) {
riskMaterialMapper.save(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<String> urls = (List<String>)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);
JSONObject operator = riskMaterialMapper.findOperatorById(material.getString("risk_id"));
if(operator.containsKey("email")){
JSONObject client = clientMapper.findClientByMoniker(event.getString("client_moniker"));
Context ctx = new Context();
ctx.setVariable("client_moniker", event.getString("client_moniker"));
ctx.setVariable("short_name", client.getString("short_name"));
ctx.setVariable("create_time", DateFormatUtils.format(event.getDate("create_time"),"yyyy-MM-dd HH:mm:ss"));
ctx.setVariable("operator", operator.getString("display_name"));
final String content = thymeleaf.process("mail/risk_operator_notice", ctx);
royalThreadPoolExecutor.execute(() -> {
try {
String emailId = mailService.sendRiskEmail(event.getString("client_moniker")+" has submitted the material",operator.getString("email") ,
"", content, null,event.getIntValue("order_type"));
} catch (Exception e) {
throw new EmailException("Email Sending Failed", e);
}
});
}
}
@Override

@ -84,7 +84,6 @@ public class RiskBusinessController {
public JSONObject getRiskMaterial(@PathVariable("risk_id") String riskId) {
JSONObject param = new JSONObject();
param.put("risk_id", riskId);
param.put("orderby_type", "update_time");
return riskBusinessService.getRiskMaterial(param);
}

@ -1,5 +1,6 @@
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.*;
@ -12,6 +13,8 @@ import javax.annotation.Resource;
public class RiskFileUploadController {
@Resource
private RiskUploadService riskUploadService;
@Resource
private RiskBusinessService riskBusinessService;
/**
*
@ -23,9 +26,12 @@ public class RiskFileUploadController {
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;
}

@ -12,35 +12,9 @@
LIMIT 1
</select>
<resultMap id="materialResultMap" type="com.alibaba.fastjson.JSONObject">
<id column="material_id" property="material_id"/>
<result column="risk_id" property="risk_id"/>
<result column="description" property="description"/>
<result column="file1_url" property="file1_url"/>
<result column="file2_url" property="file2_url"/>
<result column="file3_url" property="file3_url"/>
<result column="file4_url" property="file4_url"/>
<result column="file5_url" property="file5_url"/>
<result column="file6_url" property="file6_url"/>
<result column="file7_url" property="file7_url"/>
<result column="file8_url" property="file8_url"/>
<result column="file9_url" property="file9_url"/>
<result column="file10_url" property="file10_url"/>
<result column="update_time" property="update_time"/>
</resultMap>
<select id="getRiskMaterial" resultMap="materialResultMap">
<select id="findAllMaterials" resultType="com.alibaba.fastjson.JSONObject">
SELECT *
from risk_material
<where>
<if test="material_id != null">
AND material_id = #{material_id}
</if>
<if test="risk_id != null">
AND risk_id = #{risk_id}
</if>
</where>
<if test="orderby_type != null">
ORDER BY ${orderby_type} DESC
</if>
FROM risk_material
ORDER BY update_time DESC
</select>
</mapper>
</mapper>

@ -32,6 +32,7 @@
<script type="text/javascript" src="/static/lib/bootstrap/js/bootstrap.min.js"></script>
<script type="text/javascript" src="/static/riskupload/risk_upload.js"></script>
<script type="text/javascript" src="/static/lib/ngfileupload/ng-file-upload.min.js"></script>
<script type="text/javascript" src="/static/lib/angular-plugins/ui-bootstrap-tpls-2.5.0.min.js"></script>
<style type="text/css">
.register-box-bg {
background-color: rgba(255, 255, 255, 0.9);
@ -187,155 +188,179 @@
<div class="register-box content-with" style="margin-top:4%">
<div class="register-box-body register-box-bg">
<p class="login-box-msg">Easy BusinessEasy Payment</p>
<p class="small text-info">Image size should not exceed 3MB</p>
<p class="small text-info" id="short_name"></p>
<form novalidate name="uploadForm">
<div class="panel-body">
<div class="form-horizontal">
<div class="form-group">
<label class="control-label col-sm-3">* Material No.1</label>
<div class="col-sm-3">
<div class="form-control-static">
<button class="btn btn-primary" type="button"
ngf-select="uploadFile1($file)">
<i class="fa fa-upload"></i> Upload
</button>
</div>
<uib-progressbar value="file1Progress.value"
ng-if="file1Progress"></uib-progressbar>
<img ng-src="{{material.file1_url}}" class="col-sm-10 logo-width"></a>
<div class="col-sm-12 text-left">
<p ng-if="order_type==1">1、物流公司发货单据照片
要求:每笔交易对应的物流单必须提供,且单据必须清晰可见<br>
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.
</p>
<p ng-if="order_type==3">1.请解释相应的消费场景/业务模式,例如网站商城,扫码支付, 消费者到店支付等;<br>
Please explain the relative payment scenario/business activities, for example, online store, QR code payment, payment at the store, etc;
</p>
</div>
<label class="control-label col-sm-3">* Material No.2</label>
<div class="col-sm-3">
<div class="form-control-static">
<div class="col-sm-12">
<div class="col-xs-12">
<button class="btn btn-primary" type="button"
ngf-select="uploadFile2($file)">
ngf-select="uploadFile1($files)" ngf-multiple="true">
<i class="fa fa-upload"></i> Upload
</button>
</div>
<uib-progressbar value="file2Progress.value"
ng-if="file2Progress"></uib-progressbar>
<img ng-src="{{material.file2_url}}" class="col-sm-10 logo-width"></a>
&nbsp;&nbsp;<br>
<div class="col-xs-12">
<uib-progressbar value="file1Progress.value" type="success" animate="true" ng-if="file1Progress.value" max="100"
>{{file1Progress.value}}%</uib-progressbar>
<img class="col-xs-3 logo-width" ng-repeat="url in material.file1_url" ng-src="{{url}}">
</div>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-3">* Material No.3</label>
<div class="col-sm-3">
<div class="form-control-static">
<button class="btn btn-primary" type="button"
ngf-select="uploadFile3($file)">
<i class="fa fa-upload"></i> Upload
</button>
</div>
<uib-progressbar value="file3Progress.value"
ng-if="file3Progress"></uib-progressbar>
<img ng-src="{{material.file3_url}}" class="col-sm-10 logo-width"></a>
<div class="col-sm-12 text-left">
<p ng-if="order_type==1">2、用户购买虚拟物品需要提供聊天记录、订单信息、发货凭证截图、虚拟物品最终消费场景例如何种游戏、软件、提供消费场景网址/下载链接
要求:每笔交易对应的截图必须清晰可见<br>
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.
</p>
<p ng-if="order_type==3">2.提供相应购物清单,订单小票(请提供与被查交易订单号相匹配的交易时间及金额的发票);<br>
Provide related shopping lists, invoices. (Please provide the invoices, amount of which matches that of the abnormal transaction);
</p>
</div>
<label class="control-label col-sm-3">* Material No.4</label>
<div class="col-sm-3">
<div class="form-control-static">
<div class="col-sm-12">
<div class="col-xs-12">
<button class="btn btn-primary" type="button"
ngf-select="uploadFile4($file)">
ngf-select="uploadFile2($files)" ngf-multiple="true">
<i class="fa fa-upload"></i> Upload
</button>
</div>
<uib-progressbar value="file4Progress.value"
ng-if="file4Progress"></uib-progressbar>
<img ng-src="{{material.file4_url}}" class="col-sm-10 logo-width"></a>
&nbsp;&nbsp;<br>
<div class="col-xs-12">
<uib-progressbar value="file2Progress.value" type="success" animate="true" ng-if="file2Progress.value" max="100"
>{{file2Progress.value}}%</uib-progressbar>
<img class="col-xs-3 logo-width" ng-repeat="url in material.file2_url" ng-src="{{url}}">
</div>
</div>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-3">* Material No.5</label>
<div class="col-sm-3">
<div class="form-control-static">
<button class="btn btn-primary" type="button"
ngf-select="uploadFile5($file)">
<i class="fa fa-upload"></i> Upload
</button>
</div>
<uib-progressbar value="file5Progress.value"
ng-if="file5Progress"></uib-progressbar>
<img ng-src="{{material.file5_url}}" class="col-sm-10 logo-width"></a>
<div class="col-sm-12 text-left">
<p ng-if="order_type==1">3、购物小票/发票存根照片
照片应清晰,必须显示商户名称、商户地址、购物时间、物品名称
购物金额等<br>
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.
</p>
<p ng-if="order_type==3">3.提供相应的发货证明,报关单(若有消费者在国内购买,请提供物流单据或报关单);<br>
Relative proof of delivery, customs declaration (If the consumer purchased from China, please provide shipping receipt or customs declaration);
</p>
</div>
<label class="control-label col-sm-3">* Material No.6</label>
<div class="col-sm-3">
<div class="form-control-static">
<div class="col-sm-12">
<div class="col-xs-12">
<button class="btn btn-primary" type="button"
ngf-select="uploadFile6($file)">
ngf-select="uploadFile3($files)" ngf-multiple="true">
<i class="fa fa-upload"></i> Upload
</button>
</div>
<uib-progressbar value="file6Progress.value"
ng-if="file6Progress"></uib-progressbar>
<img ng-src="{{material.file6_url}}" class="col-sm-10 logo-width"></a>
&nbsp;&nbsp;<br>
<div class="col-xs-12">
<uib-progressbar value="file3Progress.value" type="success" animate="true" ng-if="file3Progress.value" max="100"
>{{file3Progress.value}}%</uib-progressbar>
<img class="col-xs-3 logo-width" ng-repeat="url in material.file3_url" ng-src="{{url}}">
</div>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-3">* Material No.7</label>
<div class="col-sm-3">
<div class="form-control-static">
<button class="btn btn-primary" type="button"
ngf-select="uploadFile7($file)">
<i class="fa fa-upload"></i> Upload
</button>
</div>
<uib-progressbar value="file7Progress.value"
ng-if="file7Progress"></uib-progressbar>
<img ng-src="{{material.file7_url}}" class="col-sm-10 logo-width"></a>
<div class="col-sm-12 text-left">
<p ng-if="order_type==1">4、显示商户门牌号码和店头名称的照片
要求:清晰可见,至少一张<br>
Photos of Merchant Street number & Merchant name
Requirement: At least one visible photo
</p>
<p ng-if="order_type==3">4.提供您的门店照片(门店照及店铺内的照片各一张, 一张可以看到商户名的门头照,一张可以看到相关商品或服务的店内照片);<br>
Photos of the store ( one of each front-store and in-store);
</p>
</div>
<label class="control-label col-sm-3">* Material No.8</label>
<div class="col-sm-3">
<div class="form-control-static">
<div class="col-sm-12">
<div class="col-xs-12">
<button class="btn btn-primary" type="button"
ngf-select="uploadFile8($file)">
ngf-select="uploadFile4($files)" ngf-multiple="true">
<i class="fa fa-upload"></i> Upload
</button>
</div>
<uib-progressbar value="file8Progress.value"
ng-if="file8Progress"></uib-progressbar>
<img ng-src="{{material.file8_url}}" class="col-sm-10 logo-width"></a>
&nbsp;&nbsp;<br>
<div class="col-xs-12">
<uib-progressbar value="file4Progress.value" type="success" animate="true" ng-if="file4Progress.value" max="100"
>{{file4Progress.value}}%</uib-progressbar>
<img class="col-xs-3 logo-width" ng-repeat="url in material.file4_url" ng-src="{{url}}">
</div>
</div>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-3">* Material No.9</label>
<div class="col-sm-3">
<div class="form-control-static">
<div class="col-sm-12 text-left">
<p ng-if="order_type==1">5、显示商户营业场景所场内部情况如店内商品陈列、收银台等的照片
要求:照片清晰,且能清楚显示商户实际售卖物品或服务,至少三张<br>
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
</p>
<p ng-if="order_type==3">5.其他可以还原交易背景的资料,如和消费者的聊天记录等,来佐证被查单号交易的真实性;<br>
Other materials that can verify the payment scenario, for example, chatting history, to prove the truth of the transactions;
</p>
</div>
<div class="col-sm-12">
<div class="col-xs-12">
<button class="btn btn-primary" type="button"
ngf-select="uploadFile9($file)">
ngf-select="uploadFile5($files)" ngf-multiple="true">
<i class="fa fa-upload"></i> Upload
</button>
</div>
<uib-progressbar value="file9Progress.value"
ng-if="file9Progress"></uib-progressbar>
<img ng-src="{{material.file9_url}}" class="col-sm-10 logo-width"></a>
&nbsp;&nbsp;<br>
<div class="col-xs-12">
<uib-progressbar value="file5Progress.value" type="success" animate="true" ng-if="file5Progress.value" max="100"
>{{file5Progress.value}}%</uib-progressbar>
<img class="col-xs-3 logo-width" ng-repeat="url in material.file5_url" ng-src="{{url}}">
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-12 text-left">
<p>6、其他图片<br>
Other pictures
</p>
</div>
<label class="control-label col-sm-3">* Material No.10</label>
<div class="col-sm-3">
<div class="form-control-static">
<div class="col-sm-12">
<div class="col-xs-12">
<button class="btn btn-primary" type="button"
ngf-select="uploadFile10($file)">
ngf-select="uploadFile6($files)" ngf-multiple="true">
<i class="fa fa-upload"></i> Upload
</button>
</div>
<uib-progressbar value="file10Progress.value"
ng-if="file10Progress"></uib-progressbar>
<img ng-src="{{material.file10_url}}" class="col-sm-10 logo-width"></a>
&nbsp;&nbsp;<br>
<div class="col-xs-12">
<uib-progressbar value="file6Progress.value" type="success" animate="true" ng-if="file6Progress.value" max="100"
>{{file6Progress.value}}%</uib-progressbar>
<img class="col-xs-3 logo-width" ng-repeat="url in material.file6_url" ng-src="{{url}}">
</div>
</div>
</div>
<div class="form-group" ng-class="{'has-error':uploadForm.description.$invalid && uploadForm.description.$dirty}">
<label class="control-label col-sm-3">* Description</label>
<div class="col-sm-9">
<div class="form-group">
<label class="control-label col-sm-2">Description</label>
<div class="col-sm-10">
<textarea class="form-control" required
ng-model="material.description" placeholder="Less than 500 characters"
ng-model="material.description" placeholder="No more than 500"
name="description"
maxlength="500"></textarea>
<input id="codeKey" type="text" class="hidden" name="codeKey"
ng-model="codeKey">
<input id="risk_id" type="text" class="hidden" name="risk_id"
ng_model="material.risk_id">
<input id="order_type" type="text" class="hidden" name="order_type"
ng_model="order_type">
</div>
</div>
@ -355,8 +380,12 @@
$(document).ready(function () {
window.codeKey = /*[[${codeKey}]]*/'';
window.risk_id = /*[[${risk_id}]]*/'';
window.order_type = /*[[${order_type}]]*/'';
window.short_name = /*[[${short_name}]]*/'';
$('#codeKey').val(window.codeKey).trigger('input');
$('#risk_id').val(window.risk_id).trigger('input');
$('#order_type').val(window.order_type).trigger('input');
$('#short_name').text(window.short_name);
})
</script>
</div>

@ -29,8 +29,9 @@
</tr>
</tbody>
</table>
<p>请点击此链接上传所需材料<a th:href="${uploadUrl}"><span th:text="${uploadUrl}"></span></a></p>
<p>如果提交的材料不齐, 则有关停支付的风险。还请按时提供商户材料并直接回复该邮件, 感谢,辛苦。</p>
<!--<p>请点击此链接上传所需材料<a th:href="${uploadUrl}"><span th:text="${uploadUrl}"></span></a></p>-->
<p><a th:href="${uploadUrl}" style="color: rgb(255, 255, 255); text-align: center; padding: 12px 10px; height: 100%; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; text-decoration: none; background-color: #00c0ef; min-width: 150px;"><strong>Submit Risk Materials</strong></a></p>
</div>
<div th:if="${order_type==3}">
<b>尊敬的RoyalPay商户 :<br>
@ -53,9 +54,10 @@
<p>注:以上证件需原件扫描件/数码拍摄件,且照片内容需真实有效,不得做任何修改。 </p>
<p>请查收附件中关于被抽查的订单交易的相关信息,并在<span style="background: #FCE824"><span th:text="${reply_date}"></span>下午600 (悉尼时间)前</span>将所需材料直接回复该邮件,未能按时提交完整证明材料,支付渠道将被关停,请您务必配合调查。感谢。<br>
Please find sampled transactions in attachment, and reply required materials to this email <span style="background: #FCE824">before 6:00 pm <span th:text="${reply_date_english}"></span> (AEST).</span> 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.</p>
<p>请点击此链接上传所需材料。<a th:href="${uploadUrl}"><span th:text="${uploadUrl}"></span></a><br>
Please click on this link to upload the required materials.<a th:href="${uploadUrl}"><span th:text="${uploadUrl}"></span></a>
</p>
<!--<p>请点击此链接上传所需材料。<a th:href="${uploadUrl}"><span th:text="${uploadUrl}"></span></a><br>-->
<!--Please click on this link to upload the required materials.<a th:href="${uploadUrl}"><span th:text="${uploadUrl}"></span></a>-->
<!--</p>-->
<p><a th:href="${uploadUrl}" style="color: rgb(255, 255, 255); text-align: center; padding: 12px 10px; height: 100%; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; text-decoration: none; background-color: #00c0ef; min-width: 150px;"><strong>Submit Risk Materials</strong></a></p>
</div>
<div th:if="${order_type==4}">
<b>尊敬的RoyalPay商户 :<br>

@ -261,17 +261,23 @@ define(['angular', 'jquery', 'uiRouter', './monitoring/analysis-monitoring'],
};
// 加载提交材料
$scope.fileObject = {};
// $scope.fileObject = {};
$scope.loadRiskMaterial = function() {
$http.get('/risk/business/' + $scope.riskEvent.risk_id + '/material').then(function(resp) {
var riskMaterial = resp.data;
for (var i = 1; i <= 10; i++) {
var key = "file" + i;
if (riskMaterial[key + '_url'] != null)
$scope.fileObject[key] = riskMaterial[key + '_url'];
}
$scope.fileLength = Object.keys($scope.fileObject).length;
$scope.description = riskMaterial.description;
$scope.riskMaterial = resp.data;
$scope.file1 = resp.data.file1;
$scope.file2 = resp.data.file2;
$scope.file3 = resp.data.file3;
$scope.file4 = resp.data.file4;
$scope.file5 = resp.data.file5;
$scope.file6 = resp.data.file6;
// for (var i = 1; i <= 10; i++) {
// var key = "file" + i;
// if (riskMaterial[key + '_url'] != null)
// $scope.fileObject[key] = riskMaterial[key + '_url'];
// }
// $scope.fileLength = Object.keys($scope.fileObject).length;
})
};
$scope.loadRiskMaterial();

@ -1,3 +1,12 @@
<style>
@media (max-width: 544px) {
.logo-width {
width: 100%;
}
}
</style>
<div class="panel panel-default" ng-if="fileLength != 0">
<div class="panel-heading">Audit Files &nbsp;&nbsp;&nbsp;
<a class="btn-group btn btn-success"
@ -20,21 +29,141 @@
<label class="control-label col-sm-2">Description:</label>
<div class="col-sm-8">
<div class="form-control-static">
<p ng-bind="description"></p>
<p ng-bind="riskMaterial.description"></p>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-12 text-left">
<p ng-if="riskEvent.order_type==1">1、物流公司发货单据照片
要求:每笔交易对应的物流单必须提供,且单据必须清晰可见<br>
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.
</p>
<p ng-if="riskEvent.order_type==3">1.请解释相应的消费场景/业务模式,例如网站商城,扫码支付, 消费者到店支付等;<br>
Please explain the relative payment scenario/business activities, for example, online store, QR code payment, payment at the store, etc;
</p>
</div>
<div class="col-sm-12">
&nbsp;&nbsp;<br>
<div class="col-xs-12">
<a class="col-xs-3 logo-width" ng-repeat="url in file1" target="_blank" ng-href="{{url}}">
<img class="col-xs-12" ng-src="{{url}}">
</a>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-12 text-left">
<p ng-if="riskEvent.order_type==1">2、用户购买虚拟物品需要提供聊天记录、订单信息、发货凭证截图、虚拟物品最终消费场景例如何种游戏、软件、提供消费场景网址/下载链接
要求:每笔交易对应的截图必须清晰可见<br>
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.
</p>
<p ng-if="riskEvent.order_type==3">2.提供相应购物清单,订单小票(请提供与被查交易订单号相匹配的交易时间及金额的发票);<br>
Provide related shopping lists, invoices. (Please provide the invoices, amount of which matches that of the abnormal transaction);
</p>
</div>
<div class="col-sm-12">
&nbsp;&nbsp;<br>
<div class="col-xs-12">
<a class="col-xs-3 logo-width" ng-repeat="url in file2" target="_blank" ng-href="{{url}}">
<img class="col-xs-12" ng-src="{{url}}">
</a>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-12 text-left">
<p ng-if="riskEvent.order_type==1">3、购物小票/发票存根照片
照片应清晰,必须显示商户名称、商户地址、购物时间、物品名称
购物金额等<br>
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.
</p>
<p ng-if="riskEvent.order_type==3">3.提供相应的发货证明,报关单(若有消费者在国内购买,请提供物流单据或报关单);<br>
Relative proof of delivery, customs declaration (If the consumer purchased from China, please provide shipping receipt or customs declaration);
</p>
</div>
<div class="col-sm-12">
&nbsp;&nbsp;<br>
<div class="col-xs-12">
<a class="col-xs-3 logo-width" ng-repeat="url in file3" target="_blank" ng-href="{{url}}">
<img class="col-xs-12" ng-src="{{url}}">
</a>
</div>
</div>
</div>
<div class="form-group" ng-repeat="(key, value) in fileObject">
<div class="form-group">
<div class="col-sm-12 text-left">
<p ng-if="riskEvent.order_type==1">4、显示商户门牌号码和店头名称的照片
要求:清晰可见,至少一张<br>
Photos of Merchant Street number & Merchant name
Requirement: At least one visible photo
</p>
<p ng-if="riskEvent.order_type==3">4.提供您的门店照片(门店照及店铺内的照片各一张, 一张可以看到商户名的门头照,一张可以看到相关商品或服务的店内照片);<br>
Photos of the store ( one of each front-store and in-store);
</p>
</div>
<div class="col-sm-12">
<label class="control-label col-sm-2">{{key}}</label>
<div class="col-sm-4">
<div class="form-control-static">
<a ng-if="value" target="_blank" ng-href="{{value}}">
<img ng-src="{{value}}" class="col-sm-8"></a>
</div>
&nbsp;&nbsp;<br>
<div class="col-xs-12">
<a class="col-xs-3 logo-width" ng-repeat="url in file4" target="_blank" ng-href="{{url}}">
<img class="col-xs-12" ng-src="{{url}}">
</a>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-12 text-left">
<p ng-if="riskEvent.order_type==1">5、显示商户营业场景所场内部情况如店内商品陈列、收银台等的照片
要求:照片清晰,且能清楚显示商户实际售卖物品或服务,至少三张<br>
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
</p>
<p ng-if="riskEvent.order_type==3">5.其他可以还原交易背景的资料,如和消费者的聊天记录等,来佐证被查单号交易的真实性;<br>
Other materials that can verify the payment scenario, for example, chatting history, to prove the truth of the transactions;
</p>
</div>
<div class="col-sm-12">
&nbsp;&nbsp;<br>
<div class="col-xs-12">
<a class="col-xs-3 logo-width" ng-repeat="url in file5" target="_blank" ng-href="{{url}}">
<img class="col-xs-12" ng-src="{{url}}">
</a>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-12 text-left">
<p>6、其他图片<br>
Other pictures
</p>
</div>
<div class="col-sm-12">
&nbsp;&nbsp;<br>
<div class="col-xs-12">
<a class="col-xs-3 logo-width" ng-repeat="url in file6" target="_blank" ng-href="{{url}}">
<img class="col-xs-12" ng-src="{{url}}">
</a>
</div>
</div>
</div>
<!--<div class="form-group" ng-repeat="(key, value) in fileObject">-->
<!--<div class="col-sm-12">-->
<!--<label class="control-label col-sm-2">{{key}}</label>-->
<!--<div class="col-sm-4">-->
<!--<div class="form-control-static">-->
<!--<a ng-if="value" target="_blank" ng-href="{{value}}">-->
<!--<img ng-src="{{value}}" class="col-sm-8"></a>-->
<!--</div>-->
<!--</div>-->
<!--</div>-->
<!--</div>-->
</div>
</div>

@ -1,182 +1,150 @@
// define(['angular', 'static/commons/commons', 'uiBootstrap', 'uiRouter', 'ngBootSwitch', 'ngFileUpload'], function (angular) {
// 'use strict';
var app = angular.module('riskUploadApp',['ngFileUpload']);
var app = angular.module('riskUploadApp',['ngFileUpload','ui.bootstrap']);
app.controller('riskUploadCtrl', ['$scope','$http','Upload','$filter',function ($scope,$http,Upload,$filter) {
$scope.material={};
$scope.codeKey=document.getElementById('codeKey').value;
$scope.material.risk_id=document.getElementById('risk_id').value;
$scope.order_type=document.getElementById('order_type').value;
$scope.material.update_time=$filter('date')(new Date(), 'yyyy-MM-dd HH:mm:ss');
$scope.uploadFile1 = function (file) {
if (file != null) {
$scope.uploadFile1 = function (files) {
if (files && files.length) {
var urls = new Array();
var value = 0;
$scope.file1Progress = {value: 0};
Upload.upload({
url: '/attachment/riskFiles',
data: {file: file}
}).then(function (resp) {
delete $scope.file1Progress;
$scope.material.file1_url = resp.data.url;
}, function (resp) {
delete $scope.file1Progress;
commonDialog.alert({title: 'Upload Failed', content: resp.data.message, type: 'error'})
}, function (evt) {
$scope.file1Progress.value = parseInt(100 * evt.loaded / evt.total);
})
for (var i = 0; i < files.length; i++) {
var file = files[i];
Upload.upload({
url: '/attachment/riskFiles',
data: {file: file}
}).then(function (resp) {
urls.push(resp.data.url);
}, function (resp) {
delete $scope.file1Progress;
alert('Upload Failed');
}, function (evt) {
value += parseInt(100 * evt.loaded / evt.total );
$scope.file1Progress.value = value/(files.length*2);
})
}
$scope.material.file1_url = urls;
}
};
$scope.uploadFile2 = function (file) {
if (file != null) {
$scope.uploadFile2 = function (files) {
if (files && files.length) {
var urls = new Array();
var value = 0;
$scope.file2Progress = {value: 0};
Upload.upload({
url: '/attachment/riskFiles',
data: {file: file}
}).then(function (resp) {
delete $scope.file2Progress;
$scope.material.file2_url = resp.data.url;
}, function (resp) {
delete $scope.file2Progress;
commonDialog.alert({title: 'Upload Failed', content: resp.data.message, type: 'error'})
}, function (evt) {
$scope.file2Progress.value = parseInt(100 * evt.loaded / evt.total);
})
for (var i = 0; i < files.length; i++) {
var file = files[i];
Upload.upload({
url: '/attachment/riskFiles',
data: {file: file}
}).then(function (resp) {
urls.push(resp.data.url);
}, function (resp) {
delete $scope.file2Progress;
alert('Upload Failed');
}, function (evt) {
value += parseInt(100 * evt.loaded / evt.total );
$scope.file2Progress.value = value/(files.length*2);
})
}
$scope.material.file2_url = urls;
}
};
$scope.uploadFile3 = function (file) {
if (file != null) {
$scope.uploadFile3 = function (files) {
if (files && files.length) {
var urls = new Array();
var value = 0;
$scope.file3Progress = {value: 0};
Upload.upload({
url: '/attachment/riskFiles',
data: {file: file}
}).then(function (resp) {
delete $scope.file3Progress;
$scope.material.file3_url = resp.data.url;
}, function (resp) {
delete $scope.file3Progress;
commonDialog.alert({title: 'Upload Failed', content: resp.data.message, type: 'error'})
}, function (evt) {
$scope.file3Progress.value = parseInt(100 * evt.loaded / evt.total);
})
for (var i = 0; i < files.length; i++) {
var file = files[i];
Upload.upload({
url: '/attachment/riskFiles',
data: {file: file}
}).then(function (resp) {
urls.push(resp.data.url);
}, function (resp) {
delete $scope.file3Progress;
alert('Upload Failed');
}, function (evt) {
value += parseInt(100 * evt.loaded / evt.total );
$scope.file3Progress.value = value/(files.length*2);
})
}
$scope.material.file3_url = urls;
}
};
$scope.uploadFile4 = function (file) {
if (file != null) {
$scope.uploadFile4 = function (files) {
if (files && files.length) {
var urls = new Array();
var value = 0;
$scope.file4Progress = {value: 0};
Upload.upload({
url: '/attachment/riskFiles',
data: {file: file}
}).then(function (resp) {
delete $scope.file4Progress;
$scope.material.file4_url = resp.data.url;
}, function (resp) {
delete $scope.file4Progress;
commonDialog.alert({title: 'Upload Failed', content: resp.data.message, type: 'error'})
}, function (evt) {
$scope.file4Progress.value = parseInt(100 * evt.loaded / evt.total);
})
for (var i = 0; i < files.length; i++) {
var file = files[i];
Upload.upload({
url: '/attachment/riskFiles',
data: {file: file}
}).then(function (resp) {
urls.push(resp.data.url);
}, function (resp) {
delete $scope.file4Progress;
alert('Upload Failed');
}, function (evt) {
value += parseInt(100 * evt.loaded / evt.total );
$scope.file4Progress.value = value/(files.length*2);
})
}
$scope.material.file4_url = urls;
}
};
$scope.uploadFile5 = function (file) {
if (file != null) {
$scope.uploadFile5 = function (files) {
if (files && files.length) {
var urls = new Array();
var value = 0;
$scope.file5Progress = {value: 0};
Upload.upload({
url: '/attachment/riskFiles',
data: {file: file}
}).then(function (resp) {
delete $scope.file5Progress;
$scope.material.file5_url = resp.data.url;
}, function (resp) {
delete $scope.file5Progress;
commonDialog.alert({title: 'Upload Failed', content: resp.data.message, type: 'error'})
}, function (evt) {
$scope.file5Progress.value = parseInt(100 * evt.loaded / evt.total);
})
for (var i = 0; i < files.length; i++) {
var file = files[i];
Upload.upload({
url: '/attachment/riskFiles',
data: {file: file}
}).then(function (resp) {
urls.push(resp.data.url);
}, function (resp) {
delete $scope.file5Progress;
alert('Upload Failed');
}, function (evt) {
value += parseInt(100 * evt.loaded / evt.total );
$scope.file5Progress.value = value/(files.length*2);
})
}
$scope.material.file5_url = urls;
}
};
$scope.uploadFile6 = function (file) {
if (file != null) {
$scope.uploadFile6 = function (files) {
if (files && files.length) {
var urls = new Array();
var value = 0;
$scope.file6Progress = {value: 0};
Upload.upload({
url: '/attachment/riskFiles',
data: {file: file}
}).then(function (resp) {
delete $scope.file6Progress;
$scope.material.file6_url = resp.data.url;
}, function (resp) {
delete $scope.file6Progress;
commonDialog.alert({title: 'Upload Failed', content: resp.data.message, type: 'error'})
}, function (evt) {
$scope.file6Progress.value = parseInt(100 * evt.loaded / evt.total);
})
}
};
$scope.uploadFile7 = function (file) {
if (file != null) {
$scope.file7Progress = {value: 0};
Upload.upload({
url: '/attachment/riskFiles',
data: {file: file}
}).then(function (resp) {
delete $scope.file7Progress;
$scope.material.file7_url = resp.data.url;
}, function (resp) {
delete $scope.file7Progress;
commonDialog.alert({title: 'Upload Failed', content: resp.data.message, type: 'error'})
}, function (evt) {
$scope.file7Progress.value = parseInt(100 * evt.loaded / evt.total);
})
}
};
$scope.uploadFile8 = function (file) {
if (file != null) {
$scope.file8Progress = {value: 0};
Upload.upload({
url: '/attachment/riskFiles',
data: {file: file}
}).then(function (resp) {
delete $scope.file8Progress;
$scope.material.file8_url = resp.data.url;
}, function (resp) {
delete $scope.file8Progress;
commonDialog.alert({title: 'Upload Failed', content: resp.data.message, type: 'error'})
}, function (evt) {
$scope.file8Progress.value = parseInt(100 * evt.loaded / evt.total);
})
}
};
$scope.uploadFile9 = function (file) {
if (file != null) {
$scope.file9Progress = {value: 0};
Upload.upload({
url: '/attachment/riskFiles',
data: {file: file}
}).then(function (resp) {
delete $scope.file9Progress;
$scope.material.file9_url = resp.data.url;
}, function (resp) {
delete $scope.file9Progress;
commonDialog.alert({title: 'Upload Failed', content: resp.data.message, type: 'error'})
}, function (evt) {
$scope.file9Progress.value = parseInt(100 * evt.loaded / evt.total);
})
}
};
$scope.uploadFile10 = function (file) {
if (file != null) {
$scope.file10Progress = {value: 0};
Upload.upload({
url: '/attachment/riskFiles',
data: {file: file}
}).then(function (resp) {
delete $scope.file10Progress;
$scope.material.file10_url = resp.data.url;
}, function (resp) {
delete $scope.file10Progress;
commonDialog.alert({title: 'Upload Failed', content: resp.data.message, type: 'error'})
}, function (evt) {
$scope.file10Progress.value = parseInt(100 * evt.loaded / evt.total);
})
for (var i = 0; i < files.length; i++) {
var file = files[i];
Upload.upload({
url: '/attachment/riskFiles',
data: {file: file}
}).then(function (resp) {
urls.push(resp.data.url);
}, function (resp) {
delete $scope.file6Progress;
alert('Upload Failed');
}, function (evt) {
value += parseInt(100 * evt.loaded / evt.total );
$scope.file6Progress.value = value/(files.length*2);
})
}
$scope.material.file6_url = urls;
}
};
$scope.submit = function (form) {
@ -190,7 +158,8 @@
});
}
}])
}]);

Loading…
Cancel
Save