APP手机重置密码

master
james.zhao 6 years ago
parent e59883442c
commit c9d3368242

@ -76,4 +76,12 @@ public interface ManageAppService {
void updateProduct(JSONObject device, ProductBean productBean);
void deleteProduct(JSONObject device, String commodity_id);
void bindAccountEmail(JSONObject device,JSONObject email);
void updateAccountEmail(JSONObject device,JSONObject codekey);
void bindAccountPhone(JSONObject device,JSONObject phone);
void updateAccountPhone(JSONObject device,JSONObject codekey);
}

@ -169,4 +169,22 @@ public interface RetailAppService {
void cancelCouponAccuessLog(String accuess_id, String remark);
void submitMaterial(JSONObject material, JSONObject device);
void bindAccountEmail(JSONObject device,JSONObject email);
void updateAccountEmail(JSONObject device,JSONObject codekey);
void bindAccountPhone(JSONObject device,JSONObject phone);
void updateAccountPhone(JSONObject device,JSONObject codekey);
/**
* 退
*/
void verifyRefundPassword(JSONObject device, JSONObject json);
/**
* 退
*/
void resetRefundPassword(JSONObject device, JSONObject json);
}

@ -1,5 +1,6 @@
package au.com.royalpay.payment.manage.appclient.core.impls;
import au.com.royalpay.payment.core.exceptions.EmailException;
import au.com.royalpay.payment.manage.appclient.beans.AppMerchantBean;
import au.com.royalpay.payment.manage.appclient.core.ManageAppService;
import au.com.royalpay.payment.manage.bdprize.core.BDPrizeService;
@ -16,26 +17,37 @@ import au.com.royalpay.payment.manage.merchants.beans.ClientAuthFilesInfo;
import au.com.royalpay.payment.manage.merchants.beans.ClientRegisterInfo;
import au.com.royalpay.payment.manage.merchants.beans.PartnerQuery;
import au.com.royalpay.payment.manage.merchants.core.ClientManager;
import au.com.royalpay.payment.manage.notice.core.MailService;
import au.com.royalpay.payment.manage.product.beans.ProductBean;
import au.com.royalpay.payment.manage.product.core.ClientProduct;
import au.com.royalpay.payment.manage.signin.beans.ChangePwdBean;
import au.com.royalpay.payment.manage.signin.core.ManagerAccountsService;
import au.com.royalpay.payment.manage.signin.core.SignInAccountService;
import au.com.royalpay.payment.manage.support.sms.SmsSender;
import au.com.royalpay.payment.tools.device.DeviceSupport;
import au.com.royalpay.payment.tools.device.ManageDeviceSupport;
import au.com.royalpay.payment.tools.device.support.DeviceRegister;
import au.com.royalpay.payment.tools.env.PlatformEnvironment;
import au.com.royalpay.payment.tools.exceptions.BadRequestException;
import au.com.royalpay.payment.tools.exceptions.ForbiddenException;
import au.com.royalpay.payment.tools.exceptions.ServerErrorException;
import au.com.royalpay.payment.tools.threadpool.RoyalThreadPoolExecutor;
import com.alibaba.fastjson.JSONObject;
import com.github.miemiedev.mybatis.paginator.domain.PageBounds;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.ibatis.annotations.Param;
import org.springframework.cache.annotation.Cacheable;
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.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@Service
@ -67,6 +79,19 @@ public class ManageAppServiceImp implements ManageAppService {
private FinancialBDConfigMapper financialBDConfigMapper;
@Resource
private ClientProduct clientProduct;
@Resource
private StringRedisTemplate stringRedisTemplate;
@Resource
private MailService mailService;
@Resource
private RoyalThreadPoolExecutor royalThreadPoolExecutor;
@Resource
private SpringTemplateEngine thymeleaf;
@Resource
private SmsSender smsSender;
private final String BIND_MANAGE_EMAIL_PREFIX = "BIND_MANAGE_EMAIL";
private final String BIND_MANAGE_PHONE_PREFIX = "BIND_MANAGE_PHONE";
private final int BIND_PHONE_TEMPLID = 126978;
@Override
@ -429,4 +454,106 @@ public class ManageAppServiceImp implements ManageAppService {
JSONObject manager = managerMapper.findById(device.getString("manager_id"));
clientProduct.deleteProduct(manager, commodity_id);
}
@Override
public void bindAccountEmail(JSONObject device, JSONObject email) {
String codeKey = device.getString("manager_id");
String codeKeyValueRedis = stringRedisTemplate.boundValueOps(getUpdateManageEmailKey(codeKey)).get();
if(StringUtils.isNotEmpty(codeKeyValueRedis)){
throw new BadRequestException("Captcha has been sent.Please check your email or try again in 5 minutes.");
}
String codeKeyValue = RandomStringUtils.random(6, false, true);
Context ctx = new Context();
JSONObject manager = managerMapper.findById(device.getString("manager_id"));
ctx.setVariable("account",manager);
ctx.setVariable("captcha",codeKeyValue);
final String content = thymeleaf.process("mail/account_bind_email.html", ctx);
royalThreadPoolExecutor.execute(() -> {
try {
mailService.sendEmail("Your account is in the process of binding a mailbox", email.getString("contact_email"),
"", content);
} catch (Exception e) {
throw new EmailException("Email Sending Failed", e);
}
});
stringRedisTemplate.boundValueOps(getUpdateManageEmailKey(codeKey)).set(codeKeyValue+"&"+email.getString("contact_email"), 5, TimeUnit.MINUTES);
}
@Override
public void updateAccountEmail(JSONObject device, JSONObject params) {
String key = stringRedisTemplate.boundValueOps(getUpdateManageEmailKey(device.getString("manager_id"))).get();
if(key == null){
throw new BadRequestException("Captcha has expired");
}
String captcha = key.split("&")[0];
String email = key.split("&")[1];
if(!StringUtils.equals(captcha,params.getString("captcha"))){
throw new BadRequestException("Verification code is wrong");
}
JSONObject account = new JSONObject();
account.put("manager_id",device.getString("manager_id"));
account.put("email",email);
managerMapper.update(account);
deleteManageEmailKey(device.getString("manager_id"));
}
@Override
public void bindAccountPhone(JSONObject device, JSONObject phone) {
String codeKey = device.getString("manager_id");
String codeKeyValueRedis = stringRedisTemplate.boundValueOps(getUpdateManagePhoneKey(codeKey)).get();
if(StringUtils.isNotEmpty(codeKeyValueRedis)){
throw new BadRequestException("Captcha has been sent.Please check your phone or try again in 5 minutes.");
}
String codeKeyValue = RandomStringUtils.random(6, false, true);
String nationCode = phone.getString("nation_code");
String phoneNumber = phone.getString("contact_phone");
ArrayList<String> param = new ArrayList<>();
param.add("绑定手机号");
param.add(codeKeyValue);
String expireMin = "5";
param.add(expireMin);
try {
smsSender.getSender().sendWithParam(nationCode.trim(), phoneNumber, BIND_PHONE_TEMPLID, param, "RoyalPay", "", "");
} catch (Exception e) {
e.printStackTrace();
throw new ServerErrorException("Phone number is wrong.Please try again.");
}
stringRedisTemplate.boundValueOps(getUpdateManagePhoneKey(codeKey)).set(codeKeyValue+"&"+nationCode+"&"+phoneNumber, Long.parseLong(expireMin), TimeUnit.MINUTES);
}
@Override
public void updateAccountPhone(JSONObject device, JSONObject params) {
String key = stringRedisTemplate.boundValueOps(getUpdateManagePhoneKey(device.getString("manager_id"))).get();
if(key == null){
throw new BadRequestException("Captcha has expired");
}
String captcha = key.split("&")[0];
String nation_code = key.split("&")[1];
String contact_phone = key.split("&")[2];
if(!StringUtils.equals(captcha,params.getString("captcha"))){
throw new BadRequestException("Verification code is wrong");
}
JSONObject account = new JSONObject();
account.put("manager_id",device.getString("manager_id"));
account.put("contact_phone",contact_phone);
account.put("nation_code","+" + nation_code);
managerMapper.update(account);
deleteManagePhoneKey(device.getString("manager_id"));
}
private void deleteManageEmailKey(String codeKey){
stringRedisTemplate.delete(getUpdateManageEmailKey(codeKey));
}
private void deleteManagePhoneKey(String codeKey){
stringRedisTemplate.delete(getUpdateManagePhoneKey(codeKey));
}
private String getUpdateManageEmailKey(String codeKey){
return BIND_MANAGE_EMAIL_PREFIX+codeKey;
}
private String getUpdateManagePhoneKey(String codeKey){
return BIND_MANAGE_PHONE_PREFIX+codeKey;
}
}

@ -1,6 +1,7 @@
package au.com.royalpay.payment.manage.appclient.core.impls;
import au.com.royalpay.payment.core.PaymentApi;
import au.com.royalpay.payment.core.exceptions.EmailException;
import au.com.royalpay.payment.manage.activities.app_index.core.AppActService;
import au.com.royalpay.payment.manage.analysis.mappers.CustomerAndOrdersStatisticsMapper;
import au.com.royalpay.payment.manage.analysis.mappers.TransactionAnalysisMapper;
@ -15,12 +16,7 @@ import au.com.royalpay.payment.manage.mappers.log.*;
import au.com.royalpay.payment.manage.mappers.notice.NoticePartnerMapper;
import au.com.royalpay.payment.manage.mappers.payment.OrderMapper;
import au.com.royalpay.payment.manage.mappers.payment.TransactionMapper;
import au.com.royalpay.payment.manage.mappers.system.ClientAccountMapper;
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.ClientSettleDelayConfMapper;
import au.com.royalpay.payment.manage.mappers.system.CustomerMapper;
import au.com.royalpay.payment.manage.mappers.system.ManagerCustomerRelationAlipayMapper;
import au.com.royalpay.payment.manage.mappers.system.*;
import au.com.royalpay.payment.manage.merchants.beans.ClientAuthFilesInfo;
import au.com.royalpay.payment.manage.merchants.beans.ClientUpdateInfo;
import au.com.royalpay.payment.manage.merchants.core.ClientConfigService;
@ -28,6 +24,7 @@ import au.com.royalpay.payment.manage.merchants.core.ClientManager;
import au.com.royalpay.payment.manage.merchants.core.ClientModifySupport;
import au.com.royalpay.payment.manage.merchants.entity.impls.SwitchPermissionModify;
import au.com.royalpay.payment.manage.notice.beans.NoticeInfo;
import au.com.royalpay.payment.manage.notice.core.MailService;
import au.com.royalpay.payment.manage.notice.core.NoticeManage;
import au.com.royalpay.payment.manage.notice.core.NoticePartner;
import au.com.royalpay.payment.manage.openim.core.CustomerServiceService;
@ -40,6 +37,7 @@ import au.com.royalpay.payment.manage.riskbusiness.enums.RiskResultTypeEnum;
import au.com.royalpay.payment.manage.signin.beans.ChangePwdBean;
import au.com.royalpay.payment.manage.signin.core.SignInAccountService;
import au.com.royalpay.payment.manage.signin.core.impls.SignInAccountServiceImpl;
import au.com.royalpay.payment.manage.support.sms.SmsSender;
import au.com.royalpay.payment.manage.tradelog.beans.TradeLogQuery;
import au.com.royalpay.payment.manage.tradelog.core.TradeLogService;
import au.com.royalpay.payment.manage.tradelog.refund.RefundService;
@ -58,7 +56,9 @@ import au.com.royalpay.payment.tools.merchants.beans.QRCodeConfig;
import au.com.royalpay.payment.tools.merchants.beans.UpdateSurchargeDTO;
import au.com.royalpay.payment.tools.merchants.core.MerchantInfoProvider;
import au.com.royalpay.payment.tools.permission.enums.PartnerRole;
import au.com.royalpay.payment.tools.threadpool.RoyalThreadPoolExecutor;
import au.com.royalpay.payment.tools.utils.PageListUtils;
import au.com.royalpay.payment.tools.utils.PasswordUtils;
import au.com.royalpay.payment.tools.utils.QRCodeUtils;
import au.com.royalpay.payment.tools.utils.TimeZoneUtils;
@ -69,7 +69,9 @@ 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 com.github.qcloudsms.httpclient.HTTPException;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
@ -78,9 +80,14 @@ import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.slf4j.LoggerFactory;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.thymeleaf.context.Context;
import org.thymeleaf.spring4.SpringTemplateEngine;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DateFormat;
@ -186,6 +193,19 @@ public class RetailAppServiceImp implements RetailAppService {
private RiskBusinessService riskBusinessService;
@Resource
private RiskUploadService riskUploadService;
@Resource
private MailService mailService;
@Resource
private RoyalThreadPoolExecutor royalThreadPoolExecutor;
@Resource
private SpringTemplateEngine thymeleaf;
@Resource
private StringRedisTemplate stringRedisTemplate;
@Resource
private SmsSender smsSender;
private final String BIND_ACCOUNT_EMAIL_PREFIX = "BIND_ACCOUNT_EMAIL";
private final String BIND_ACCOUNT_PHONE_PREFIX = "BIND_ACCOUNT_PHONE";
private final int BIND_PHONE_TEMPLID = 126978;
private Map<String, AppMsgSender> senderMap = new HashMap<>();
private final String fileName[] = { "client_bank_file", "client_id_file", "client_company_file" };
@ -1900,4 +1920,144 @@ public class RetailAppServiceImp implements RetailAppService {
RiskResultTypeEnum.WAIT_FOR_AUDIT.getResultType());
}
@Override
public void bindAccountEmail(JSONObject device, JSONObject email) {
String codeKey = device.getString("account_id");
String codeKeyValueRedis = stringRedisTemplate.boundValueOps(getUpdateAccountEmailKey(codeKey)).get();
if(StringUtils.isNotEmpty(codeKeyValueRedis)){
throw new BadRequestException("Captcha has been sent.Please check your email or try again in 5 minutes.");
}
String codeKeyValue = RandomStringUtils.random(6, false, true);
Context ctx = new Context();
JSONObject account = clientAccountMapper.findById(device.getString("account_id"));
ctx.setVariable("account",account);
ctx.setVariable("captcha",codeKeyValue);
final String content = thymeleaf.process("mail/account_bind_email.html", ctx);
royalThreadPoolExecutor.execute(() -> {
try {
mailService.sendEmail("Your account is in the process of binding a mailbox", email.getString("contact_email"),
"", content);
} catch (Exception e) {
throw new EmailException("Email Sending Failed", e);
}
});
stringRedisTemplate.boundValueOps(getUpdateAccountEmailKey(codeKey)).set(codeKeyValue+"&"+email.getString("contact_email"), 5, TimeUnit.MINUTES);
}
@Override
public void updateAccountEmail(JSONObject device, JSONObject params) {
String key = stringRedisTemplate.boundValueOps(getUpdateAccountEmailKey(device.getString("account_id"))).get();
if(key == null){
throw new BadRequestException("Captcha has expired");
}
String captcha = key.split("&")[0];
String email = key.split("&")[1];
if(!StringUtils.equals(captcha,params.getString("captcha"))){
throw new BadRequestException("Verification code is wrong");
}
JSONObject account = new JSONObject();
account.put("account_id",device.getString("account_id"));
account.put("contact_email",email);
clientAccountMapper.update(account);
deleteAccountEmailKey(device.getString("account_id"));
}
@Override
public void bindAccountPhone(JSONObject device, JSONObject phone) {
String codeKey = device.getString("account_id");
String codeKeyValueRedis = stringRedisTemplate.boundValueOps(getUpdateAccountPhoneKey(codeKey)).get();
if(StringUtils.isNotEmpty(codeKeyValueRedis)){
throw new BadRequestException("Captcha has been sent.Please check your phone or try again in 5 minutes.");
}
String codeKeyValue = RandomStringUtils.random(6, false, true);
String nationCode = phone.getString("nation_code");
String phoneNumber = phone.getString("contact_phone");
ArrayList<String> param = new ArrayList<>();
param.add("绑定手机号");
param.add(codeKeyValue);
String expireMin = "5";
param.add(expireMin);
try {
smsSender.getSender().sendWithParam(nationCode.trim(), phoneNumber, BIND_PHONE_TEMPLID, param, "RoyalPay", "", "");
} catch (Exception e) {
e.printStackTrace();
throw new ServerErrorException("Phone number is wrong.Please try again.");
}
stringRedisTemplate.boundValueOps(getUpdateAccountPhoneKey(codeKey)).set(codeKeyValue+"&"+nationCode+"&"+phoneNumber, Long.parseLong(expireMin), TimeUnit.MINUTES);
}
@Override
public void updateAccountPhone(JSONObject device, JSONObject params) {
String key = stringRedisTemplate.boundValueOps(getUpdateAccountPhoneKey(device.getString("account_id"))).get();
if(key == null){
throw new BadRequestException("Captcha has expired");
}
String captcha = key.split("&")[0];
String nation_code = key.split("&")[1];
String contact_phone = key.split("&")[2];
if(!StringUtils.equals(captcha,params.getString("captcha"))){
throw new BadRequestException("Verification code is wrong");
}
JSONObject account = new JSONObject();
account.put("account_id",device.getString("account_id"));
account.put("contact_phone",contact_phone);
account.put("nation_code","+" + nation_code);
clientAccountMapper.update(account);
deleteAccountPhoneKey(device.getString("account_id"));
}
@Override
public void verifyRefundPassword(JSONObject device, JSONObject json) {
String clientType = device.getString("client_type");
deviceSupport.findRegister(clientType);
JSONObject clientConfig = clientConfigService.find(device.getIntValue("client_id"));
String needVerifyPassword = json.getString("refund_password");
String refundPwdSalt = clientConfig.getString("refund_pwd_salt");
if (!StringUtils.equals(clientConfig.getString("refund_pwd"), PasswordUtils.hashPwd(needVerifyPassword, refundPwdSalt))) {
throw new BadRequestException("Incorrect refund password");
}
}
@Override
@Transactional
public void resetRefundPassword(JSONObject device, JSONObject json) {
String clientType = device.getString("client_type");
deviceSupport.findRegister(clientType);
JSONObject account = clientAccountMapper.findById(device.getString("account_id"));
if (PartnerRole.getRole(account.getIntValue("role")) != PartnerRole.ADMIN) {
throw new BadRequestException("You have no permission");
}
verifyRefundPassword(device, json);
String newSalt = PasswordUtils.newSalt();
String newPassWord = json.getString("new_refund_password");
if (!StringUtils.isNumeric(newPassWord)) {
throw new BadRequestException("Refund password must be pure number");
}
String newPwdHash = PasswordUtils.hashPwd(newPassWord, newSalt);
if (StringUtils.equals(newPwdHash, PasswordUtils.hashPwd(json.getString("refund_password"), newSalt))) {
throw new BadRequestException("Old and new passwords cannot be duplicated");
}
JSONObject update = new JSONObject();
update.put("client_id", device.getIntValue("client_id"));
update.put("refund_pwd", newPwdHash);
update.put("refund_pwd_salt", newSalt);
clientConfigService.update(update);
}
private void deleteAccountEmailKey(String codeKey){
stringRedisTemplate.delete(getUpdateAccountEmailKey(codeKey));
}
private void deleteAccountPhoneKey(String codeKey){
stringRedisTemplate.delete(getUpdateAccountPhoneKey(codeKey));
}
private String getUpdateAccountEmailKey(String codeKey){
return BIND_ACCOUNT_EMAIL_PREFIX+codeKey;
}
private String getUpdateAccountPhoneKey(String codeKey){
return BIND_ACCOUNT_PHONE_PREFIX+codeKey;
}
}

@ -30,6 +30,8 @@ import java.util.Date;
import java.util.List;
import java.util.Map;
import static au.com.royalpay.payment.tools.CommonConsts.RETAIL_DEVICE;
@AppClientController
@RequestMapping("/api/v1.0/manage/app")
@ -200,4 +202,48 @@ public class ManageAppController {
manageAppService.deleteProduct(device, commodity_id);
}
/**
*
* @param device
* @param email contact_email
* @throws Exception
*/
@RequestMapping(value = "/account/email",method = RequestMethod.PUT)
public void bindAccountEmail(@ModelAttribute(CommonConsts.MANAGER_DEVICE) JSONObject device,@RequestBody JSONObject email){
manageAppService.bindAccountEmail(device,email);
}
/**
*
* @param device
* @param params
* @throws Exception
*/
@RequestMapping(value = "/account/email/bind",method = RequestMethod.PUT)
public void updateAccountEmail(@ModelAttribute(CommonConsts.MANAGER_DEVICE) JSONObject device,@RequestBody JSONObject params){
manageAppService.updateAccountEmail(device,params);
}
/**
*
* @param device
* @param phone contact_phone
* @throws Exception
*/
@RequestMapping(value = "/account/phone",method = RequestMethod.PUT)
public void bindAccountPhone(@ModelAttribute(CommonConsts.MANAGER_DEVICE) JSONObject device,@RequestBody JSONObject phone) {
manageAppService.bindAccountPhone(device,phone);
}
/**
*
* @param device
* @param params
* @throws Exception
*/
@RequestMapping(value = "/account/phone/bind",method = RequestMethod.PUT)
public void updateAccountPhone(@ModelAttribute(CommonConsts.MANAGER_DEVICE) JSONObject device,@RequestBody JSONObject params){
manageAppService.updateAccountPhone(device,params);
}
}

@ -33,7 +33,6 @@ import au.com.royalpay.payment.tools.merchants.beans.UpdateSurchargeDTO;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -644,4 +643,64 @@ public class RetailAppController {
return attachmentClient.uploadFile(file,false);
}
/**
*
* @param device
* @param email contact_email
* @throws Exception
*/
@RequestMapping(value = "/account/email",method = RequestMethod.PUT)
public void bindAccountEmail(@ModelAttribute(RETAIL_DEVICE) JSONObject device,@RequestBody JSONObject email) throws Exception {
retailAppService.bindAccountEmail(device,email);
}
/**
*
* @param device
* @param params
* @throws Exception
*/
@RequestMapping(value = "/account/email/bind",method = RequestMethod.PUT)
public void updateAccountEmail(@ModelAttribute(RETAIL_DEVICE) JSONObject device,@RequestBody JSONObject params) throws Exception {
retailAppService.updateAccountEmail(device,params);
}
/**
*
* @param device
* @param phone contact_phone
* @throws Exception
*/
@RequestMapping(value = "/account/phone",method = RequestMethod.PUT)
public void bindAccountPhone(@ModelAttribute(RETAIL_DEVICE) JSONObject device,@RequestBody JSONObject phone) throws Exception {
retailAppService.bindAccountPhone(device,phone);
}
/**
*
* @param device
* @param params
* @throws Exception
*/
@RequestMapping(value = "/account/phone/bind",method = RequestMethod.PUT)
public void updateAccountPhone(@ModelAttribute(RETAIL_DEVICE) JSONObject device,@RequestBody JSONObject params) throws Exception {
retailAppService.updateAccountPhone(device,params);
}
/**
* 退
*/
@RequestMapping(value = "/refund/passwd/verify", method = RequestMethod.PUT)
public void verifyRefundPassword(@ModelAttribute(CommonConsts.RETAIL_DEVICE) JSONObject device, @RequestBody JSONObject json) {
retailAppService.verifyRefundPassword(device, json);
}
/**
* 退
*/
@RequestMapping(value = "/refund/passwd/reset", method = RequestMethod.PUT)
public void resetRefundPassWord(@ModelAttribute(CommonConsts.RETAIL_DEVICE) JSONObject device, @RequestBody JSONObject json) {
retailAppService.resetRefundPassword(device, json);
}
}

@ -18,15 +18,23 @@ public class NewAccountBean {
private String displayName;
@JSONField(name = "contact_phone")
private String contactPhone;
@JSONField(name = "contact_email")
private String contactEmail;
@JSONField(name = "nation_code")
private String nation_code = "+61";
private int role = PartnerRole.CASHIER.getCode();
@JSONField(name = "client_id")
private int clientId;
public JSONObject toJson() {
JSONObject account = new JSONObject();
account.put("display_name", displayName);
account.put("username", getUsername());
account.put("role", role);
account.put("nation_code", nation_code.startsWith("+")?nation_code:"+"+nation_code);
if (contactEmail != null){
account.put("contact_email", contactEmail);
}
if (contactPhone != null){
account.put("contact_phone", contactPhone);
}
@ -80,4 +88,20 @@ public class NewAccountBean {
public void setNation_code(String nation_code) {
this.nation_code = nation_code;
}
public String getContactEmail() {
return contactEmail;
}
public void setContactEmail(String contactEmail) {
this.contactEmail = contactEmail;
}
public int getClientId() {
return clientId;
}
public void setClientId(int clientId) {
this.clientId = clientId;
}
}

@ -416,4 +416,16 @@ public interface ClientManager {
void partnerCBChannelConfig(String clientMoniker, String channelKey, String channel_id);
void addDevice(JSONObject manager, String clientMoniker, JSONObject device);
/**
* 退
*/
void verifyRefundPassword(JSONObject account, JSONObject json);
/**
* 退
*/
void resetRefundPassword(JSONObject account, JSONObject json);
void resetRefundPasswordByManage(String clientMoniker,JSONObject manage, JSONObject json);
}

@ -1351,7 +1351,11 @@ public class ClientManagerImpl implements ClientManager, ManagerTodoNoticeProvid
throw new InvalidShortIdException();
}
checkOrgPermission(manager, client);
if(!client.containsKey("parent_client_id") && client.getBoolean("sub_manage")){
return clientAccountMapper.partnerAndSubPartnerAccounts(client.getIntValue("client_id"));
}
return clientAccountMapper.listPartnerAccounts(client.getIntValue("client_id"));
}
@Override
@ -1370,7 +1374,7 @@ public class ClientManagerImpl implements ClientManager, ManagerTodoNoticeProvid
accountJson.put("salt", salt);
accountJson.put("password_hash", PasswordUtils.hashPwd(account.getPwd(), salt));
accountJson.put("password_aes", PasswordUtils.encryptAESPwd(account.getPwd()));
accountJson.put("client_id", client.getIntValue("client_id"));
accountJson.put("client_id", account.getClientId()==0?client.getIntValue("client_id"):account.getClientId());
accountJson.put("creator", managerType == 1 ? manager.getString("manager_id") : manager.getString("account_id"));
accountJson.put("creator_type", managerType);
accountJson.put("create_time", new Date());
@ -1401,8 +1405,14 @@ public class ClientManagerImpl implements ClientManager, ManagerTodoNoticeProvid
if (clientMoniker != null) {
JSONObject client = getClientInfoByMoniker(clientMoniker);
Assert.notNull(client);
//父商户全局管理子商户时候,跳过
if (account.getIntValue("client_id") != client.getIntValue("client_id")) {
throw new BadRequestException("error.partner.valid.account_not_match");
//登录用户所属商户
JSONObject clientLogin = getClientInfo(account.getIntValue("client_id"));
if(!(client.getBoolean("sub_manage") &&
clientLogin.containsKey("parent_client_id")?clientLogin.getIntValue("parent_client_id")==client.getIntValue("client_id"):false)){
throw new BadRequestException("error.partner.valid.account_not_match");
}
}
checkOrgPermission(manager, client);
}
@ -2200,6 +2210,57 @@ public class ClientManagerImpl implements ClientManager, ManagerTodoNoticeProvid
clientDeviceMapper.save(newDevice);
}
@Override
public void verifyRefundPassword(JSONObject account, JSONObject json) {
JSONObject clientConfig = clientConfigMapper.find(account.getIntValue("client_id"));
String needVerifyPassword = json.getString("refund_password");
String refundPwdSalt = clientConfig.getString("refund_pwd_salt");
if (!StringUtils.equals(clientConfig.getString("refund_pwd"), PasswordUtils.hashPwd(needVerifyPassword, refundPwdSalt))) {
throw new BadRequestException("Incorrect refund password");
}
}
@Override
public void resetRefundPassword(JSONObject account, JSONObject json) {
if (PartnerRole.getRole(account.getIntValue("role")) != PartnerRole.ADMIN) {
throw new BadRequestException("You have no permission");
}
verifyRefundPassword(account, json);
String newSalt = PasswordUtils.newSalt();
String newPassWord = json.getString("new_refund_password");
if (!StringUtils.isNumeric(newPassWord)) {
throw new BadRequestException("Refund password must be pure number");
}
String newPwdHash = PasswordUtils.hashPwd(newPassWord, newSalt);
if (StringUtils.equals(newPwdHash, PasswordUtils.hashPwd(json.getString("refund_password"), newSalt))) {
throw new BadRequestException("Old and new passwords cannot be duplicated");
}
JSONObject update = new JSONObject();
update.put("client_id", account.getIntValue("client_id"));
update.put("refund_pwd", newPwdHash);
update.put("refund_pwd_salt", newSalt);
clientConfigMapper.update(update);
}
@Override
public void resetRefundPasswordByManage(String clientMoniker,JSONObject manage, JSONObject json) {
JSONObject client = getClientInfoByMoniker(clientMoniker);
if (client == null) {
throw new InvalidShortIdException();
}
JSONObject update = new JSONObject();
update.put("client_id", client.getIntValue("client_id"));
String newPassWord = json.getString("new_refund_password");
if (!StringUtils.isNumeric(newPassWord)) {
throw new BadRequestException("Refund password must be pure number");
}
String newSalt = PasswordUtils.newSalt();
String newPwdHash = PasswordUtils.hashPwd(newPassWord, newSalt);
update.put("refund_pwd", newPwdHash);
update.put("refund_pwd_salt", newSalt);
clientConfigMapper.update(update);
}
@Override
public void updateDevie(JSONObject manager, String clientMoniker, String devId, String remark) {
JSONObject client = getClientInfoByMoniker(clientMoniker);

@ -272,6 +272,17 @@ public class PartnerManageController {
clientManager.switchPermission(manager, clientMoniker, "common_sub_merchant_id", pass.getBooleanValue("allow"));
}
/**
*
* @param clientMoniker
* @param pass
* @param manager
*/
@ManagerMapping(value = "/{clientMoniker}/sub_manage", method = RequestMethod.PUT, role = {ManagerRole.OPERATOR})
public void switchSubManage(@PathVariable String clientMoniker, @RequestBody JSONObject pass, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) {
clientManager.switchPermission(manager, clientMoniker, "sub_manage", pass.getBooleanValue("allow"));
}
@ManagerMapping(value = "/{clientMoniker}/channels/{channel}/permission", method = RequestMethod.PUT, role = {ManagerRole.SERVANT, ManagerRole.DEVELOPER})
public void switchChannelPermission(@PathVariable String clientMoniker, @PathVariable String channel, @RequestBody JSONObject pass, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) {
clientManager.switchChannelPermission(manager, clientMoniker, channel, pass.getBooleanValue("allow"));
@ -302,6 +313,12 @@ public class PartnerManageController {
clientManager.switchPermission(manager, clientMoniker, "enable_pre_refund", pass.getBooleanValue("allow"));
}
@ManagerMapping(value = "/{clientMoniker}/reset/refund_pwd", method = RequestMethod.PUT, role = {ManagerRole.OPERATOR, ManagerRole.ADMIN, ManagerRole.DEVELOPER})
public void changeRefundPwd(@PathVariable String clientMoniker, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager,@RequestBody JSONObject config) {
clientManager.resetRefundPasswordByManage(clientMoniker, manager, config);
}
@ManagerMapping(value = "/{clientMoniker}/payment_page_version", method = RequestMethod.PUT, role = {ManagerRole.OPERATOR, ManagerRole.BD_USER})
public void changePaymentPage(@PathVariable String clientMoniker, @RequestBody JSONObject pass, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) {
clientManager.changePaymentPage(manager, clientMoniker, pass.getString("paypad_version"));

@ -283,6 +283,12 @@ public class PartnerViewController {
clientManager.updateRefundPwd(account, req.getString("pwd"));
}
@PartnerMapping(value = "/refund_pwd_new", method = RequestMethod.PUT, roles = {PartnerRole.ADMIN})
@ResponseBody
public void updateRefundPwdNew(@ModelAttribute(CommonConsts.PARTNER_STATUS) JSONObject account, @RequestBody JSONObject req) {
clientManager.resetRefundPassword(account, req);
}
@PartnerMapping(value = "/trade_logs", method = RequestMethod.GET)
@ResponseBody
public JSONObject listTradeLogs(@ModelAttribute(CommonConsts.PARTNER_STATUS) JSONObject account, TradeLogQuery query) throws Exception {

@ -27,4 +27,6 @@ public interface ManagerAccountsService {
JSONObject getBDConfig(String bd_id);
List<JSONObject> listServants(JSONObject loginManager);
}
void resetPwd(JSONObject account,String password);
}

@ -3,6 +3,7 @@ package au.com.royalpay.payment.manage.signin.core;
import au.com.royalpay.payment.manage.signin.beans.ChangePwdBean;
import au.com.royalpay.payment.manage.signin.beans.LoginInfo;
import com.alibaba.fastjson.JSONObject;
import org.springframework.web.servlet.ModelAndView;
/**
* Created by yixian on 2016-06-29.
@ -15,6 +16,10 @@ public interface SignInAccountService {
JSONObject getClient(String accountId);
JSONObject getClientByUsername(String username);
JSONObject getManagerByUsername(String username);
void clearAccountCache(String accountId);
JSONObject managerLoginCheck(LoginInfo loginInfo);
@ -40,4 +45,16 @@ public interface SignInAccountService {
String ForgetPassword(String partner_code) throws Exception;
void changePasswordByEmail(String codeValue, String login_id, String newPassword);
void getClientResetPwdCode(JSONObject account,String type);
void getManagerResetPwdCode(JSONObject account,String type);
void verifyClientCaptcha(JSONObject account, String captcha);
void verifyManagerCaptcha(JSONObject account, String captcha);
void deleteClientCodeKey(String codekey);
void deleteManagerCodeKey(String codekey);
}

@ -11,6 +11,7 @@ import au.com.royalpay.payment.tools.exceptions.BadRequestException;
import au.com.royalpay.payment.tools.exceptions.NotFoundException;
import au.com.royalpay.payment.tools.permission.enums.ManagerRole;
import au.com.royalpay.payment.tools.utils.PasswordUtils;
import com.alibaba.fastjson.JSONObject;
import com.github.miemiedev.mybatis.paginator.domain.Order;
import com.github.miemiedev.mybatis.paginator.domain.PageBounds;
@ -149,6 +150,15 @@ public class ManagerAccountServiceImpl implements ManagerAccountsService {
return managerMapper.listServants(ManagerRole.SERVANT.getMask());
}
@Override
public void resetPwd(JSONObject account, String password) {
String salt = PasswordUtils.newSalt();
account.put("salt", salt);
account.put("password_hash", PasswordUtils.hashPwd(password, salt));
managerMapper.update(account);
signInAccountService.clearManager(account.getString("manager_id"));
}
private void checkOrg(JSONObject loginManager,JSONObject manager){
if (loginManager.getInteger("org_id")!=null){
List<JSONObject> orgs = orgMapper.listOrgAndChild(loginManager.getIntValue("org_id"));

@ -1,5 +1,6 @@
package au.com.royalpay.payment.manage.signin.core.impls;
import au.com.royalpay.payment.core.exceptions.EmailException;
import au.com.royalpay.payment.core.exceptions.InvalidShortIdException;
import au.com.royalpay.payment.manage.device.core.DeviceManager;
import au.com.royalpay.payment.manage.management.sysconfig.core.PermissionManager;
@ -17,26 +18,33 @@ import au.com.royalpay.payment.manage.signin.core.SignInAccountService;
import au.com.royalpay.payment.manage.signin.core.SignInStatusManager;
import au.com.royalpay.payment.manage.signin.events.ClientLoginEvent;
import au.com.royalpay.payment.manage.signin.events.ManagerLoginEvent;
import au.com.royalpay.payment.manage.support.sms.SmsSender;
import au.com.royalpay.payment.manage.system.core.PermissionClientModulesService;
import au.com.royalpay.payment.tools.env.PlatformEnvironment;
import au.com.royalpay.payment.tools.env.RequestEnvironment;
import au.com.royalpay.payment.tools.exceptions.BadRequestException;
import au.com.royalpay.payment.tools.exceptions.ForbiddenException;
import au.com.royalpay.payment.tools.exceptions.ServerErrorException;
import au.com.royalpay.payment.tools.locale.LocaleSupport;
import au.com.royalpay.payment.tools.permission.enums.ManagerRole;
import au.com.royalpay.payment.tools.threadpool.RoyalThreadPoolExecutor;
import au.com.royalpay.payment.tools.utils.PasswordUtils;
import com.alibaba.fastjson.JSONObject;
import com.sun.xml.internal.bind.v2.TODO;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.web.servlet.ModelAndView;
import org.thymeleaf.context.Context;
import org.thymeleaf.spring4.SpringTemplateEngine;
@ -44,6 +52,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
@ -79,6 +88,15 @@ public class SignInAccountServiceImpl implements SignInAccountService, Applicati
private SysCustomerServiceMapper sysCustomerServiceMapper;
@Resource
private PermissionClientModulesService permissionClientModulesService;
@Resource
private RoyalThreadPoolExecutor royalThreadPoolExecutor;
@Resource
private StringRedisTemplate stringRedisTemplate;
@Resource
private SmsSender smsSender;
private final String RESET_CLIENT_ACCOUNT_PREFIX = "RESET_CLIENT_ACCOUNT";
private final String RESET_MANAGER_ACCOUNT_PREFIX = "RESET_MANAGER_ACCOUNT";
private final int RESET_PASSWORD_TEMPLID = 126978;
private ApplicationEventPublisher publisher;
private static final List<String> tags = new ArrayList<>();
@ -172,6 +190,20 @@ public class SignInAccountServiceImpl implements SignInAccountService, Applicati
return account;
}
@Override
public JSONObject getClientByUsername(String username) {
JSONObject account = clientAccountMapper.findByUsername(username);
Assert.notNull(account, "Username is not exists!");
return account;
}
@Override
public JSONObject getManagerByUsername(String username) {
JSONObject account = managerMapper.findAvailableByLoginId(username);
Assert.notNull(account, "Username is not exists!");
return account;
}
@Override
@CacheEvict(value = ":login:clients:", key = "''+#accountId")
public void clearAccountCache(String accountId) {
@ -454,4 +486,145 @@ public class SignInAccountServiceImpl implements SignInAccountService, Applicati
account.put("is_password_expired", 0);
clientAccountMapper.update(account);
}
@Override
public void getClientResetPwdCode(JSONObject account,String type) {
if(StringUtils.equals(type,"email") && !account.containsKey("contact_email")){
throw new BadRequestException("Your account is not bound to your mailbox!");
}
if(StringUtils.equals(type,"phone") && !account.containsKey("contact_phone") && !account.containsKey("nation_code")){
throw new BadRequestException("Your account is not bound to your phone!");
}
String accountId = account.getString("account_id");
String codeKeyValueRedis = stringRedisTemplate.boundValueOps(getResetClientAccountKey(accountId)).get();
if(StringUtils.isNotEmpty(codeKeyValueRedis)){
throw new BadRequestException("Captcha has been sent.Please check your "+type+" or try again in 5 minutes.");
}
String codeKeyValue = RandomStringUtils.random(6, false, true);
switch(type){
case "email":
Context ctx = new Context();
ctx.setVariable("account",account);
ctx.setVariable("captcha",codeKeyValue);
final String content = thymeleaf.process("mail/account_reset_email.html", ctx);
royalThreadPoolExecutor.execute(() -> {
try {
mailService.sendEmail("Reset your password", account.getString("contact_email"),
"", content);
} catch (Exception e) {
throw new EmailException("Email Sending Failed", e);
}
});
break;
case "phone":
ArrayList<String> param = new ArrayList<>();
param.add("密码重置服务");
param.add(codeKeyValue);
String expireMin = "5";
param.add(expireMin);
try {
smsSender.getSender().sendWithParam(account.getString("nation_code").trim(), account.getString("contact_phone"), RESET_PASSWORD_TEMPLID, param, "RoyalPay", "", "");
} catch (Exception e) {
e.printStackTrace();
throw new ServerErrorException("Phone number is wrong.Please try again.");
}
break;
}
stringRedisTemplate.boundValueOps(getResetClientAccountKey(accountId)).set(codeKeyValue,5, TimeUnit.MINUTES);
}
@Override
public void getManagerResetPwdCode(JSONObject account, String type) {
if(StringUtils.equals(type,"email") && !account.containsKey("email")){
throw new BadRequestException("Your account is not bound to your mailbox!");
}
if(StringUtils.equals(type,"phone") && !account.containsKey("phone") && !account.containsKey("nation_code")){
throw new BadRequestException("Your account is not bound to your phone!");
}
String managerId = account.getString("manager_id");
String codeKeyValueRedis = stringRedisTemplate.boundValueOps(getResetManagerAccountKey(managerId)).get();
if(StringUtils.isNotEmpty(codeKeyValueRedis)){
throw new BadRequestException("Captcha has been sent.Please check your "+type+" or try again in 5 minutes.");
}
String codeKeyValue = RandomStringUtils.random(6, false, true);
switch(type){
case "email":
Context ctx = new Context();
ctx.setVariable("account",account);
ctx.setVariable("captcha",codeKeyValue);
final String content = thymeleaf.process("mail/account_reset_email.html", ctx);
royalThreadPoolExecutor.execute(() -> {
try {
mailService.sendEmail("Reset your password", account.getString("email"),
"", content);
} catch (Exception e) {
throw new EmailException("Email Sending Failed", e);
}
});
break;
case "phone":
ArrayList<String> param = new ArrayList<>();
param.add("密码重置服务");
param.add(codeKeyValue);
String expireMin = "5";
param.add(expireMin);
try {
smsSender.getSender().sendWithParam(account.getString("nation_code").trim(), account.getString("phone"), RESET_PASSWORD_TEMPLID, param, "RoyalPay", "", "");
} catch (Exception e) {
e.printStackTrace();
throw new ServerErrorException("Phone number is wrong.Please try again.");
}
break;
}
stringRedisTemplate.boundValueOps(getResetManagerAccountKey(managerId)).set(codeKeyValue,5, TimeUnit.MINUTES);
}
@Override
public void verifyClientCaptcha(JSONObject account, String captcha) {
String captchaRedis = stringRedisTemplate.boundValueOps(getResetClientAccountKey(account.getString("account_id"))).get();
if(StringUtils.isBlank(captchaRedis)){
throw new BadRequestException("Captcha has expired");
}
if(StringUtils.equals(captcha,captchaRedis)){
throw new BadRequestException("Captcha is wrong");
}
}
@Override
public void verifyManagerCaptcha(JSONObject account, String captcha) {
String captchaRedis = stringRedisTemplate.boundValueOps(getResetManagerAccountKey(account.getString("manager_id"))).get();
if(StringUtils.isBlank(captchaRedis)){
throw new BadRequestException("Captcha has expired");
}
if(StringUtils.equals(captcha,captchaRedis)){
throw new BadRequestException("Captcha is wrong");
}
}
@Override
public void deleteClientCodeKey(String codekey) {
deleteClientAccountKey(codekey);
}
@Override
public void deleteManagerCodeKey(String codekey) {
deleteManagerAccountKey(codekey);
}
private void deleteClientAccountKey(String codeKey){
stringRedisTemplate.delete(getResetClientAccountKey(codeKey));
}
private void deleteManagerAccountKey(String codeKey){
stringRedisTemplate.delete(getResetManagerAccountKey(codeKey));
}
private String getResetClientAccountKey(String codeKey){
return RESET_CLIENT_ACCOUNT_PREFIX + codeKey;
}
private String getResetManagerAccountKey(String codeKey){
return RESET_MANAGER_ACCOUNT_PREFIX + codeKey;
}
}

@ -1,5 +1,7 @@
package au.com.royalpay.payment.manage.signin.web;
import au.com.royalpay.payment.manage.merchants.core.ClientManager;
import au.com.royalpay.payment.manage.signin.core.*;
import au.com.royalpay.payment.tools.permission.consumer.ConsumersAction;
import com.google.code.kaptcha.Producer;
@ -10,11 +12,6 @@ import au.com.royalpay.payment.manage.signin.beans.ChangePwdBean;
import au.com.royalpay.payment.manage.signin.beans.FindPwdBean;
import au.com.royalpay.payment.manage.signin.beans.LoginInfo;
import au.com.royalpay.payment.manage.signin.beans.TodoNotice;
import au.com.royalpay.payment.manage.signin.core.ClientLoginLogRepository;
import au.com.royalpay.payment.manage.signin.core.ManagerLoginLogRepository;
import au.com.royalpay.payment.manage.signin.core.ManagerTodoNoticeProvider;
import au.com.royalpay.payment.manage.signin.core.SignInAccountService;
import au.com.royalpay.payment.manage.signin.core.SignInStatusManager;
import au.com.royalpay.payment.tools.CommonConsts;
import au.com.royalpay.payment.tools.connections.mpsupport.MpWechatApi;
import au.com.royalpay.payment.tools.connections.mpsupport.MpWechatApiProvider;
@ -69,6 +66,11 @@ public class SignInController {
private Producer captchaProducer;
@Resource
private ManagerTodoNoticeProvider[] managerTodoNoticeProviders;
@Resource
private ClientManager clientManager;
@Resource
private ManagerAccountsService managerAccountsService;
@Resource
private MpWechatApiProvider mpWechatApiProvider;
@ -371,4 +373,52 @@ public class SignInController {
HttpUtils.setCookie(response, "CustomerID", statusKey,false);
return result;
}
/**
*
* @param username
* @param type emailphone
*/
@RequestMapping(value = "/client/reset_pwd/{type}/{username}", method = RequestMethod.PUT)
public void resetMerchantPwd(@PathVariable("username") String username,@PathVariable("type") String type) {
JSONObject account = signInAccountService.getClientByUsername(username);
signInAccountService.getClientResetPwdCode(account,type);
}
/**
*
* @param info
*/
@RequestMapping(value = "/client/reset_pwd", method = RequestMethod.PUT)
public void resetClientPwd(@RequestBody LoginInfo info) {
JSONObject account = signInAccountService.getClientByUsername(info.getLoginId());
signInAccountService.verifyClientCaptcha(account, info.getVerifyCode());
clientManager.resetAccountPwd(null, null, account.getString("account_id"), info.getPassword());
signInAccountService.deleteClientCodeKey(account.getString("account_id"));
}
/**
*
* @param username
* @param type emailphone
*/
@RequestMapping(value = "/manager/reset_pwd/{type}/{username}", method = RequestMethod.PUT)
public void resetManagerPwd(@PathVariable("username") String username,@PathVariable("type") String type) {
JSONObject account = signInAccountService.getManagerByUsername(username);
signInAccountService.getClientResetPwdCode(account,type);
}
/**
*
* @param info
*/
@RequestMapping(value = "/manager/reset_pwd", method = RequestMethod.PUT)
public void resetManagerPwd(@RequestBody LoginInfo info) {
JSONObject account = signInAccountService.getManagerByUsername(info.getLoginId());
signInAccountService.verifyManagerCaptcha(account, info.getVerifyCode());
managerAccountsService.resetPwd(account, info.getPassword());
signInAccountService.deleteManagerCodeKey(account.getString("manager_id"));
}
}

@ -76,8 +76,16 @@ public class RefundServiceImpl implements RefundService, ApplicationEventPublish
public JSONObject checkOrderRefundAmount(String orderId, JSONObject account) {
JSONObject order = orderMapper.getOrderDetail(orderId);
if (account != null) {
JSONObject client = clientMapper.findClient(account.getIntValue("client_id"));
////父商户全局管理子商户时候,跳过
if (account.getIntValue("client_id") != order.getIntValue("client_id")) {
throw new ForbiddenException("Order is not belong to your shop/merchant");
JSONObject clientOrder = clientMapper.findClient(order.getIntValue("client_id"));
if(!(client.getBoolean("sub_manage") &&
clientOrder.containsKey("parent_client_id")?clientOrder.getIntValue("parent_client_id")==client.getIntValue("client_id"):false)){
throw new ForbiddenException("Order is not belong to your shop/merchant");
}
}
}
Assert.notNull(order, "Order Not Exists");

@ -18,9 +18,10 @@
</where>
</select>
<select id="partnerAndSubPartnerAccounts" resultType="com.alibaba.fastjson.JSONObject">
SELECT sc.client_moniker, sa.account_id, sa.role, sa.username
SELECT sc.client_moniker,sc.short_name,sc.client_id,sc.parent_client_id, sa.account_id, sa.role, sa.username,sa.contact_phone,sa.contact_email,sa.nation_code,sa.wechat_name,sa.wechat_openid,sa.wxapp_openid,
sa.wx_unionid,sa.wechat_headimg,sa.payment_notice,sa.refund_authorised,sa.display_name
FROM sys_clients sc
INNER JOIN sys_accounts sa ON sc.client_id = sa.client_id AND sa.is_valid = 1
WHERE sc.client_id = #{client_id} OR sc.parent_client_id = #{client_id} AND sc.is_valid = 1
</select>
</mapper>
</mapper>

@ -0,0 +1,31 @@
<html xmlns:th="http://www.thymeleaf.org" lang="zh">
<b>Dear <span th:text="${account.display_name}"></span> :</b>
<p>
Your account(<span th:text="${account.username}"></span>) is in the process of binding a mailbox, the verification code is <u th:text="${captcha}"></u>,valid within 5 minutes.
</p>
<b>尊敬的<span th:text="${account.display_name}"></span>,您好:</b>
<p>
您的账户(<span th:text="${account.username}"></span>)正在进行绑定邮箱的操作,验证码是<u th:text="${captcha}"></u>5分钟内有效。
</p>
<hr>
<h4>Best Regards</h4>
<p>
<img style="width: 120px;height: 120px"
src="https://mpay.royalpay.com.au/static/images/logo_new.jpg"> <br>
Contact Us<br>
Email:<br>
<a href="mailto:info@royalpay.com.au">info@royalpay.com.au</a> <br>
Tel:<br>
1300 10 77 50<br>
<br>
Service WeChat Account:<br>
<img src="https://mpay.royalpay.com.au/static/images/customer_service.jpg"
style="width: 60px"><br>
Level 14, 383 Kent Street, Sydney NSW 2000<br>
<br>
Level 11, 15 William Street, Melbourne VIC 3000
</p>
<p>Tunnel Show Pty Ltd trading as RoyalPay<br>
Representative of AFSL licensee 448066
</p>
</html>

@ -0,0 +1,34 @@
<html xmlns:th="http://www.thymeleaf.org" lang="zh">
<b>Dear <span th:text="${account.display_name}"></span> :</b>
<p>
You are requesting a password reset service with a verification code of <u th:text="${captcha}"></u>, valid for 5 minutes. Please do not provide this verification code to anyone.
</p>
<p>
<a th:href="${url}">Reset Password ></a>
</p>
<b>尊敬的<span th:text="${account.display_name}"></span>,您好:</b>
<p>
您正在申请密码重置服务,验证码为<u th:text="${captcha}"></u>5分钟内有效请勿向任何人提供此验证码。
</p>
<hr>
<h4>Best Regards</h4>
<p>
<img style="width: 120px;height: 120px"
src="https://mpay.royalpay.com.au/static/images/logo_new.jpg"> <br>
Contact Us<br>
Email:<br>
<a href="mailto:info@royalpay.com.au">info@royalpay.com.au</a> <br>
Tel:<br>
1300 10 77 50<br>
<br>
Service WeChat Account:<br>
<img src="https://mpay.royalpay.com.au/static/images/customer_service.jpg"
style="width: 60px"><br>
Level 14, 383 Kent Street, Sydney NSW 2000<br>
<br>
Level 11, 15 William Street, Melbourne VIC 3000
</p>
<p>Tunnel Show Pty Ltd trading as RoyalPay<br>
Representative of AFSL licensee 448066
</p>
</html>

@ -1003,7 +1003,7 @@ margin-bottom: 10%;"/>
<!--&lt;!&ndash;<i class="fa fa-file-image-o"></i> &ndash;&gt;Marketing Materials-->
<!--</a>-->
<!--</li>-->
<li ng-if="(currentUser.client.client_id!=9 && currentUser.client.parent_client_id!=9)&&([1]|withRole)">
<li ng-if="([1]|withRole)">
<a ui-sref="accounts">
<!--<i class="fa fa-users"></i> -->Accounts
</a>

@ -13,10 +13,16 @@ define(['angular', 'uiRouter', 'uiBootstrap'], function (angular) {
$stateProvider.state('accounts', {
url: '/accounts',
templateUrl: '/static/payment/partner/templates/client_accounts.html',
controller: 'clientAccountsCtrl'
controller: 'clientAccountsCtrl',
resolve: {
partner: ['$http', function ($http) {
return $http.get('/client/partner_info');
}]
}
})
}]);
app.controller('clientAccountsCtrl', ['$scope', '$http', '$uibModal', 'commonDialog', function ($scope, $http, $uibModal, commonDialog) {
app.controller('clientAccountsCtrl', ['$scope', '$http', '$uibModal', 'commonDialog','partner', function ($scope, $http, $uibModal, commonDialog,partner) {
$scope.partner = partner.data;
$scope.loadAccounts = function () {
$http.get('/client/partner_info/accounts').then(function (resp) {
$scope.accounts = resp.data;
@ -28,7 +34,12 @@ define(['angular', 'uiRouter', 'uiBootstrap'], function (angular) {
$uibModal.open({
templateUrl: '/static/payment/partner/templates/add_partner_account_dialog.html',
controller: 'clientAddAccountCtrl',
backdrop: false
backdrop: false,
resolve: {
partner: ['$http', function ($http) {
return $http.get('/client/partner_info');
}]
}
}).result.then(function () {
$scope.loadAccounts();
})
@ -91,8 +102,16 @@ define(['angular', 'uiRouter', 'uiBootstrap'], function (angular) {
});
};
}]);
app.controller('clientAddAccountCtrl', ['$scope', '$http', function ($scope, $http) {
app.controller('clientAddAccountCtrl', ['$scope', '$http','partner', function ($scope, $http, partner) {
$scope.loadSubPartners = function () {
$http.get('/client/partner_info/sub_partners').then(function (resp) {
$scope.subPartners = resp.data;
})
};
$scope.partner = partner.data;
$scope.loadSubPartners();
$scope.account = {role: 3};
$scope.account.nation_code = 61;
$scope.partnerRoles = partnerRoles;
$scope.saveAccount = function (form) {
if (form.$invalid) {
@ -122,4 +141,4 @@ define(['angular', 'uiRouter', 'uiBootstrap'], function (angular) {
}
}]);
return app;
});
});

@ -1428,6 +1428,7 @@ define(['angular', 'decimal', 'static/commons/commons', 'uiBootstrap', 'uiRouter
$scope.ctrl.editAliSubMerchant = false;
$scope.ctrl.editMaxOrderAmount = false;
$scope.ctrl.editOrderExpiryConfig = false;
$scope.ctrl.editRefundPwd = false;
})
};
$scope.qrConfig = {currency: 'AUD'};
@ -1500,6 +1501,13 @@ define(['angular', 'decimal', 'static/commons/commons', 'uiBootstrap', 'uiRouter
})
};
$scope.resetRefundPwd = function (config) {
$http.put('/sys/partners/' + $scope.partner.client_moniker + '/reset/refund_pwd', {new_refund_password: config}).then(function () {
$scope.loadPartnerPaymentInfo();
}, function (resp) {
commonDialog.alert({title: 'Error', content: resp.data.message, type: 'error'});
})
};
$scope.updateClientQRCodePaySurCharge = function () {
if (!$scope.paymentInfo) {
@ -1671,6 +1679,26 @@ define(['angular', 'decimal', 'static/commons/commons', 'uiBootstrap', 'uiRouter
})
})
};
$scope.switchSubManage = function () {
if (!$scope.paymentInfo) {
return;
}
if (!$scope.init.sub_manage) {
$scope.init.sub_manage = true;
return;
}
$http.put('/sys/partners/' + $scope.partner.client_moniker + '/sub_manage', {allow: $scope.paymentInfo.sub_manage}).then(function () {
$scope.loadPartnerPaymentInfo();
}, function (resp) {
commonDialog.alert({
title: 'Failed to change Sub Partners Manage status',
content: resp.data.message,
type: 'error'
})
})
};
var info = [];
$scope.decideCompliance = function (name) {
var keywords = ['education','financial' ,'train','immigrant','invest',

@ -344,6 +344,16 @@ define(['angular', 'decimal', 'uiRouter', 'ngBootSwitch', 'ngFileUpload','uiBoot
};
}]);
app.controller('clientResetRefundPwdDialogCtrl', ['$scope', '$http', function ($scope, $http) {
$scope.updateRefundPwd = function (refundPwd) {
$scope.errmsg = null;
$http.put('/client/partner_info/refund_pwd_new', refundPwd).then(function () {
$scope.$close();
}, function (resp) {
$scope.errmsg = resp.data.message;
})
}
}]);
app.controller('clientComplianceFilesCtrl', ['$scope', '$http', '$rootScope', 'commonDialog', '$state', 'Upload', 'file', function ($scope, $http, $rootScope, commonDialog, $state, Upload, file) {
$scope.file = file.data || {};
@ -551,7 +561,7 @@ define(['angular', 'decimal', 'uiRouter', 'ngBootSwitch', 'ngFileUpload','uiBoot
};
}]);
app.controller('clientPaymentInfoCtrl', ['$scope', '$http', '$state', 'commonDialog', function ($scope, $http, $state, commonDialog) {
app.controller('clientPaymentInfoCtrl', ['$scope', '$http', '$state', 'commonDialog','$uibModal', function ($scope, $http, $state, commonDialog, $uibModal) {
$scope.paymentInfo = $scope.partner;
$scope.old_customer_surcharge_rate = angular.copy($scope.partner.customer_surcharge_rate);
$scope.qrConfig = {currency: 'AUD'};
@ -567,6 +577,22 @@ define(['angular', 'decimal', 'uiRouter', 'ngBootSwitch', 'ngFileUpload','uiBoot
}
};
$scope.resetRefundPwd = function (account) {
$uibModal.open({
templateUrl: '/static/payment/partner/templates/partner_reset_refund_pwd_dialog.html',
controller: 'clientResetRefundPwdDialogCtrl',
backdrop: false,
size: 'sm',
resolve: {
account: function () {
return account;
}
}
}).result.then(function () {
commonDialog.alert({title: 'Success!', content: 'Refund Password Changed Successfully', type: 'success'})
})
};
$scope.clientCopyCBBannkPayLink = function() {
var e=document.getElementById("c-cpcbbankpay");
e.select();

@ -36,14 +36,59 @@
<p class="small text-danger" ng-message="required">password is required</p>
</div>
</div>
<div class="form-group"
ng-class="{'has-error':newAccountForm.contact_phone.$invalid && newAccountForm.contact_phone.$dirty}">
<label class="control-label" for="contact_phone">Contact Phone *</label>
<div class="">
<div class="col-md-4">
<div class="input-group">
<div class="input-group-addon">+</div>
<input class="form-control" required type="text"
ng-model="account.nation_code"
name="nation_code" id="nation_code"
maxlength="3" minlength="1"
placeholder="country code" value="61">
</div>
<div ng-messages="newAccountForm.nation_code.$error"
ng-if="newAccountForm.nation_code.$dirty">
<p class="small text-danger" ng-message="required">Required
Field</p>
<p class="small text-danger" ng-message="maxlength">Less
Than 3 Characters</p>
</div>
</div>
<div class="col-md-8">
<input required type="text" class="form-control" ng-model="account.contact_phone" name="contact_phone"
id="contact_phone">
<div ng-messages="newAccountForm.contact_phone.$error" ng-if="newAccountForm.contact_phone.$dirty">
<p class="small text-danger" ng-message="required">contact phone is required</p>
</div>
</div>
</div>
</div>
<div class="form-group"
ng-class="{'has-error':newAccountForm.contact_email.$invalid && newAccountForm.contact_email.$dirty}">
<label class="control-label" for="contact_email">Contact Email *</label>
<input required type="email" class="form-control" ng-model="account.contact_email" name="contact_email"
id="contact_email">
<div ng-messages="newAccountForm.contact_email.$error" ng-if="newAccountForm.contact_email.$dirty">
<p class="small text-danger" ng-message="required">contact email is required</p>
</div>
</div>
<div class="form-group">
<label class="control-label" for="role-select">Role *</label>
<select class="form-control" id="role-select" ng-model="account.role" ng-options="role.code as role.label for role in partnerRoles"></select>
</div>
<div class="alert alert-danger" ng-if="errmsg" ng-bind="errmsg"></div>
<div class="form-group" ng-if="subPartners!=null && partner.sub_manage">
<label class="control-label" for="sub-select">Sub Merchant</label>
<select class="form-control" id="sub-select" ng-model="account.client_id" ng-options="partner.client_id as partner.short_name for partner in subPartners"></select>
</div>
</form>
</div>
<div class="modal-footer">
<button class="btn btn-success" ng-click="saveAccount(newAccountForm)" type="button">Save Account</button>
<button class="btn btn-danger" ng-click="$dismiss()" type="button">Cancel</button>
</div>
</div>

@ -31,6 +31,9 @@
<th>Display Name</th>
<th>Role</th>
<th>WeChat</th>
<th>Email</th>
<th>Country Code</th>
<th>Phone</th>
<th>Payment Notice</th>
<th>Refund Approver</th>
<th>Operations</th>
@ -38,7 +41,10 @@
</thead>
<tbody>
<tr ng-repeat="account in accounts">
<td ng-bind="account.username"></td>
<td>{{account.username}}
<i class="fa fa-sitemap" ng-if="account.parent_client_id && !partner.parent_client_id"
title="{{account.short_name}}"></i>
</td>
<td ng-bind="account.display_name"></td>
<td>
<select ng-disabled="account.account_id==currentUser.account_id" ng-change="updateAccountRole(account)" ng-model="account.role" ng-options="role.code as role.label for role in partnerRoles" title="Account Role"></select>
@ -50,6 +56,9 @@
<i role="button" class="fa fa-qrcode text-primary" ng-if="!account.wechat_openid" title="Wechat Sign" ng-click="userCheckIn(account)"></i>
<i role="button" class="fa fa-remove text-danger" ng-if="account.wechat_openid" title="Unbind" ng-click="unbindWechat(account)"></i>
</td>
<td ng-bind="account.contact_email"></td>
<td ng-bind="account.nation_code"></td>
<td ng-bind="account.contact_phone"></td>
<td>
<a role="button" class="text-success" ng-click="toggleNotice(account)" ng-if="account.wechat_openid">
<i class="fa" ng-class="{'fa-check-circle-o':account.payment_notice,'fa-circle-o':!account.payment_notice}"></i>
@ -77,4 +86,4 @@
</div>
</div>
</div>
</section>
</section>

@ -385,6 +385,13 @@
switch-change="toggleRequireRemark()">
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">Reset Refund Password</label>
<div class="col-sm-10">
<a role="button" class="text-primary text-bold" ng-click="resetRefundPwd(account)"><i
class="fa fa-edit"></i></a>
</div>
</div>
</div>
</div>
</div>

@ -184,6 +184,12 @@
</div>
</div>
</div>
<div class="form-group" ng-if="('10'|withRole) && partner.parent_client_id==null">
<label class="col-sm-3 control-label">Sub Partners Manage</label>
<div class="col-xs-9">
<input type="checkbox" ng-model="paymentInfo.sub_manage" bs-switch switch-change="switchSubManage()">
</div>
</div>
</div>
</div>
</div>
@ -488,6 +494,30 @@
switch-change="togglePreRefund()">
</div>
</div>
<div class="form-group" ng-if="('100000000'|withRole)">
<label class="col-sm-2 control-label">Reset Refund Password</label>
<div class="col-sm-9">
<p ng-if="!ctrl.editRefundPwd" class="form-control-static">
<a role="button" ng-click="ctrl.editRefundPwd=true" ng-if="'01'|withRole"><i
class="fa fa-edit"></i></a>
</p>
<div class="input-group" ng-if="ctrl.editRefundPwd">
<input type="text" class="form-control" maxlength="6" ng-model="paymentInfo.new_refund_password">
<div class="input-group-btn">
<button class="btn btn-success"
ng-click="resetRefundPwd(paymentInfo.new_refund_password)">
<i class="fa fa-check"></i>
</button>
</div>
<div class="input-group-btn">
<button class="btn btn-danger" ng-click="ctrl.editRefundPwd=false">
<i class="fa fa-remove"></i>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

@ -0,0 +1,25 @@
<div class="modal-header">
<h4>Reset Refund Password</h4>
</div>
<div class="modal-body">
<form novalidate name="resetForm">
<div class="form-group">
<label class="control-label" for="reset-pwd-input">Old Password
*</label>
<input id="old-pwd-input" type="password" maxlength="6" class="form-control" ng-model="refundPwd.refund_password" name="pwd" required>
<p ng-if="resetForm.pwd.$error.required" class="text-danger small">
Required Field</p>
<label class="control-label" for="reset-pwd-input">New Password
*</label>
<input id="reset-pwd-input" type="password" class="form-control" maxlength="6" ng-model="refundPwd.new_refund_password" name="pwd" required>
<p ng-if="resetForm.pwd.$error.required" class="text-danger small">
Required Field</p>
<div class="alert alert-danger" ng-if="errmsg" ng-bind="errmsg"></div>
</div>
</form>
</div>
<div class="modal-footer">
<button class="btn btn-success" type="button" ng-click="updateRefundPwd(refundPwd)">Submit</button>
<button class="btn btn-danger" type="button" ng-click="$dismiss()">Cancel</button>
</div>

@ -361,7 +361,7 @@
ng-click="releasePreAuth(trade.order_id)" title="Release Pre-Authorization">
<i class="fa fa-unlock-alt"></i>
</a>
<a role="button" ng-if="trade.status>=5 && trade.confirm_time!=null && trade.clearing_status<2 && trade.client_id==currentUser.client_id && currentUser.client.enable_refund"
<a role="button" ng-if="trade.status>=5 && trade.confirm_time!=null && trade.clearing_status<2 && currentUser.client.enable_refund"
class="text-bold text-danger" ng-click="newPRefund(trade.order_id)"
title="Refund">
<i class="fa fa-undo"></i>

Loading…
Cancel
Save