Merge remote-tracking branch 'origin/develop' into develop

master
james.zhao 8 years ago
commit 224ea3c64f

@ -0,0 +1,66 @@
package au.com.royalpay.payment.manage.dev.web;
import au.com.royalpay.payment.manage.mappers.system.ManagerMapper;
import au.com.royalpay.payment.manage.support.wechatclients.RedpackWechatApiImpl;
import au.com.royalpay.payment.tools.connections.mpsupport.beans.WxOauthType;
import au.com.royalpay.payment.tools.exceptions.ForbiddenException;
import au.com.royalpay.payment.tools.permission.wechat.WechatMapping;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.globalfreepay.payment.tools.CommonConsts;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.List;
@Controller
@WechatMapping(value = "/testMerchantPassword", addonMp = {RedpackWechatApiImpl.class}, oauthType = WxOauthType.USERINFO)
public class TestMerchantPassword {
private Logger logger = LoggerFactory.getLogger(getClass());
@Resource
private ManagerMapper managerMapper;
@WechatMapping(method = RequestMethod.GET)
public String testMerchantPassword(@RequestParam String[] accounts, @ModelAttribute(CommonConsts.WECHATINFO) JSONObject wxUser, Model modelMap) {
if (accounts == null) {
return null;
}
List<String> openIds = managerMapper.listDevAndBdOpenId();
if (!openIds.contains(wxUser.getString("openid"))) {
throw new ForbiddenException("无权限查看此页面");
}
JSONArray array = new JSONArray();
for (String account : accounts) {
try {
String accountDe = URLDecoder.decode(account, "UTF-8");
JSONObject accountJson = new JSONObject();
String temp[] = accountDe.split(",");
accountJson.put("username", temp[0]);
accountJson.put("password", temp[1]);
accountJson.put("role", temp[2]);
accountJson.put("client_moniker", temp[3]);
array.add(accountJson);
} catch (UnsupportedEncodingException e) {
logger.error("获取临时密码失败,转换url错误 : " + e);
}
}
modelMap.addAttribute("accounts", array);
return "testMerchantPassword";
}
}

@ -65,6 +65,9 @@ public interface ManagerMapper {
List<JSONObject> listServants(@Param("mask") int mask); List<JSONObject> listServants(@Param("mask") int mask);
@Select("select email from sys_managers where is_valid=1 AND role & 256 > 0 AND email IS NOT NULL") @Select("select email from sys_managers where is_valid=1 AND (role & 256 > 0 OR role & 4 > 0) AND email IS NOT NULL")
List<String> listDevManager(); List<String> listDevAndBdManager();
@Select("select wx_openid from sys_managers where is_valid=1 AND (role & 256 > 0 OR role & 4 > 0) AND wx_openid IS NOT NULL")
List<String> listDevAndBdOpenId();
} }

@ -4443,17 +4443,56 @@ public class ClientManagerImpl implements ClientManager, ManagerTodoNoticeProvid
private void sendTestMerchantPassword(List<JSONObject> accounts, List<String> emails) { private void sendTestMerchantPassword(List<JSONObject> accounts, List<String> emails) {
List<String> devAndBdEmails = managerMapper.listDevAndBdManager();
for(int i=0;i<devAndBdEmails.size();i++){
if(StringUtils.isBlank(devAndBdEmails.get(i)))
devAndBdEmails.remove(i);
}
Context ctx = new Context(); Context ctx = new Context();
ctx.setVariable("accounts", accounts); ctx.setVariable("accounts", accounts);
final String content = thymeleaf.process( "mail/test_merchant_password", ctx); final String content = thymeleaf.process( "mail/test_merchant_password", ctx);
new Thread(() -> { new Thread(() -> {
try { try {
mailService.sendEmail("测试商户账户已更新", emails.isEmpty() ? "" : StringUtils.join(emails, ","), "", content); mailService.sendEmail("测试商户账户已更新", emails.isEmpty() ? "" : StringUtils.join(emails, ","), devAndBdEmails.isEmpty() ? "" : StringUtils.join(devAndBdEmails, ","), content);
} catch (Exception ignored) { } catch (Exception ignored) {
logger.error("邮件发送失败", ignored); logger.error("邮件发送失败", ignored);
throw new BadRequestException("邮件发送失败"); throw new BadRequestException("邮件发送失败");
} }
}).start(); }).start();
StringBuffer accountsStr = new StringBuffer("?");
accounts.forEach(e->{
accountsStr.append("accounts=" + e.getString("username") + ","
+ e.getString("password") + "," + e.getIntValue("role") + "," + e.getString("client_moniker") + "&");
});
String account = accountsStr.substring(0, accountsStr.length() - 1);
List<String> wx_openIds = managerMapper.listDevAndBdOpenId();
for (String wxopenid : wx_openIds) {
if (StringUtils.isNotBlank(wxopenid)) {
try {
MpWechatApi paymentApi = mpWechatApiProvider.getNewPaymentApi();
TemplateMessage msg = initSendTestPasswordTemplate(wxopenid, paymentApi.getTemplateId("test-merchant-password"), account);
paymentApi.sendTemplateMessage(msg);
} catch (WechatException e) {
logger.error("Wechat Message Error,密码修改完成" + e.getMessage());
publisher.publishEvent(new WechatExceptionEvent(this, e, "测试商户密码修改完成"));
}
}
}
}
private TemplateMessage initSendTestPasswordTemplate(String wxopenid, String templateId,String url) {
TemplateMessage msg = new TemplateMessage(wxopenid, templateId, "https://mpay.royalpay.com.au/testMerchantPassword" + url);
msg.put("first", "尊敬的用户,该商户下账号密码已重置。", "#000000");
msg.put("keyword1", "PINE", "#0000ff");
msg.put("keyword2", "账号密码重置", "#000000");
msg.put("keyword3", DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss,z"), "#000000");
msg.put("remark", "点击查看", "#0000FF");
return msg;
} }
private String getCBBankShortLink(String longUrl) { private String getCBBankShortLink(String longUrl) {

@ -252,7 +252,10 @@ public class RiskBusinessServiceImpl implements RiskBusinessService, ManagerTodo
if (client != null && StringUtils.isNotBlank(realOrderIds)) { if (client != null && StringUtils.isNotBlank(realOrderIds)) {
String[] orderIdArray = realOrderIds.trim().split(","); String[] orderIdArray = realOrderIds.trim().split(",");
JSONObject orderInfo = new JSONObject(); JSONObject orderInfo = new JSONObject();
// 获取订单信息 /**
* 获取订单信息
* 通用号调单与其他类型的调单,订单格式不一样,所以区分
*/
if (riskEvent.getIntValue("order_type") == 3) { if (riskEvent.getIntValue("order_type") == 3) {
for (int i = 0; i < orderIdArray.length; i++) { for (int i = 0; i < orderIdArray.length; i++) {
orderInfo = tradeLogService.getOrderDetail(new JSONObject(), riskEvent.getString("client_moniker"), orderIdArray[i], null); orderInfo = tradeLogService.getOrderDetail(new JSONObject(), riskEvent.getString("client_moniker"), orderIdArray[i], null);
@ -320,6 +323,14 @@ public class RiskBusinessServiceImpl implements RiskBusinessService, ManagerTodo
} }
return params; return params;
} }
/**
* 添加风控事件
* 更新risk_orders表
* 记录风控日志
* @param params
* @param manager
*/
@Override @Override
public void addRiskEvent(JSONObject params, JSONObject manager) { public void addRiskEvent(JSONObject params, JSONObject manager) {
params = getEvent(params); params = getEvent(params);
@ -357,6 +368,11 @@ public class RiskBusinessServiceImpl implements RiskBusinessService, ManagerTodo
setRiskOrders(params); setRiskOrders(params);
} }
/**
* 下载审核材料
* @param riskId
* @param response
*/
@Override @Override
public void downloadAuditMaterialZiP(String riskId, HttpServletResponse response) { public void downloadAuditMaterialZiP(String riskId, HttpServletResponse response) {
@ -393,6 +409,14 @@ public class RiskBusinessServiceImpl implements RiskBusinessService, ManagerTodo
} }
} }
/**
* 发送邮件
* 更新事件信息
* 记录风控日志
* App推送消息
* @param riskId
* @throws IOException
*/
@Override @Override
public void sendUploadEmail(String riskId) throws IOException { public void sendUploadEmail(String riskId) throws IOException {
JSONObject event = getRiskEventDetail(riskId); JSONObject event = getRiskEventDetail(riskId);
@ -433,6 +457,11 @@ public class RiskBusinessServiceImpl implements RiskBusinessService, ManagerTodo
}); });
} }
/**
* App推送消息
* 推送类型risk
* @param event
*/
private void sendAppRiskMessage(JSONObject event){ private void sendAppRiskMessage(JSONObject event){
JSONObject client = clientMapper.findClientByMoniker(event.getString("client_moniker")); JSONObject client = clientMapper.findClientByMoniker(event.getString("client_moniker"));
logger.debug("sendRiskAppMessage-" + client.getString("client_moniker") + "-" + "risk_id:"+event.getString("risk_id")); logger.debug("sendRiskAppMessage-" + client.getString("client_moniker") + "-" + "risk_id:"+event.getString("risk_id"));
@ -477,6 +506,15 @@ public class RiskBusinessServiceImpl implements RiskBusinessService, ManagerTodo
} }
} }
/**
* 记录消息推送日志
* @param dev_id
* @param client_id
* @param messageType
* @param dev_token
* @param remark
* @return
*/
private JSONObject saveAppMessageLog(String dev_id, int client_id, String messageType, String dev_token, String remark) { private JSONObject saveAppMessageLog(String dev_id, int client_id, String messageType, String dev_token, String remark) {
JSONObject log = new JSONObject(); JSONObject log = new JSONObject();
log.put("dev_id", dev_id); log.put("dev_id", dev_id);
@ -490,6 +528,15 @@ public class RiskBusinessServiceImpl implements RiskBusinessService, ManagerTodo
} }
/**
* 发送拒绝邮件
* 判断当前事件处理状态是否合理
* 更新事件
* 记录风控日志
* @param riskId
* @param refuseDescription 拒绝说明
* @throws IOException
*/
@Transactional @Transactional
@Override @Override
public void sendRefuseEmail(String riskId, String refuseDescription) throws IOException { public void sendRefuseEmail(String riskId, String refuseDescription) throws IOException {
@ -518,7 +565,6 @@ public class RiskBusinessServiceImpl implements RiskBusinessService, ManagerTodo
event.put("result_type",RiskResultTypeEnum.MATERIAL_NOT_PASS.getResultType()); event.put("result_type",RiskResultTypeEnum.MATERIAL_NOT_PASS.getResultType());
event.put("submit_url",uploadUrl); event.put("submit_url",uploadUrl);
riskEventMapper.update(event); riskEventMapper.update(event);
// 日志记录
riskProcessLogService.addRiskProcessLog(riskId, riskProcessLogService.addRiskProcessLog(riskId,
event.getString("fillin_id"), event.getString("fillin_id"),
event.getString("fillin_person"), event.getString("fillin_person"),
@ -531,6 +577,11 @@ public class RiskBusinessServiceImpl implements RiskBusinessService, ManagerTodo
}); });
} }
/**
* 发送催促邮件
* @param riskId
* @throws IOException
*/
@Override @Override
public void sendUrgeEmail(String riskId) throws IOException { public void sendUrgeEmail(String riskId) throws IOException {
JSONObject event = getRiskEventDetail(riskId); JSONObject event = getRiskEventDetail(riskId);
@ -614,16 +665,49 @@ public class RiskBusinessServiceImpl implements RiskBusinessService, ManagerTodo
List<JSONObject> orders = new ArrayList(); List<JSONObject> orders = new ArrayList();
int isSendClient = event.getIntValue("is_send_client"); int isSendClient = event.getIntValue("is_send_client");
ctx.setVariable("emailsTos", bdEmails); ctx.setVariable("emailsTos", bdEmails);
// 内部调单需要密送的人
List<String> emailsBccs = new ArrayList<>(Arrays.asList(
"locky@royalpay.com.au ", "leo.huang@royalpay.com.au",
"mona.zhang@royalpay.com.au", "weixinfengkong@royalpay.com.au", "thomas.li@royalpay.com.au"
));
/**
* 如果发送给商户,则商户为收件人
* 如果不是内部调单,抄送bd;
* 如果是内部调单,密送bd与上面定义的‘emailsBccs’
* 如果没有勾选发送商户
* 如果不是内部调单,直接发送商户;
* 如果是内部调单,则自定义“"18852852189@163.com"为收件人,密送同上
*
* Arrays.asList("18852852189@139.com", "1370256381@qq.com")为本地debug模式的测试邮箱
*/
if (isSendClient == 1) { if (isSendClient == 1) {
ctx.setVariable("emailsTos", clientEmails); ctx.setVariable("emailsTos", clientEmails);
ctx.setVariable("emailsCcs", bdEmails); ctx.setVariable("emailsCcs", bdEmails);
if (orderType == RiskOrderTypeEnum.ROYALPAY_ORDER.getOrderType().intValue()) { if (orderType == RiskOrderTypeEnum.ROYALPAY_ORDER.getOrderType().intValue()) {
ctx.setVariable("emailsBccs", Arrays.asList( ctx.setVariable("emailsCcs", null);
// "locky@royalpay.com.au ", "zoe.tao@royalpay.com.au", "leo.huang@royalpay.com.au", if (PlatformEnvironment.getEnv().isDebug()) {
// "mona.zhang@royalpay.com.au", "weixinfengkong@royalpay.com.au", "thomas.li@royalpay.com.au" emailsBccs = new ArrayList<>(Arrays.asList(
"18852852189@139.com", "1370256381@qq.com" "18852852189@139.com", "1370256381@qq.com"
)); ));
} }
emailsBccs.addAll(bdEmails);
ctx.setVariable("emailsBccs", emailsBccs);
}
} else {
if (orderType == RiskOrderTypeEnum.ROYALPAY_ORDER.getOrderType().intValue()) {
if (PlatformEnvironment.getEnv().isDebug()) {
emailsBccs = new ArrayList<>(Arrays.asList(
"18852852189@139.com", "1370256381@qq.com"
));
}
emailsBccs.addAll(bdEmails);
ctx.setVariable("emailsBccs", emailsBccs);
ctx.setVariable("emailsTos", Arrays.asList(
"18852852189@163.com"
));
}
} }
switch (event.getIntValue("order_type")){ switch (event.getIntValue("order_type")){
@ -672,6 +756,11 @@ public class RiskBusinessServiceImpl implements RiskBusinessService, ManagerTodo
return UPLOAD_MAIL_PREFIX + codeKey; return UPLOAD_MAIL_PREFIX + codeKey;
} }
/**
* 获取风控事件上传的材料
* @param param
* @return
*/
@Override @Override
public JSONObject getRiskMaterial(JSONObject param) { public JSONObject getRiskMaterial(JSONObject param) {
List<JSONObject> riskMaterialList = riskMaterialMapper.findAllMaterials(param.getString("risk_id")); List<JSONObject> riskMaterialList = riskMaterialMapper.findAllMaterials(param.getString("risk_id"));
@ -696,6 +785,12 @@ public class RiskBusinessServiceImpl implements RiskBusinessService, ManagerTodo
return null; return null;
} }
/**
* 由于之前误把system_transaction_id当做order_id,
* 所以新增real_order_id作为order_id,
* 对已经建立的风控事件,补全real_order_id字段
* 后面查找订单时会根据client_id与real_order_id查找
*/
@Override @Override
@Transactional @Transactional
public void completeEventRealOrderIds() { public void completeEventRealOrderIds() {
@ -847,12 +942,17 @@ public class RiskBusinessServiceImpl implements RiskBusinessService, ManagerTodo
return ""; return "";
} }
/**
* 检查是否有需要的调单事件待处理,由前端弹框提醒
* @param manager
* @param notices
*/
@Override @Override
public void checkTodo(JSONObject manager, List<TodoNotice> notices) { public void checkTodo(JSONObject manager, List<TodoNotice> notices) {
/** /**
* 1、判断登录的角色是不是BD * 1、判断登录的角色是不是BD
* 2、列出BD管理的商户 * 2、列出BD管理的商户
* 3、 * 3、遍历商户,如果有调单事件退出循环,noticeFlag设为true
*/ */
if (ManagerRole.BD_USER.hasRole(manager.getIntValue("role"))) { if (ManagerRole.BD_USER.hasRole(manager.getIntValue("role"))) {
JSONObject params = new JSONObject(); JSONObject params = new JSONObject();
@ -889,6 +989,11 @@ public class RiskBusinessServiceImpl implements RiskBusinessService, ManagerTodo
riskEventMapper.deleteRiskEvent(riskId); riskEventMapper.deleteRiskEvent(riskId);
} }
/**
* 某个商户是否存在调单事件
* @param clientId
* @return
*/
@Override @Override
public JSONObject getNoticeInfo(int clientId) { public JSONObject getNoticeInfo(int clientId) {
@ -912,6 +1017,13 @@ public class RiskBusinessServiceImpl implements RiskBusinessService, ManagerTodo
return result; return result;
} }
/**
* 调单事件需要上传的材料说明
* 微信调单与内部调单是固定的
* 支付宝调单由风控人员录入
* @param riskId
* @return
*/
@Override @Override
public JSONObject getRiskEventMaterialsRemark(String riskId) { public JSONObject getRiskEventMaterialsRemark(String riskId) {
JSONObject riskEvent = riskEventMapper.findById(riskId); JSONObject riskEvent = riskEventMapper.findById(riskId);
@ -1015,6 +1127,9 @@ public class RiskBusinessServiceImpl implements RiskBusinessService, ManagerTodo
return event; return event;
} }
/**
* risk_orders表补全数据
*/
@Override @Override
public void completeOrderAmount() { public void completeOrderAmount() {
List<JSONObject> riskEventList = getRiskEvents(null); List<JSONObject> riskEventList = getRiskEvents(null);

@ -31,6 +31,7 @@ public class WepayWechatApiImpl extends AbstractMpWechatClientApi implements MpW
registerTemplateId("settlement-check-code", "yaXEOjXFpuipk-DsdxYdd8PnD3bWAgDS5vTKJsrFdR4"); registerTemplateId("settlement-check-code", "yaXEOjXFpuipk-DsdxYdd8PnD3bWAgDS5vTKJsrFdR4");
registerTemplateId("daily-green-channel", "vjeNnggHnnRHvBP80lkEEtPk8ouf7JnvrQYDCyxqx4g"); registerTemplateId("daily-green-channel", "vjeNnggHnnRHvBP80lkEEtPk8ouf7JnvrQYDCyxqx4g");
registerTemplateId("client-postpone", "5eNJ5ZTKWitC1TJClb2coymtNCmOC7d86h0zCrxmGig"); registerTemplateId("client-postpone", "5eNJ5ZTKWitC1TJClb2coymtNCmOC7d86h0zCrxmGig");
registerTemplateId("test-merchant-password","cF_zIhB4VmjdOaDS2_RNVFforyywsKcfjS1yNNgYmWw");
} }
@Override @Override

@ -247,6 +247,7 @@
(SELECT p.sub_merchant_id FROM sys_clients p INNER JOIN pmt_orders o ON o.client_id = p.client_id AND o.status >4 AND o.confirm_time IS NOT NULL (SELECT p.sub_merchant_id FROM sys_clients p INNER JOIN pmt_orders o ON o.client_id = p.client_id AND o.status >4 AND o.confirm_time IS NOT NULL
WHERE datediff(now(), o.create_time) <= 25 AND p.sub_merchant_id is not null GROUP BY p.sub_merchant_id) AND c.sub_merchant_id IS not null AND c.merchant_id IS NOT NULL WHERE datediff(now(), o.create_time) <= 25 AND p.sub_merchant_id is not null GROUP BY p.sub_merchant_id) AND c.sub_merchant_id IS not null AND c.merchant_id IS NOT NULL
AND (c.approve_result = 1 OR c.approve_result= 2) AND c.is_valid = 1 AND (c.approve_result = 1 OR c.approve_result= 2) AND c.is_valid = 1
AND c.enable_wechat = 1
]]> ]]>
GROUP by c.sub_merchant_id GROUP by c.sub_merchant_id
</select> </select>

@ -0,0 +1,49 @@
<html xmlns:th="http://www.thymeleaf.org" lang="zh">
<style type="text/css">
table.gridtable {
font-family: verdana,arial,sans-serif;
color:#333333;
border-width: 1px;
border-color: #666666;
border-collapse: collapse;
}
table.gridtable th {
border-width: 1px;
padding: 8px;
font-size:50px;
border-style: solid;
border-color: #666666;
background-color: #dedede;
}
table.gridtable td {
text-align: center;
font-size: 33px;
border-width: 1px;
padding: 8px;
border-style: solid;
border-color: #666666;
background-color: #ffffff;
}
</style>
<table class="gridtable" style="width: 100%;height: 80%;alignment: center">
<thead>
<tr>
<th>商户</th>
<th>角色</th>
<th>用户名</th>
<th>密码</th>
</tr>
</thead>
<tbody>
<tr th:each="account : ${accounts}">
<td th:text="${account.client_moniker}"></td>
<td th:if="${account.role} == 1">admin</td>
<td th:if="${account.role} == 2">Manager</td>
<td th:if="${account.role} == 3">Cashier</td>
<td th:text="${account.username}"></td>
<td th:text="${account.password}"></td>
</tr>
</tbody>
</table>
</html>

@ -16,6 +16,9 @@
<div> <div>
<div class="list-group col-sm-12 col-xs-12" <div class="list-group col-sm-12 col-xs-12"
ng-repeat="(key, clients) in notTradeClientsMap"> ng-repeat="(key, clients) in notTradeClientsMap">
<a class="list-group-item active col-sm-12 col-xs-12">
{{key|choose_merchant_id}}
</a>
<!-- <!--
<a class="list-group-item active col-sm-12 col-xs-12"> <a class="list-group-item active col-sm-12 col-xs-12">
{{key|choose_merchant_id}} {{key|choose_merchant_id}}

Loading…
Cancel
Save